@athenna/http 3.1.0 → 3.1.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.
@@ -26,7 +26,7 @@ export class MakeControllerCommand extends BaseCommand {
26
26
  this.logger.simple('({bold,green} [ MAKING CONTROLLER ])\n');
27
27
  const file = await this.generator
28
28
  .path(Path.http(`Controllers/${this.name}.${Path.ext()}`))
29
- .template('artisan::controller')
29
+ .template('controller')
30
30
  .setNameProperties(true)
31
31
  .make();
32
32
  this.logger.success(`Controller ({yellow} "${file.name}") successfully created.`);
@@ -26,7 +26,7 @@ export class MakeInterceptorCommand extends BaseCommand {
26
26
  this.logger.simple('({bold,green} [ MAKING INTERCEPTOR ])\n');
27
27
  const file = await this.generator
28
28
  .path(Path.http(`Interceptors/${this.name}.${Path.ext()}`))
29
- .template('artisan::interceptor')
29
+ .template('interceptor')
30
30
  .setNameProperties(true)
31
31
  .make();
32
32
  this.logger.success(`Interceptor ({yellow} "${file.name}") successfully created.`);
@@ -26,7 +26,7 @@ export class MakeMiddlewareCommand extends BaseCommand {
26
26
  this.logger.simple('({bold,green} [ MAKING MIDDLEWARE ])\n');
27
27
  const file = await this.generator
28
28
  .path(Path.http(`Middlewares/${this.name}.${Path.ext()}`))
29
- .template('artisan::middleware')
29
+ .template('middleware')
30
30
  .setNameProperties(true)
31
31
  .make();
32
32
  this.logger.success(`Middleware ({yellow} "${file.name}") successfully created.`);
@@ -26,7 +26,7 @@ export class MakeTerminatorCommand extends BaseCommand {
26
26
  this.logger.simple('({bold,green} [ MAKING TERMINATOR ])\n');
27
27
  const file = await this.generator
28
28
  .path(Path.http(`Terminators/${this.name}.${Path.ext()}`))
29
- .template('artisan::terminator')
29
+ .template('terminator')
30
30
  .setNameProperties(true)
31
31
  .make();
32
32
  this.logger.success(`Terminator ({yellow} "${file.name}") successfully created.`);
@@ -12,8 +12,4 @@ export declare class RouteListCommand extends BaseCommand {
12
12
  static signature(): string;
13
13
  static description(): string;
14
14
  handle(): Promise<void>;
15
- /**
16
- * Resolve the import path by meta URL and import it.
17
- */
18
- private resolveRoutePathAndImport;
19
15
  }
@@ -6,8 +6,6 @@
6
6
  * For the full copyright and license information, please view the LICENSE
7
7
  * file that was distributed with this source code.
8
8
  */
9
- import { resolve } from 'node:path';
10
- import { pathToFileURL } from 'node:url';
11
9
  import { Config } from '@athenna/config';
12
10
  import { Module } from '@athenna/common';
13
11
  import { BaseCommand } from '@athenna/artisan';
@@ -27,7 +25,7 @@ export class RouteListCommand extends BaseCommand {
27
25
  const kernel = new HttpKernel();
28
26
  await kernel.registerControllers();
29
27
  await kernel.registerMiddlewares();
30
- await this.resolveRoutePathAndImport();
28
+ await Module.resolve(this.routeFilePath, Config.get('rc.meta'));
31
29
  const routes = Route.list();
32
30
  const table = this.logger.table();
33
31
  table.head('Methods', 'Route', 'Name', 'Handler');
@@ -44,19 +42,4 @@ export class RouteListCommand extends BaseCommand {
44
42
  });
45
43
  table.render();
46
44
  }
47
- /**
48
- * Resolve the import path by meta URL and import it.
49
- */
50
- resolveRoutePathAndImport() {
51
- if (this.routeFilePath.includes('./') ||
52
- this.routeFilePath.includes('../')) {
53
- this.routeFilePath = resolve(this.routeFilePath);
54
- }
55
- if (!this.routeFilePath.startsWith('#')) {
56
- this.routeFilePath = pathToFileURL(this.routeFilePath).href;
57
- }
58
- return import.meta
59
- .resolve(this.routeFilePath, Config.get('rc.meta'))
60
- .then(meta => Module.get(import(meta)));
61
- }
62
45
  }
@@ -24,8 +24,4 @@ export declare class HttpExceptionHandler {
24
24
  * Return a boolean indicating if the error can be logged or not.
25
25
  */
26
26
  private canBeLogged;
27
- /**
28
- * Returns a boolean indicating if the error is an internal server error.
29
- */
30
- private isInternalServerError;
31
27
  }
@@ -7,7 +7,7 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
  import { Log } from '@athenna/logger';
10
- import { String } from '@athenna/common';
10
+ import { Is, String } from '@athenna/common';
11
11
  export class HttpExceptionHandler {
12
12
  /**
13
13
  * Error codes that should be ignored from logging.
@@ -35,7 +35,7 @@ export class HttpExceptionHandler {
35
35
  if (error.help) {
36
36
  body.help = error.help;
37
37
  }
38
- const isInternalServerError = this.isInternalServerError(error);
38
+ const isInternalServerError = Is.Error(error) && !Is.Exception(error);
39
39
  const isDebugMode = Config.is('app.debug', true);
40
40
  if (isInternalServerError && !isDebugMode) {
41
41
  body.code = 'E_INTERNAL_SERVER';
@@ -47,10 +47,10 @@ export class HttpExceptionHandler {
47
47
  if (!this.canBeLogged(error)) {
48
48
  return;
49
49
  }
50
- if (!error.prettify) {
50
+ if (!Is.Exception(error)) {
51
51
  error = error.toAthennaException();
52
52
  }
53
- Log.channelOrVanilla('exception').error((await error.prettify()).concat('\n'));
53
+ Log.channelOrVanilla('exception').error(await error.prettify());
54
54
  }
55
55
  /**
56
56
  * Return a boolean indicating if the error can be logged or not.
@@ -64,19 +64,4 @@ export class HttpExceptionHandler {
64
64
  }
65
65
  return true;
66
66
  }
67
- /**
68
- * Returns a boolean indicating if the error is an internal server error.
69
- */
70
- isInternalServerError(error) {
71
- return [
72
- 'Error',
73
- 'URIError',
74
- 'TypeError',
75
- 'EvalError',
76
- 'RangeError',
77
- 'SyntaxError',
78
- 'InternalError',
79
- 'ReferenceError',
80
- ].includes(error.name);
81
- }
82
67
  }
@@ -69,5 +69,5 @@ export declare class HttpKernel {
69
69
  /**
70
70
  * Resolve the import path by meta URL and import it.
71
71
  */
72
- private resolvePathAndImport;
72
+ private resolvePath;
73
73
  }
@@ -8,60 +8,64 @@
8
8
  */
9
9
  import 'reflect-metadata';
10
10
  import { Server } from '#src';
11
- import { resolve } from 'node:path';
12
11
  import { Log } from '@athenna/logger';
13
- import { pathToFileURL } from 'node:url';
14
12
  import { Config } from '@athenna/config';
15
- import { Is, Module } from '@athenna/common';
13
+ import { Exec, Is, Module } from '@athenna/common';
16
14
  import { HttpExceptionHandler } from '#src/Handlers/HttpExceptionHandler';
15
+ const corsPlugin = await Module.safeImport('@fastify/cors');
16
+ const helmetPlugin = await Module.safeImport('@fastify/helmet');
17
+ const swaggerPlugin = await Module.safeImport('@fastify/swagger');
18
+ const swaggerUiPlugin = await Module.safeImport('@fastify/swagger-ui');
19
+ const rateLimitPlugin = await Module.safeImport('@fastify/rate-limit');
20
+ const rTracerPlugin = await Module.safeImport('cls-rtracer');
17
21
  export class HttpKernel {
18
22
  /**
19
23
  * Register the @fastify/cors plugin in the Http server.
20
24
  */
21
25
  async registerCors() {
22
- if (!Config.exists('http.cors')) {
26
+ if (!corsPlugin) {
23
27
  return;
24
28
  }
25
- await Server.plugin(import('@fastify/cors'), Config.get('http.cors'));
29
+ await Server.plugin(corsPlugin, Config.get('http.cors'));
26
30
  }
27
31
  /**
28
32
  * Register the @fastify/helmet plugin in the Http server.
29
33
  */
30
34
  async registerHelmet() {
31
- if (!Config.exists('http.helmet')) {
35
+ if (!helmetPlugin) {
32
36
  return;
33
37
  }
34
- await Server.plugin(import('@fastify/helmet'), Config.get('http.helmet'));
38
+ await Server.plugin(helmetPlugin, Config.get('http.helmet'));
35
39
  }
36
40
  /**
37
41
  * Register the @fastify/swagger plugin in the Http server.
38
42
  */
39
43
  async registerSwagger() {
40
- if (!Config.exists('http.swagger')) {
41
- return;
44
+ if (swaggerPlugin) {
45
+ await Server.plugin(swaggerPlugin, Config.get('http.swagger.configurations'));
46
+ }
47
+ if (swaggerUiPlugin) {
48
+ await Server.plugin(swaggerUiPlugin, Config.get('http.swagger.ui'));
42
49
  }
43
- await Server.plugin(import('@fastify/swagger'), Config.get('http.swagger.configurations'));
44
- await Server.plugin(import('@fastify/swagger-ui'), Config.get('http.swagger.ui'));
45
50
  }
46
51
  /**
47
52
  * Register the @fastify/rate-limit plugin in the Http server.
48
53
  */
49
54
  async registerRateLimit() {
50
- if (!Config.exists('http.rateLimit')) {
55
+ if (!rateLimitPlugin) {
51
56
  return;
52
57
  }
53
- await Server.plugin(import('@fastify/rate-limit'), Config.get('http.rateLimit'));
58
+ await Server.plugin(rateLimitPlugin, Config.get('http.rateLimit'));
54
59
  }
55
60
  /**
56
61
  * Register the cls-rtracer plugin in the Http server.
57
62
  */
58
63
  async registerRTracer() {
59
- if (!Config.exists('http.rTracer')) {
64
+ if (!rTracerPlugin) {
60
65
  return;
61
66
  }
62
- const rTracer = await import('cls-rtracer');
63
- Server.middleware(async (ctx) => (ctx.data.traceId = rTracer.id()));
64
- await Server.plugin(rTracer.fastifyPlugin, Config.get('http.rTracer'));
67
+ Server.middleware(async (ctx) => (ctx.data.traceId = rTracerPlugin.id()));
68
+ await Server.plugin(rTracerPlugin.fastifyPlugin, Config.get('http.rTracer'));
65
69
  }
66
70
  /**
67
71
  * Register the global log terminator in the Http server.
@@ -78,15 +82,15 @@ export class HttpKernel {
78
82
  */
79
83
  async registerControllers() {
80
84
  const controllers = Config.get('rc.controllers', []);
81
- const promises = controllers.map(path => this.resolvePathAndImport(path).then(Controller => {
85
+ await Exec.concurrently(controllers, async (path) => {
86
+ const Controller = await this.resolvePath(path);
82
87
  if (Reflect.hasMetadata('provider:registered', Controller)) {
83
88
  return;
84
89
  }
85
90
  const createCamelAlias = false;
86
91
  const alias = `App/Http/Controllers/${Controller.name}`;
87
92
  ioc.bind(alias, Controller, createCamelAlias);
88
- }));
89
- await Promise.all(promises);
93
+ });
90
94
  }
91
95
  /**
92
96
  * Register all the middlewares found inside "rc.middlewares" config
@@ -97,7 +101,7 @@ export class HttpKernel {
97
101
  await this.registerNamedMiddlewares();
98
102
  await this.registerGlobalMiddlewares();
99
103
  if (Config.exists('rc.middlewares')) {
100
- await Promise.all(Config.get('rc.middlewares').map(this.resolvePathAndImport));
104
+ await Exec.concurrently(Config.get('rc.middlewares'), this.resolvePath);
101
105
  }
102
106
  }
103
107
  /**
@@ -109,15 +113,15 @@ export class HttpKernel {
109
113
  if (Is.Empty(namedMiddlewares)) {
110
114
  return;
111
115
  }
112
- const promises = Object.keys(namedMiddlewares).map(key => this.resolvePathAndImport(namedMiddlewares[key]).then(Middleware => {
116
+ await Exec.concurrently(Object.keys(namedMiddlewares), async (key) => {
117
+ const Middleware = await this.resolvePath(namedMiddlewares[key]);
113
118
  if (Reflect.hasMetadata('provider:registered', Middleware)) {
114
119
  return;
115
120
  }
116
121
  const createCamelAlias = false;
117
122
  const { alias, namedAlias } = this.getNamedMiddlewareAlias(key, Middleware);
118
123
  ioc.bind(alias, Middleware, createCamelAlias).alias(namedAlias, alias);
119
- }));
120
- await Promise.all(promises);
124
+ });
121
125
  }
122
126
  /**
123
127
  * Register all the named middlewares found inside "rc.globalMiddlewares"
@@ -128,7 +132,8 @@ export class HttpKernel {
128
132
  if (Is.Empty(globalMiddlewares)) {
129
133
  return;
130
134
  }
131
- const promises = globalMiddlewares.map(path => this.resolvePathAndImport(path).then(Middleware => {
135
+ await Exec.concurrently(globalMiddlewares, async (path) => {
136
+ const Middleware = await this.resolvePath(path);
132
137
  if (Reflect.hasMetadata('provider:registered', Middleware)) {
133
138
  return;
134
139
  }
@@ -136,8 +141,7 @@ export class HttpKernel {
136
141
  const { alias, handler, serverMethod } = this.getGlobalMiddlewareAliasAndHandler(Middleware);
137
142
  ioc.bind(alias, Middleware, createCamelAlias);
138
143
  Server[serverMethod](ioc.safeUse(alias)[handler]);
139
- }));
140
- await Promise.all(promises);
144
+ });
141
145
  }
142
146
  /**
143
147
  * Register the exception handler for all request handlers.
@@ -148,7 +152,7 @@ export class HttpKernel {
148
152
  Server.setErrorHandler(handler.handle.bind(handler));
149
153
  return;
150
154
  }
151
- const Handler = await this.resolvePathAndImport(path);
155
+ const Handler = await this.resolvePath(path);
152
156
  const handler = new Handler();
153
157
  Server.setErrorHandler(handler.handle.bind(handler));
154
158
  }
@@ -207,15 +211,7 @@ export class HttpKernel {
207
211
  /**
208
212
  * Resolve the import path by meta URL and import it.
209
213
  */
210
- resolvePathAndImport(path) {
211
- if (path.includes('./') || path.includes('../')) {
212
- path = resolve(path);
213
- }
214
- if (!path.startsWith('#')) {
215
- path = pathToFileURL(path).href;
216
- }
217
- return import.meta
218
- .resolve(path, Config.get('rc.meta'))
219
- .then(meta => Module.get(import(`${meta}?version=${Math.random()}`)));
214
+ resolvePath(path) {
215
+ return Module.resolve(`${path}?version=${Math.random()}`, Config.get('rc.meta'));
220
216
  }
221
217
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@athenna/http",
3
- "version": "3.1.0",
3
+ "version": "3.1.1",
4
4
  "description": "The Athenna Http server. Built on top of fastify.",
5
5
  "license": "MIT",
6
6
  "author": "João Lenon <lenon@athenna.io>",
@@ -213,6 +213,16 @@
213
213
  }
214
214
  },
215
215
  "athenna": {
216
+ "view": {
217
+ "disks": {},
218
+ "templates": {
219
+ "controller": "./templates/controller.edge",
220
+ "interceptor": "./templates/interceptor.edge",
221
+ "middleware": "./templates/middleware.edge",
222
+ "terminator": "./templates/terminator.edge",
223
+ "command": "@athenna/artisan/templates/command.edge"
224
+ }
225
+ },
216
226
  "preloads": [],
217
227
  "services": [],
218
228
  "providers": [],