@athenna/http 1.4.3 → 1.4.6

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@athenna/http",
3
- "version": "1.4.3",
3
+ "version": "1.4.6",
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>",
@@ -30,7 +30,9 @@
30
30
  "src/*.js",
31
31
  "src/*.d.ts",
32
32
  "src/**/*.js",
33
- "src/**/*.d.ts"
33
+ "src/**/*.d.ts",
34
+ "templates/*",
35
+ "templates/**/*"
34
36
  ],
35
37
  "type": "module",
36
38
  "main": "./src/index.js",
@@ -52,10 +54,10 @@
52
54
  "#tests/*": "./tests/*.js"
53
55
  },
54
56
  "dependencies": {
55
- "@athenna/artisan": "1.2.7",
56
- "@athenna/ioc": "1.2.0",
57
- "@athenna/logger": "1.2.5",
58
- "@secjs/utils": "1.9.4",
57
+ "@athenna/artisan": "1.2.9",
58
+ "@athenna/ioc": "1.2.2",
59
+ "@athenna/logger": "1.2.7",
60
+ "@secjs/utils": "1.9.7",
59
61
  "fastify": "3.27.4",
60
62
  "fastify-cors": "6.0.3",
61
63
  "fastify-rate-limit": "5.8.0"
@@ -7,20 +7,27 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
 
10
- import { join } from 'node:path'
11
- import { Folder, Path, String } from '@secjs/utils'
10
+ import { Path, String } from '@secjs/utils'
12
11
  import { Artisan, Command, TemplateHelper } from '@athenna/artisan'
13
12
 
14
13
  export class MakeController extends Command {
15
14
  /**
16
15
  * The name and signature of the console command.
16
+ *
17
+ * @return {string}
17
18
  */
18
- signature = 'make:controller <name>'
19
+ get signature() {
20
+ return 'make:controller <name>'
21
+ }
19
22
 
20
23
  /**
21
24
  * The console command description.
25
+ *
26
+ * @return {string}
22
27
  */
23
- description = 'Make a new controller file.'
28
+ get description() {
29
+ return 'Make a new controller file.'
30
+ }
24
31
 
25
32
  /**
26
33
  * Set additional flags in the commander instance.
@@ -45,10 +52,6 @@ export class MakeController extends Command {
45
52
  * @return {Promise<void>}
46
53
  */
47
54
  async handle(name, options) {
48
- TemplateHelper.setTemplatesFolder(
49
- new Folder(join(__dirname, '..', '..', '..', 'templates')).loadSync(),
50
- )
51
-
52
55
  const resource = 'Controller'
53
56
  const subPath = Path.app(`Http/${String.pluralize(resource)}`)
54
57
 
@@ -66,7 +69,5 @@ export class MakeController extends Command {
66
69
  if (options.lint) {
67
70
  await Artisan.call(`eslint:fix ${file.path} --resource ${resource}`)
68
71
  }
69
-
70
- TemplateHelper.setOriginalTemplatesFolder()
71
72
  }
72
73
  }
@@ -7,20 +7,27 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
 
10
- import { join } from 'node:path'
11
- import { Folder, Path, String } from '@secjs/utils'
10
+ import { Path, String } from '@secjs/utils'
12
11
  import { Artisan, Command, TemplateHelper } from '@athenna/artisan'
13
12
 
14
13
  export class MakeMiddleware extends Command {
15
14
  /**
16
15
  * The name and signature of the console command.
16
+ *
17
+ * @return {string}
17
18
  */
18
- signature = 'make:middleware <name>'
19
+ get signature() {
20
+ return 'make:middleware <name>'
21
+ }
19
22
 
20
23
  /**
21
24
  * The console command description.
25
+ *
26
+ * @return {string}
22
27
  */
23
- description = 'Make a new middleware file.'
28
+ get description() {
29
+ return 'Make a new middleware file.'
30
+ }
24
31
 
25
32
  /**
26
33
  * Set additional flags in the commander instance.
@@ -47,10 +54,6 @@ export class MakeMiddleware extends Command {
47
54
  * @return {Promise<void>}
48
55
  */
49
56
  async handle(name, options) {
50
- TemplateHelper.setTemplatesFolder(
51
- new Folder(join(__dirname, '..', '..', '..', 'templates')).loadSync(),
52
- )
53
-
54
57
  const resource = 'Middleware'
55
58
  const subPath = Path.app(`Http/${String.pluralize(resource)}`)
56
59
 
@@ -70,14 +73,12 @@ export class MakeMiddleware extends Command {
70
73
  }
71
74
 
72
75
  if (options.register) {
73
- await TemplateHelper.replaceObjectProperty(
76
+ await TemplateHelper.replaceObjectGetter(
74
77
  Path.http('Kernel.js'),
75
- 'namedMiddlewares =',
78
+ 'namedMiddlewares',
76
79
  file.name,
77
80
  `#app/Http/Middlewares/${file.name}`,
78
81
  )
79
82
  }
80
-
81
- TemplateHelper.setOriginalTemplatesFolder()
82
83
  }
83
84
  }
@@ -7,20 +7,29 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
 
10
- import { pathToFileURL } from 'node:url'
11
10
  import { Command } from '@athenna/artisan'
12
- import { Exec, Path, String } from '@secjs/utils'
11
+ import { Module, Path, String } from '@secjs/utils'
12
+
13
+ import { Route } from '#src/index'
13
14
 
14
15
  export class RouteList extends Command {
15
16
  /**
16
17
  * The name and signature of the console command.
18
+ *
19
+ * @return {string}
17
20
  */
18
- signature = 'route:list'
21
+ get signature() {
22
+ return 'route:list'
23
+ }
19
24
 
20
25
  /**
21
26
  * The console command description.
27
+ *
28
+ * @return {string}
22
29
  */
23
- description = 'List all the routes of your application.'
30
+ get description() {
31
+ return 'List all the routes of your application.'
32
+ }
24
33
 
25
34
  /**
26
35
  * Set additional flags in the commander instance.
@@ -46,11 +55,7 @@ export class RouteList extends Command {
46
55
  async handle(options) {
47
56
  this.simpleLog('[ ROUTE LISTING ]', 'rmNewLineStart', 'bold', 'green')
48
57
 
49
- const Route = ioc.safeUse('Athenna/Core/HttpRoute')
50
-
51
- const Kernel = await Exec.getModule(
52
- import(pathToFileURL(Path.http('Kernel.js')).href),
53
- )
58
+ const Kernel = await Module.getFrom(Path.http('Kernel.js'))
54
59
 
55
60
  const kernel = new Kernel()
56
61
 
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class BadGatewayException extends HttpException {
13
+ /**
14
+ * Creates a new instance of BadGatewayException.
15
+ *
16
+ * @example
17
+ * throw new BadGatewayException()
18
+ * This exception uses the 502 status code and the "E_BAD_GATEWAY_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Bad gateway error',
26
+ code = 'E_BAD_GATEWAY_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 502, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class BadRequestException extends HttpException {
13
+ /**
14
+ * Creates a new instance of BadRequestException.
15
+ *
16
+ * @example
17
+ * throw new BadRequestException()
18
+ * This exception uses the 400 status code and the "E_BAD_REQUEST_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Bad request error',
26
+ code = 'E_BAD_REQUEST_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 400, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class ForbiddenException extends HttpException {
13
+ /**
14
+ * Creates a new instance of ForbiddenException.
15
+ *
16
+ * @example
17
+ * throw new ForbiddenException()
18
+ * This exception uses the 403 status code and the "E_FORBIDDEN_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Forbidden error',
26
+ code = 'E_FORBIDDEN_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 403, code, help)
30
+ }
31
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { Exception } from '@secjs/utils'
11
+
12
+ export class HttpException extends Exception {
13
+ /**
14
+ * Creates a new instance of HttpException.
15
+ *
16
+ * @example
17
+ * throw new HttpException()
18
+ * This exception uses the 500 status code and the "E_HTTP_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {number} [status]
22
+ * @param {string} [code]
23
+ * @param {string|null} [help]
24
+ */
25
+ constructor(
26
+ content = 'Http error',
27
+ status = 500,
28
+ code = 'E_HTTP_ERROR',
29
+ help = null,
30
+ ) {
31
+ super(content, status, code, help)
32
+ }
33
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class InternalServerException extends HttpException {
13
+ /**
14
+ * Creates a new instance of InternalServerException.
15
+ *
16
+ * @example
17
+ * throw new InternalServerException()
18
+ * This exception uses the 500 status code and the "E_INTERNAL_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Internal server error',
26
+ code = 'E_INTERNAL_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 500, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class MethodNotAllowedException extends HttpException {
13
+ /**
14
+ * Creates a new instance of MethodNotAllowedException.
15
+ *
16
+ * @example
17
+ * throw new MethodNotAllowedException()
18
+ * This exception uses the 405 status code and the "E_METHOD_NOT_ALLOWED_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Method not allowed error',
26
+ code = 'E_METHOD_NOT_ALLOWED_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 405, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class NotAcceptableException extends HttpException {
13
+ /**
14
+ * Creates a new instance of NotAcceptableException.
15
+ *
16
+ * @example
17
+ * throw new NotAcceptableException()
18
+ * This exception uses the 406 status code and the "E_NOT_ACCEPTABLE_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Not acceptable error',
26
+ code = 'E_NOT_ACCEPTABLE_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 406, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class NotFoundException extends HttpException {
13
+ /**
14
+ * Creates a new instance of NotFoundException.
15
+ *
16
+ * @example
17
+ * throw new NotFoundException()
18
+ * This exception uses the 404 status code and the "E_NOT_FOUND_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Not found error',
26
+ code = 'E_NOT_FOUND_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 404, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class NotImplementedException extends HttpException {
13
+ /**
14
+ * Creates a new instance of NotImplementedException.
15
+ *
16
+ * @example
17
+ * throw new NotImplementedException()
18
+ * This exception uses the 501 status code and the "E_NOT_IMPLEMENTED_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Not implemented error',
26
+ code = 'E_NOT_IMPLEMENTED_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 501, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class PayloadTooLargeException extends HttpException {
13
+ /**
14
+ * Creates a new instance of PayloadTooLargeException.
15
+ *
16
+ * @example
17
+ * throw new PayloadTooLargeException()
18
+ * This exception uses the 413 status code and the "E_PAYLOAD_TOO_LARGE_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Payload too large error',
26
+ code = 'E_PAYLOAD_TOO_LARGE_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 413, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class RequestTimeoutException extends HttpException {
13
+ /**
14
+ * Creates a new instance of RequestTimeoutException.
15
+ *
16
+ * @example
17
+ * throw new RequestTimeoutException()
18
+ * This exception uses the 408 status code and the "E_REQUEST_TIMEOUT_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Request timeout error',
26
+ code = 'E_REQUEST_TIMEOUT_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 408, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class ServiceUnavailableException extends HttpException {
13
+ /**
14
+ * Creates a new instance of ServiceUnavailableException.
15
+ *
16
+ * @example
17
+ * throw new ServiceUnavailableException()
18
+ * This exception uses the 503 status code and the "E_SERVICE_UNAVAILABLE_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Service unavailable error',
26
+ code = 'E_SERVICE_UNAVAILABLE_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 503, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class UnauthorizedException extends HttpException {
13
+ /**
14
+ * Creates a new instance of UnauthorizedException.
15
+ *
16
+ * @example
17
+ * throw new UnauthorizedException()
18
+ * This exception uses the 401 status code and the "E_UNAUTHORIZED_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Unauthorized error',
26
+ code = 'E_UNAUTHORIZED_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 401, code, help)
30
+ }
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+
10
+ import { HttpException } from '#src/Exceptions/HttpException'
11
+
12
+ export class UnprocessableEntityException extends HttpException {
13
+ /**
14
+ * Creates a new instance of UnprocessableEntityException.
15
+ *
16
+ * @example
17
+ * throw new UnprocessableEntityException()
18
+ * This exception uses the 422 status code and the "E_UNPROCESSABLE_ENTITY_ERROR" code.
19
+ *
20
+ * @param {string} [content]
21
+ * @param {string} [code]
22
+ * @param {string|null} [help]
23
+ */
24
+ constructor(
25
+ content = 'Unprocessable entity error',
26
+ code = 'E_UNPROCESSABLE_ENTITY_ERROR',
27
+ help = null,
28
+ ) {
29
+ super(content, 422, code, help)
30
+ }
31
+ }
@@ -1,8 +1,7 @@
1
1
  import { Log } from '@athenna/logger'
2
- import { Config, Exec, Path, Uuid } from '@secjs/utils'
2
+ import { Config, Module, Path, Uuid } from '@secjs/utils'
3
3
 
4
4
  import { Server } from '#src/Facades/Server'
5
- import { pathToFileURL } from 'url'
6
5
 
7
6
  export class HttpKernel {
8
7
  /**
@@ -10,18 +9,22 @@ export class HttpKernel {
10
9
  *
11
10
  * This middlewares are run during every request to your http server.
12
11
  *
13
- * @type {any | Promise<any>}
12
+ * @return {any[] | Promise<any[]>}
14
13
  */
15
- globalMiddlewares
14
+ get globalMiddlewares() {
15
+ return []
16
+ }
16
17
 
17
18
  /**
18
19
  * The application's named HTTP middlewares.
19
20
  *
20
21
  * Here you define all your named middlewares to use inside routes/http file.
21
22
  *
22
- * @type {Record<string, any | Promise<any>>}
23
+ * @return {Record<string, any | Promise<any>>}
23
24
  */
24
- namedMiddlewares
25
+ get namedMiddlewares() {
26
+ return {}
27
+ }
25
28
 
26
29
  /**
27
30
  * Register all global and named middlewares to the server.
@@ -29,35 +32,36 @@ export class HttpKernel {
29
32
  * @return void
30
33
  */
31
34
  async registerMiddlewares() {
35
+ const subAlias = 'App/Http/Middlewares'
36
+
32
37
  /**
33
38
  * Binding the named middlewares inside the container and
34
39
  * creating a simple alias to use it inside Route.
35
40
  */
36
41
  for (const key of Object.keys(this.namedMiddlewares)) {
37
- const Middleware = await Exec.getModule(this.namedMiddlewares[key])
42
+ const midModule = this.namedMiddlewares[key]
43
+
44
+ const { alias, module } = await Module.getWithAlias(midModule, subAlias)
38
45
 
39
- if (!ioc.hasDependency(`App/Http/Middlewares/${Middleware.name}`)) {
40
- ioc.bind(`App/Http/Middlewares/${Middleware.name}`, Middleware)
46
+ if (!ioc.hasDependency(alias)) {
47
+ ioc.bind(alias, module)
41
48
  }
42
49
 
43
- ioc.alias(
44
- `App/Http/Middlewares/Names/${key}`,
45
- `App/Http/Middlewares/${Middleware.name}`,
46
- )
50
+ ioc.alias(`App/Http/Middlewares/Names/${key}`, alias)
47
51
  }
48
52
 
49
53
  /**
50
54
  * Binding the global middlewares inside the container and
51
55
  * resolving it inside the Http server using "use" method.
52
56
  */
53
- for (const module of this.globalMiddlewares) {
54
- let Middleware = await Exec.getModule(module)
57
+ for (const midModule of this.globalMiddlewares) {
58
+ const { alias, module } = await Module.getWithAlias(midModule, subAlias)
55
59
 
56
- if (!ioc.hasDependency(`App/Http/Middlewares/${Middleware.name}`)) {
57
- ioc.bind(`App/Http/Middlewares/${Middleware.name}`, Middleware)
60
+ if (!ioc.hasDependency(alias)) {
61
+ ioc.bind(alias, module)
58
62
  }
59
63
 
60
- Middleware = ioc.safeUse(`App/Http/Middlewares/${Middleware.name}`)
64
+ const Middleware = ioc.safeUse(alias)
61
65
 
62
66
  if (Middleware.handle) {
63
67
  Server.use(Middleware.handle, 'handle')
@@ -109,9 +113,8 @@ export class HttpKernel {
109
113
  return
110
114
  }
111
115
 
112
- const path = Path.app(`Http/Exceptions/Handler.js`)
116
+ const Handler = await Module.getFrom(Path.http('Exceptions/Handler.js'))
113
117
 
114
- const Handler = await Exec.getModule(import(pathToFileURL(path).href))
115
118
  const handler = new Handler()
116
119
 
117
120
  Server.setErrorHandler(handler.handle.bind(handler))
@@ -7,7 +7,7 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
 
10
- import { Exec, Folder, Path } from '@secjs/utils'
10
+ import { Module, Path } from '@secjs/utils'
11
11
  import { ServiceProvider } from '@athenna/ioc'
12
12
 
13
13
  export class ControllerProvider extends ServiceProvider {
@@ -18,23 +18,12 @@ export class ControllerProvider extends ServiceProvider {
18
18
  */
19
19
  async boot() {
20
20
  const path = Path.app('Http/Controllers')
21
+ const subAlias = 'App/Http/Controllers'
21
22
 
22
- if (!(await Folder.exists(path))) {
23
- return
24
- }
23
+ const controllers = await Module.getAllFromWithAlias(path, subAlias)
25
24
 
26
- const controllers = (await new Folder(path).load()).getFilesByPattern(
27
- '*/**/*.js',
28
- )
29
-
30
- const promises = controllers.map(({ href }) => {
31
- return Exec.getModule(import(href)).then(Controller => {
32
- const alias = `App/Http/Controllers/${Controller.name}`
33
-
34
- this.container.singleton(alias, Controller)
35
- })
25
+ controllers.forEach(({ alias, module }) => {
26
+ this.container.singleton(alias, module)
36
27
  })
37
-
38
- await Promise.all(promises)
39
28
  }
40
29
  }
@@ -7,8 +7,8 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
 
10
+ import { Module, Path } from '@secjs/utils'
10
11
  import { ServiceProvider } from '@athenna/ioc'
11
- import { Exec, Folder, Path } from '@secjs/utils'
12
12
 
13
13
  export class MiddlewareProvider extends ServiceProvider {
14
14
  /**
@@ -18,23 +18,12 @@ export class MiddlewareProvider extends ServiceProvider {
18
18
  */
19
19
  async boot() {
20
20
  const path = Path.app('Http/Middlewares')
21
+ const subAlias = 'App/Http/Middlewares'
21
22
 
22
- if (!(await Folder.exists(path))) {
23
- return
24
- }
23
+ const middlewares = await Module.getAllFromWithAlias(path, subAlias)
25
24
 
26
- const middlewares = (await new Folder(path).load()).getFilesByPattern(
27
- '*/**/*.js',
28
- )
29
-
30
- const promises = middlewares.map(({ href }) => {
31
- return Exec.getModule(import(href)).then(Middleware => {
32
- const alias = `App/Http/Middlewares/${Middleware.name}`
33
-
34
- this.container.singleton(alias, Middleware)
35
- })
25
+ middlewares.forEach(({ alias, module }) => {
26
+ this.container.singleton(alias, module)
36
27
  })
37
-
38
- await Promise.all(promises)
39
28
  }
40
29
  }
package/src/index.d.ts CHANGED
@@ -9,6 +9,7 @@
9
9
 
10
10
  import { Facade } from '@athenna/ioc'
11
11
  import { FastifyReply, FastifyRequest } from 'fastify'
12
+ import { Exception } from '@secjs/utils'
12
13
 
13
14
  export const Server: Facade & Http
14
15
  export const Route: Facade & Router.Router
@@ -665,3 +666,214 @@ export interface MiddlewareContract {
665
666
  intercept?: InterceptHandlerContract
666
667
  terminate?: TerminateHandlerContract
667
668
  }
669
+
670
+ export class HttpException extends Exception {
671
+ /**
672
+ * Creates a new instance of HttpException.
673
+ *
674
+ * @example
675
+ * throw new HttpException()
676
+ * This exception uses the 500 status code and the "E_HTTP_ERROR" code.
677
+ *
678
+ * @param {string} [content]
679
+ * @param {number} [status]
680
+ * @param {string} [code]
681
+ * @param {string|null} [help]
682
+ */
683
+ constructor(content?: string, status?: number, code?: string, help?: string | null)
684
+ }
685
+
686
+ export class BadGatewayException extends Exception {
687
+ /**
688
+ * Creates a new instance of BadGatewayException.
689
+ *
690
+ * @example
691
+ * throw new BadGatewayException()
692
+ * This exception uses the 502 status code and the "E_BAD_GATEWAY_ERROR" code.
693
+ *
694
+ * @param {string} [content]
695
+ * @param {string} [code]
696
+ * @param {string|null} [help]
697
+ */
698
+ constructor(content?: string, code?: string, help?: string | null)
699
+ }
700
+
701
+ export class BadRequestException extends Exception {
702
+ /**
703
+ * Creates a new instance of BadRequestException.
704
+ *
705
+ * @example
706
+ * throw new BadRequestException()
707
+ * This exception uses the 400 status code and the "E_BAD_REQUEST_ERROR" code.
708
+ *
709
+ * @param {string} [content]
710
+ * @param {string} [code]
711
+ * @param {string|null} [help]
712
+ */
713
+ constructor(content?: string, code?: string, help?: string | null)
714
+ }
715
+
716
+ export class ForbiddenException extends Exception {
717
+ /**
718
+ * Creates a new instance of ForbiddenException.
719
+ *
720
+ * @example
721
+ * throw new ForbiddenException()
722
+ * This exception uses the 403 status code and the "E_FORBIDDEN_ERROR" code.
723
+ *
724
+ * @param {string} [content]
725
+ * @param {string} [code]
726
+ * @param {string|null} [help]
727
+ */
728
+ constructor(content?: string, code?: string, help?: string | null)
729
+ }
730
+
731
+ export class InternalServerException extends Exception {
732
+ /**
733
+ * Creates a new instance of InternalServerException.
734
+ *
735
+ * @example
736
+ * throw new InternalServerException()
737
+ * This exception uses the 500 status code and the "E_INTERNAL_ERROR" code.
738
+ *
739
+ * @param {string} [content]
740
+ * @param {string} [code]
741
+ * @param {string|null} [help]
742
+ */
743
+ constructor(content?: string, code?: string, help?: string | null)
744
+ }
745
+
746
+ export class MethodNotAllowedException extends Exception {
747
+ /**
748
+ * Creates a new instance of MethodNotAllowedException.
749
+ *
750
+ * @example
751
+ * throw new MethodNotAllowedException()
752
+ * This exception uses the 405 status code and the "E_METHOD_NOT_ALLOWED_ERROR" code.
753
+ *
754
+ * @param {string} [content]
755
+ * @param {string} [code]
756
+ * @param {string|null} [help]
757
+ */
758
+ constructor(content?: string, code?: string, help?: string | null)
759
+ }
760
+
761
+ export class NotAcceptableException extends Exception {
762
+ /**
763
+ * Creates a new instance of NotAcceptableException.
764
+ *
765
+ * @example
766
+ * throw new NotAcceptableException()
767
+ * This exception uses the 406 status code and the "E_NOT_ACCEPTABLE_ERROR" code.
768
+ *
769
+ * @param {string} [content]
770
+ * @param {string} [code]
771
+ * @param {string|null} [help]
772
+ */
773
+ constructor(content?: string, code?: string, help?: string | null)
774
+ }
775
+
776
+ export class NotFoundException extends Exception {
777
+ /**
778
+ * Creates a new instance of NotFoundException.
779
+ *
780
+ * @example
781
+ * throw new NotFoundException()
782
+ * This exception uses the 404 status code and the "E_NOT_FOUND_ERROR" code.
783
+ *
784
+ * @param {string} [content]
785
+ * @param {string} [code]
786
+ * @param {string|null} [help]
787
+ */
788
+ constructor(content?: string, code?: string, help?: string | null)
789
+ }
790
+
791
+ export class NotImplementedException extends Exception {
792
+ /**
793
+ * Creates a new instance of NotImplementedException.
794
+ *
795
+ * @example
796
+ * throw new NotImplementedException()
797
+ * This exception uses the 501 status code and the "E_NOT_IMPLEMENTED_ERROR" code.
798
+ *
799
+ * @param {string} [content]
800
+ * @param {string} [code]
801
+ * @param {string|null} [help]
802
+ */
803
+ constructor(content?: string, code?: string, help?: string | null)
804
+ }
805
+
806
+ export class PayloadTooLargeException extends Exception {
807
+ /**
808
+ * Creates a new instance of PayloadTooLargeException.
809
+ *
810
+ * @example
811
+ * throw new PayloadTooLargeException()
812
+ * This exception uses the 413 status code and the "E_PAYLOAD_TOO_LARGE_ERROR" code.
813
+ *
814
+ * @param {string} [content]
815
+ * @param {string} [code]
816
+ * @param {string|null} [help]
817
+ */
818
+ constructor(content?: string, code?: string, help?: string | null)
819
+ }
820
+
821
+ export class RequestTimeoutException extends Exception {
822
+ /**
823
+ * Creates a new instance of RequestTimeoutException.
824
+ *
825
+ * @example
826
+ * throw new RequestTimeoutException()
827
+ * This exception uses the 408 status code and the "E_REQUEST_TIMEOUT_ERROR" code.
828
+ *
829
+ * @param {string} [content]
830
+ * @param {string} [code]
831
+ * @param {string|null} [help]
832
+ */
833
+ constructor(content?: string, code?: string, help?: string | null)
834
+ }
835
+
836
+ export class ServiceUnavailableException extends Exception {
837
+ /**
838
+ * Creates a new instance of ServiceUnavailableException.
839
+ *
840
+ * @example
841
+ * throw new ServiceUnavailableException()
842
+ * This exception uses the 503 status code and the "E_SERVICE_UNAVAILABLE_ERROR" code.
843
+ *
844
+ * @param {string} [content]
845
+ * @param {string} [code]
846
+ * @param {string|null} [help]
847
+ */
848
+ constructor(content?: string, code?: string, help?: string | null)
849
+ }
850
+
851
+ export class UnauthorizedException extends Exception {
852
+ /**
853
+ * Creates a new instance of UnauthorizedException.
854
+ *
855
+ * @example
856
+ * throw new UnauthorizedException()
857
+ * This exception uses the 401 status code and the "E_UNAUTHORIZED_ERROR" code.
858
+ *
859
+ * @param {string} [content]
860
+ * @param {string} [code]
861
+ * @param {string|null} [help]
862
+ */
863
+ constructor(content?: string, code?: string, help?: string | null)
864
+ }
865
+
866
+ export class UnprocessableEntityException extends Exception {
867
+ /**
868
+ * Creates a new instance of UnprocessableEntityException.
869
+ *
870
+ * @example
871
+ * throw new UnprocessableEntityException()
872
+ * This exception uses the 422 status code and the "E_UNPROCESSABLE_ENTITY_ERROR" code.
873
+ *
874
+ * @param {string} [content]
875
+ * @param {string} [code]
876
+ * @param {string|null} [help]
877
+ */
878
+ constructor(content?: string, code?: string, help?: string | null)
879
+ }
package/src/index.js CHANGED
@@ -24,6 +24,21 @@ export * from './Commands/Make/Controller.js'
24
24
  export * from './Commands/Make/Middleware.js'
25
25
  export * from './Helpers/HttpCommandsLoader.js'
26
26
 
27
+ export * from './Exceptions/BadGatewayException.js'
28
+ export * from './Exceptions/BadRequestException.js'
29
+ export * from './Exceptions/ForbiddenException.js'
30
+ export * from './Exceptions/HttpException.js'
31
+ export * from './Exceptions/InternalServerException.js'
32
+ export * from './Exceptions/MethodNotAllowedException.js'
33
+ export * from './Exceptions/NotAcceptableException.js'
34
+ export * from './Exceptions/NotFoundException.js'
35
+ export * from './Exceptions/NotImplementedException.js'
36
+ export * from './Exceptions/PayloadTooLargeException.js'
37
+ export * from './Exceptions/RequestTimeoutException.js'
38
+ export * from './Exceptions/ServiceUnavailableException.js'
39
+ export * from './Exceptions/UnauthorizedException.js'
40
+ export * from './Exceptions/UnprocessableEntityException.js'
41
+
27
42
  export class Http {
28
43
  /**
29
44
  * Holds the fastify server instance.
@@ -0,0 +1,52 @@
1
+ export class <%= namePascal %>Controller {
2
+ /**
3
+ * Resolve any dependency of the service container
4
+ * inside the constructor.
5
+ */
6
+ constructor() {}
7
+
8
+ /**
9
+ * Index method
10
+ *
11
+ * @param {import('@athenna/http').ContextContract} ctx
12
+ */
13
+ async index({ response }) {
14
+ return response.status(200).send([{}])
15
+ }
16
+
17
+ /**
18
+ * Store method
19
+ *
20
+ * @param {import('@athenna/http').ContextContract} ctx
21
+ */
22
+ async store({ response }) {
23
+ return response.status(201).send({})
24
+ }
25
+
26
+ /**
27
+ * Show method
28
+ *
29
+ * @param {import('@athenna/http').ContextContract} ctx
30
+ */
31
+ async show({ response }) {
32
+ return response.status(200).send({})
33
+ }
34
+
35
+ /**
36
+ * Update method
37
+ *
38
+ * @param {import('@athenna/http').ContextContract} ctx
39
+ */
40
+ async update({ response, params }) {
41
+ return response.status(200).send({ id: params.id })
42
+ }
43
+
44
+ /**
45
+ * Delete method
46
+ *
47
+ * @param {import('@athenna/http').ContextContract} ctx
48
+ */
49
+ async delete({ response }) {
50
+ return response.status(204)
51
+ }
52
+ }
@@ -0,0 +1,40 @@
1
+ export class <%= namePascal %>Middleware {
2
+ /**
3
+ * Resolve any dependency of the service container
4
+ * inside the constructor.
5
+ */
6
+ constructor() {}
7
+
8
+ /**
9
+ * Handle method is executed before the request gets
10
+ * in your controller.
11
+ *
12
+ * @param {import('@athenna/http').HandleContextContract} ctx
13
+ */
14
+ async handle({ next }) {
15
+ next()
16
+ }
17
+
18
+ /**
19
+ * Intercept method is executed before the response
20
+ * has been sent.
21
+ *
22
+ * @param {import('@athenna/http').InterceptContextContract} ctx
23
+ */
24
+ async intercept({ body }) {
25
+ body.intercepted = true
26
+
27
+ return body
28
+ }
29
+
30
+ /**
31
+ * Terminate method is executed after the response
32
+ * has been sent.
33
+ *
34
+ * @param {import('@athenna/http').TerminateContextContract} ctx
35
+ * @return any
36
+ */
37
+ async terminate({ next }) {
38
+ next()
39
+ }
40
+ }