5htp-core 0.6.0-85 → 0.6.0-87
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.6.0-
|
|
4
|
+
"version": "0.6.0-87",
|
|
5
5
|
"author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
|
|
6
6
|
"repository": "git://github.com/gaetanlegac/5htp-core.git",
|
|
7
7
|
"license": "MIT",
|
|
@@ -218,13 +218,13 @@ export default abstract class AuthService<
|
|
|
218
218
|
// Insufficient permissions
|
|
219
219
|
} else if (!user.roles.includes(role)) {
|
|
220
220
|
|
|
221
|
-
console.warn(LogPrefix, "Refusé: " + role + " pour " + user.name + " (" + (user.roles || 'role inconnu') + ")");
|
|
221
|
+
this.config.debug && console.warn(LogPrefix, "Refusé: " + role + " pour " + user.name + " (" + (user.roles || 'role inconnu') + ")");
|
|
222
222
|
|
|
223
223
|
throw new Forbidden("You do not have sufficient permissions to access this resource.");
|
|
224
224
|
|
|
225
225
|
} else {
|
|
226
226
|
|
|
227
|
-
console.warn(LogPrefix, "Autorisé " + role + " pour " + user.name + " (" + user.roles + ")");
|
|
227
|
+
this.config.debug && console.warn(LogPrefix, "Autorisé " + role + " pour " + user.name + " (" + user.roles + ")");
|
|
228
228
|
|
|
229
229
|
}
|
|
230
230
|
|
|
@@ -21,7 +21,6 @@ import type { GlobImportedWithMetas } from 'babel-plugin-glob-import';
|
|
|
21
21
|
// Core
|
|
22
22
|
import type { Application } from '@server/app';
|
|
23
23
|
import Service, { AnyService, TServiceArgs } from '@server/app/service';
|
|
24
|
-
import type { TRegisteredServicesIndex } from '@server/app/service/container';
|
|
25
24
|
import context from '@server/context';
|
|
26
25
|
import type DisksManager from '@server/services/disks';
|
|
27
26
|
import { CoreError, NotFound, toJson as errorToJson } from '@common/errors';
|
|
@@ -173,6 +172,33 @@ export default class ServerRouter
|
|
|
173
172
|
// Start HTTP server
|
|
174
173
|
await this.http.start();
|
|
175
174
|
|
|
175
|
+
|
|
176
|
+
// override
|
|
177
|
+
const originalLog = console.log;
|
|
178
|
+
console.log = (...args: any[]) => {
|
|
179
|
+
|
|
180
|
+
// parse stack trace: skip this function and the console.log call
|
|
181
|
+
/*const stackLine = (new Error()).stack?.split('\n')[2] || '';
|
|
182
|
+
const match = stackLine.match(/at (\w+)\.(\w+) /);
|
|
183
|
+
const className = match ? match[1] : '<global>';
|
|
184
|
+
const methodName = match ? match[2] : '<anonymous>';*/
|
|
185
|
+
|
|
186
|
+
const contextData = context.getStore() || {
|
|
187
|
+
channelType: 'master',
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const requestPrefix = contextData.channelType === 'request'
|
|
191
|
+
? `[${contextData.user ? contextData.user : 'guest'}] ${contextData.method} ${contextData.path} |`
|
|
192
|
+
: 'master';
|
|
193
|
+
|
|
194
|
+
// prefix and forward
|
|
195
|
+
originalLog.call(
|
|
196
|
+
console,
|
|
197
|
+
`${requestPrefix}`, // ${className}.${methodName}
|
|
198
|
+
...args
|
|
199
|
+
);
|
|
200
|
+
};
|
|
201
|
+
|
|
176
202
|
}
|
|
177
203
|
|
|
178
204
|
public async shutdown() {
|
|
@@ -410,39 +436,34 @@ export default class ServerRouter
|
|
|
410
436
|
this
|
|
411
437
|
);
|
|
412
438
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
let response: ServerResponse<this>;
|
|
417
|
-
try {
|
|
439
|
+
let response: ServerResponse<this>;
|
|
440
|
+
try {
|
|
418
441
|
|
|
419
|
-
|
|
420
|
-
|
|
442
|
+
// Hook
|
|
443
|
+
await this.runHook('request', request);
|
|
421
444
|
|
|
422
|
-
|
|
423
|
-
|
|
445
|
+
// Bulk API Requests
|
|
446
|
+
if (request.path === '/api' && typeof request.data.fetchers === "object") {
|
|
424
447
|
|
|
425
|
-
|
|
448
|
+
return await this.resolveApiBatch(request.data.fetchers, request);
|
|
426
449
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
}
|
|
430
|
-
} catch (e) {
|
|
431
|
-
response = await this.handleError(e, request);
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
if (!res.headersSent) {
|
|
435
|
-
// Status
|
|
436
|
-
res.status(response.statusCode);
|
|
437
|
-
// Headers
|
|
438
|
-
res.header(response.headers);
|
|
439
|
-
// Data
|
|
440
|
-
res.send(response.data);
|
|
441
|
-
} else if (response.data !== 'true') {
|
|
442
|
-
throw new Error("Can't return data from the controller since response has already been sent via express.");
|
|
450
|
+
} else {
|
|
451
|
+
response = await this.resolve(request);
|
|
443
452
|
}
|
|
453
|
+
} catch (e) {
|
|
454
|
+
response = await this.handleError(e, request);
|
|
455
|
+
}
|
|
444
456
|
|
|
445
|
-
|
|
457
|
+
if (!res.headersSent) {
|
|
458
|
+
// Status
|
|
459
|
+
res.status(response.statusCode);
|
|
460
|
+
// Headers
|
|
461
|
+
res.header(response.headers);
|
|
462
|
+
// Data
|
|
463
|
+
res.send(response.data);
|
|
464
|
+
} else if (response.data !== 'true') {
|
|
465
|
+
throw new Error("Can't return data from the controller since response has already been sent via express.");
|
|
466
|
+
}
|
|
446
467
|
}
|
|
447
468
|
|
|
448
469
|
public createContextServices( request: ServerRequest<this> ) {
|
|
@@ -466,77 +487,86 @@ export default class ServerRouter
|
|
|
466
487
|
return contextServices;
|
|
467
488
|
}
|
|
468
489
|
|
|
469
|
-
public
|
|
490
|
+
public resolve = (request: ServerRequest<this>) => new Promise<ServerResponse<this>>((resolve, reject) => {
|
|
470
491
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
492
|
+
// Create request context so we can access request context across all the request-triggered libs
|
|
493
|
+
context.run({
|
|
494
|
+
// This is for debugging
|
|
495
|
+
channelType: 'request',
|
|
496
|
+
channelId: request.id,
|
|
497
|
+
method: request.method,
|
|
498
|
+
path: request.path,
|
|
499
|
+
}, async () => {
|
|
500
|
+
|
|
501
|
+
const timeStart = Date.now();
|
|
502
|
+
|
|
503
|
+
if (this.status === 'starting') {
|
|
504
|
+
console.log(LogPrefix, `Waiting for servert to be resdy before resolving request`);
|
|
505
|
+
await this.started;
|
|
506
|
+
}
|
|
476
507
|
|
|
477
|
-
|
|
478
|
-
console.log(LogPrefix, `Waiting for servert to be resdy before resolving request`);
|
|
479
|
-
await this.started;
|
|
480
|
-
}
|
|
508
|
+
try {
|
|
481
509
|
|
|
482
|
-
|
|
510
|
+
const response = new ServerResponse<this>(request);
|
|
483
511
|
|
|
484
|
-
|
|
512
|
+
await this.runHook('resolve', request);
|
|
485
513
|
|
|
486
|
-
|
|
514
|
+
// Controller route
|
|
515
|
+
let route = this.controllers[request.path];
|
|
516
|
+
if (route !== undefined) {
|
|
487
517
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
518
|
+
// Create response
|
|
519
|
+
await this.resolvedRoute(route, response, timeStart);
|
|
520
|
+
if (response.wasProvided)
|
|
521
|
+
return resolve(response);
|
|
522
|
+
}
|
|
491
523
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
return response;
|
|
496
|
-
}
|
|
524
|
+
const contextStore = context.getStore();
|
|
525
|
+
if (contextStore)
|
|
526
|
+
contextStore.user = request.user?.email;
|
|
497
527
|
|
|
498
|
-
|
|
499
|
-
|
|
528
|
+
// Classic routes
|
|
529
|
+
for (route of this.routes) {
|
|
500
530
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
531
|
+
// Match Method
|
|
532
|
+
if (request.method !== route.method && route.method !== '*')
|
|
533
|
+
continue;
|
|
504
534
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
535
|
+
// Match Response format
|
|
536
|
+
if (!request.accepts(route.options.accept))
|
|
537
|
+
continue;
|
|
508
538
|
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
539
|
+
const isMatching = matchRoute(route, request);
|
|
540
|
+
if (!isMatching)
|
|
541
|
+
continue;
|
|
512
542
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
543
|
+
await this.resolvedRoute(route, response, timeStart);
|
|
544
|
+
if (response.wasProvided)
|
|
545
|
+
return resolve(response);
|
|
546
|
+
}
|
|
517
547
|
|
|
518
|
-
|
|
548
|
+
reject( new NotFound() );
|
|
519
549
|
|
|
520
|
-
|
|
550
|
+
} catch (error) {
|
|
521
551
|
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
552
|
+
if (this.app.env.profile === 'dev') {
|
|
553
|
+
console.log('API batch error:', request.method, request.path, error);
|
|
554
|
+
const errOrigin = request.method + ' ' + request.path;
|
|
555
|
+
if (error.details === undefined)
|
|
556
|
+
error.details = { origin: errOrigin }
|
|
557
|
+
else
|
|
558
|
+
error.details.origin = errOrigin;
|
|
559
|
+
}
|
|
530
560
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
561
|
+
this.printTakenTime(timeStart);
|
|
562
|
+
reject( error );
|
|
563
|
+
}
|
|
564
|
+
});
|
|
565
|
+
});
|
|
535
566
|
|
|
536
567
|
private async resolvedRoute(
|
|
537
568
|
route: TRoute,
|
|
538
569
|
response: ServerResponse<this>,
|
|
539
|
-
logId: string,
|
|
540
570
|
timeStart: number
|
|
541
571
|
) {
|
|
542
572
|
|
|
@@ -549,14 +579,14 @@ export default class ServerRouter
|
|
|
549
579
|
return;
|
|
550
580
|
|
|
551
581
|
const timeEndResolving = Date.now();
|
|
552
|
-
this.printTakenTime(
|
|
582
|
+
this.printTakenTime(timeStart, timeEndResolving);
|
|
553
583
|
}
|
|
554
584
|
|
|
555
|
-
private printTakenTime = (
|
|
585
|
+
private printTakenTime = (timeStart: number, timeEndResolving?: number) => {
|
|
556
586
|
|
|
557
587
|
if (this.app.env.name === 'server') return;
|
|
558
588
|
|
|
559
|
-
console.log(
|
|
589
|
+
console.log( Math.round(Date.now() - timeStart) + 'ms' +
|
|
560
590
|
(timeEndResolving === undefined ? '' : ' | Routing: ' + Math.round(timeEndResolving - timeStart))
|
|
561
591
|
);
|
|
562
592
|
}
|
package/types/icons.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export type TIcones = "long-arrow-right"|"times"|"solid/spinner-third"|"sack-dollar"|"bell"|"bullseye"|"project-diagram"|"user-friends"|"eye"|"lock"|"comments"|"phone"|"chalkboard-teacher"|"rocket"|"
|
|
1
|
+
export type TIcones = "long-arrow-right"|"times"|"solid/spinner-third"|"sack-dollar"|"bell"|"bullseye"|"project-diagram"|"user-friends"|"eye"|"lock"|"comments"|"phone"|"chalkboard-teacher"|"rocket"|"chart-bar"|"user-circle"|"crosshairs"|"arrow-right"|"user-shield"|"shield-alt"|"chart-line"|"money-bill-wave"|"star"|"link"|"file-alt"|"long-arrow-left"|"plus-circle"|"comments-alt"|"user-plus"|"mouse-pointer"|"thumbs-up"|"dollar-sign"|"at"|"calendar-alt"|"paper-plane"|"brands/linkedin"|"angle-up"|"angle-down"|"solid/crown"|"brands/discord"|"pen"|"plus"|"file"|"search"|"lightbulb"|"magnet"|"key"|"user"|"envelope"|"clock"|"cog"|"trash"|"ellipsis-h"|"regular/shield-check"|"binoculars"|"check"|"times-circle"|"coins"|"download"|"info-circle"|"check-circle"|"exclamation-circle"|"solid/star"|"solid/star-half-alt"|"regular/star"|"chevron-left"|"power-off"|"arrow-left"|"meh-rolling-eyes"|"bars"|"question-circle"|"users"|"bug"|"plane-departure"|"brands/whatsapp"|"wind"|"play"|"minus-circle"|"external-link"|"map-marker-alt"|"arrow-to-bottom"|"broom"|"exclamation-triangle"|"solid/check-circle"|"solid/exclamation-triangle"|"solid/times-circle"|"hourglass"|"comment-alt"|"minus"|"coin"|"solid/magic"|"briefcase"|"map-marker"|"fire"|"globe"|"magic"|"industry"|"plug"|"calendar"|"building"|"graduation-cap"|"unlink"|"bold"|"italic"|"underline"|"strikethrough"|"subscript"|"superscript"|"code"|"font"|"empty-set"|"horizontal-rule"|"page-break"|"image"|"table"|"poll"|"columns"|"sticky-note"|"caret-right"|"align-left"|"align-center"|"align-right"|"align-justify"|"indent"|"outdent"|"list-ul"|"check-square"|"h1"|"h2"|"h3"|"h4"|"list-ol"|"paragraph"|"quote-left"
|