@athenna/http 1.3.3 → 1.3.4

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 (95) hide show
  1. package/LICENSE.md +3 -15
  2. package/README.md +8 -5
  3. package/package.json +95 -106
  4. package/src/Context/Request.js +168 -137
  5. package/src/Context/Response.js +102 -94
  6. package/src/Exceptions/UndefinedMethodException.js +30 -0
  7. package/src/Facades/Route.js +7 -5
  8. package/src/Facades/Server.js +7 -5
  9. package/src/Handlers/FastifyHandler.js +134 -115
  10. package/src/Handlers/HttpExceptionHandler.js +71 -68
  11. package/src/Kernels/HttpKernel.js +142 -124
  12. package/src/Providers/ControllerProvider.js +30 -39
  13. package/src/Providers/HttpRouteProvider.js +15 -16
  14. package/src/Providers/HttpServerProvider.js +13 -15
  15. package/src/Providers/MiddlewareProvider.js +30 -39
  16. package/src/Router/Route.js +192 -99
  17. package/src/Router/RouteGroup.js +66 -40
  18. package/src/Router/RouteResource.js +156 -74
  19. package/src/Router/Router.js +284 -112
  20. package/src/Utils/isMiddlewareContract.js +8 -6
  21. package/src/Utils/removeSlashes.js +21 -0
  22. package/src/index.d.ts +658 -0
  23. package/src/index.js +284 -0
  24. package/index.d.ts +0 -29
  25. package/index.js +0 -41
  26. package/src/Context/Request.d.ts +0 -103
  27. package/src/Context/Response.d.ts +0 -77
  28. package/src/Contracts/Context/ContextContract.d.ts +0 -17
  29. package/src/Contracts/Context/ContextContract.js +0 -10
  30. package/src/Contracts/Context/Error/ErrorContextContract.d.ts +0 -18
  31. package/src/Contracts/Context/Error/ErrorContextContract.js +0 -10
  32. package/src/Contracts/Context/Error/ErrorHandlerContract.d.ts +0 -12
  33. package/src/Contracts/Context/Error/ErrorHandlerContract.js +0 -10
  34. package/src/Contracts/Context/HandlerContract.d.ts +0 -12
  35. package/src/Contracts/Context/HandlerContract.js +0 -10
  36. package/src/Contracts/Context/Middlewares/Handle/HandleContextContract.d.ts +0 -19
  37. package/src/Contracts/Context/Middlewares/Handle/HandleContextContract.js +0 -10
  38. package/src/Contracts/Context/Middlewares/Handle/HandleHandlerContract.d.ts +0 -12
  39. package/src/Contracts/Context/Middlewares/Handle/HandleHandlerContract.js +0 -10
  40. package/src/Contracts/Context/Middlewares/Intercept/InterceptContextContract.d.ts +0 -19
  41. package/src/Contracts/Context/Middlewares/Intercept/InterceptContextContract.js +0 -10
  42. package/src/Contracts/Context/Middlewares/Intercept/InterceptHandlerContract.d.ts +0 -12
  43. package/src/Contracts/Context/Middlewares/Intercept/InterceptHandlerContract.js +0 -10
  44. package/src/Contracts/Context/Middlewares/Terminate/TerminateContextContract.d.ts +0 -23
  45. package/src/Contracts/Context/Middlewares/Terminate/TerminateContextContract.js +0 -10
  46. package/src/Contracts/Context/Middlewares/Terminate/TerminateHandlerContract.d.ts +0 -12
  47. package/src/Contracts/Context/Middlewares/Terminate/TerminateHandlerContract.js +0 -10
  48. package/src/Contracts/Context/NextContract.d.ts +0 -11
  49. package/src/Contracts/Context/NextContract.js +0 -10
  50. package/src/Contracts/Context/RequestContract.d.ts +0 -25
  51. package/src/Contracts/Context/RequestContract.js +0 -10
  52. package/src/Contracts/Context/ResponseContract.d.ts +0 -20
  53. package/src/Contracts/Context/ResponseContract.js +0 -2
  54. package/src/Contracts/FastifyErrorHandlerContract.d.ts +0 -12
  55. package/src/Contracts/FastifyErrorHandlerContract.js +0 -10
  56. package/src/Contracts/FastifyHandlerContract.d.ts +0 -12
  57. package/src/Contracts/FastifyHandlerContract.js +0 -10
  58. package/src/Contracts/HttpMethodTypes.d.ts +0 -9
  59. package/src/Contracts/HttpMethodTypes.js +0 -10
  60. package/src/Contracts/MiddlewareContract.d.ts +0 -16
  61. package/src/Contracts/MiddlewareContract.js +0 -10
  62. package/src/Contracts/MiddlewareTypes.d.ts +0 -9
  63. package/src/Contracts/MiddlewareTypes.js +0 -10
  64. package/src/Contracts/MiddlewareTypesContract.d.ts +0 -16
  65. package/src/Contracts/MiddlewareTypesContract.js +0 -10
  66. package/src/Contracts/RouteContract.d.ts +0 -16
  67. package/src/Contracts/RouteContract.js +0 -10
  68. package/src/Exceptions/BadRequestException.d.ts +0 -12
  69. package/src/Exceptions/BadRequestException.js +0 -18
  70. package/src/Exceptions/CannotDefineGroupException.d.ts +0 -12
  71. package/src/Exceptions/CannotDefineGroupException.js +0 -19
  72. package/src/Exceptions/MiddlewareNotFoundException.d.ts +0 -12
  73. package/src/Exceptions/MiddlewareNotFoundException.js +0 -19
  74. package/src/Exceptions/UndefinedControllerMethodException.d.ts +0 -12
  75. package/src/Exceptions/UndefinedControllerMethodException.js +0 -19
  76. package/src/Facades/Route.d.ts +0 -10
  77. package/src/Facades/Server.d.ts +0 -10
  78. package/src/Handlers/FastifyHandler.d.ts +0 -26
  79. package/src/Handlers/HttpExceptionHandler.d.ts +0 -27
  80. package/src/Http.d.ts +0 -167
  81. package/src/Http.js +0 -223
  82. package/src/Kernels/HttpKernel.d.ts +0 -54
  83. package/src/Providers/ControllerProvider.d.ts +0 -17
  84. package/src/Providers/HttpRouteProvider.d.ts +0 -17
  85. package/src/Providers/HttpServerProvider.d.ts +0 -17
  86. package/src/Providers/MiddlewareProvider.d.ts +0 -17
  87. package/src/Router/Route.d.ts +0 -32
  88. package/src/Router/RouteGroup.d.ts +0 -24
  89. package/src/Router/RouteResource.d.ts +0 -29
  90. package/src/Router/Router.d.ts +0 -39
  91. package/src/Utils/getAppFiles.d.ts +0 -10
  92. package/src/Utils/getAppFiles.js +0 -22
  93. package/src/Utils/isMiddlewareContract.d.ts +0 -10
  94. package/src/Utils/removeSlash.d.ts +0 -9
  95. package/src/Utils/removeSlash.js +0 -23
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * @athenna/http
4
3
  *
@@ -7,108 +6,202 @@
7
6
  * For the full copyright and license information, please view the LICENSE
8
7
  * file that was distributed with this source code.
9
8
  */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.Route = void 0;
12
- require("@athenna/ioc");
13
- const utils_1 = require("@secjs/utils");
14
- const removeSlash_1 = require("../Utils/removeSlash");
15
- const isMiddlewareContract_1 = require("../Utils/isMiddlewareContract");
16
- const MiddlewareNotFoundException_1 = require("../Exceptions/MiddlewareNotFoundException");
17
- const UndefinedControllerMethodException_1 = require("../Exceptions/UndefinedControllerMethodException");
18
- class Route {
19
- constructor(url, methods, handler) {
20
- this.url = url;
21
- this.deleted = false;
22
- this.methods = methods;
23
- this.prefixes = [];
24
- this.deleted = false;
25
- this.routeMiddlewares = { handlers: [], terminators: [], interceptors: [] };
26
- this.handler = handler;
9
+
10
+ import { Is } from '@secjs/utils'
11
+ import { removeSlashes } from '#src/Utils/removeSlashes'
12
+ import { isMiddlewareContract } from '#src/Utils/isMiddlewareContract'
13
+ import { UndefinedMethodException } from '#src/Exceptions/UndefinedMethodException'
14
+
15
+ export class Route {
16
+ /**
17
+ * Route name for resources.
18
+ *
19
+ * @type {string}
20
+ */
21
+ name
22
+
23
+ /**
24
+ * Route url.
25
+ *
26
+ * @type {string}
27
+ */
28
+ #url
29
+
30
+ /**
31
+ * Sets if route should be registered or not.
32
+ *
33
+ * @type {boolean}
34
+ */
35
+ #deleted
36
+
37
+ /**
38
+ * The route handler closure.
39
+ *
40
+ * @type {string|any}
41
+ */
42
+ #handler
43
+
44
+ /**
45
+ * The methods of this route.
46
+ *
47
+ * @type {string[]}
48
+ */
49
+ #methods
50
+
51
+ /**
52
+ * The middlewares of this route.
53
+ *
54
+ * @type {{ handlers: any[], terminators: any[], interceptors: any[] }}
55
+ */
56
+ #routeMiddlewares
57
+
58
+ /**
59
+ * The prefixes of this route.
60
+ *
61
+ * @type {string[]}
62
+ */
63
+ #prefixes
64
+
65
+ /**
66
+ * Creates a new instance of Route.
67
+ *
68
+ * @param {string} url
69
+ * @param {string[]} methods
70
+ * @param {string|any} handler
71
+ * @param {string} [name]
72
+ * @return {Route}
73
+ */
74
+ constructor(url, methods, handler, name) {
75
+ this.#url = url
76
+ this.#deleted = false
77
+ this.#methods = methods
78
+ this.#prefixes = []
79
+ this.#handler = handler
80
+ this.#routeMiddlewares = { handlers: [], terminators: [], interceptors: [] }
81
+
82
+ if (name) {
83
+ this.name = name
27
84
  }
28
- prefix(prefix) {
29
- this.prefixes.push(prefix);
30
- return this;
85
+ }
86
+
87
+ /**
88
+ * Set a prefix for the route.
89
+ *
90
+ * @param {string} prefix
91
+ * @return {Route}
92
+ */
93
+ prefix(prefix) {
94
+ this.#prefixes.push(prefix)
95
+
96
+ return this
97
+ }
98
+
99
+ /**
100
+ * Set a middleware for the route.
101
+ *
102
+ * @param {string|any} middleware
103
+ * @param {'handle'|'intercept'|'terminate'} [type]
104
+ * @param {boolean} [prepend]
105
+ * @return {Route}
106
+ */
107
+ middleware(middleware, type = 'handle', prepend = false) {
108
+ const dictionary = {
109
+ handle: 'handlers',
110
+ terminate: 'terminators',
111
+ intercept: 'interceptors',
31
112
  }
32
- as(name, prepend = false) {
33
- this.name = prepend ? `${name}.${this.name}` : name;
34
- return this;
113
+
114
+ const insertionType = prepend ? 'unshift' : 'push'
115
+
116
+ if (Is.String(middleware)) {
117
+ const mid =
118
+ ioc.use(`App/Http/Middlewares/Names/${middleware}`) ||
119
+ ioc.safeUse(`App/Http/Middlewares/${middleware}`)
120
+
121
+ if (mid.handle) {
122
+ this.#routeMiddlewares.handlers[insertionType](mid.handle.bind(mid))
123
+ }
124
+
125
+ if (mid.intercept) {
126
+ this.#routeMiddlewares.interceptors[insertionType](
127
+ mid.intercept.bind(mid),
128
+ )
129
+ }
130
+
131
+ if (mid.terminate) {
132
+ this.#routeMiddlewares.terminators[insertionType](
133
+ mid.terminate.bind(mid),
134
+ )
135
+ }
136
+
137
+ return this
35
138
  }
36
- namespace(namespace, overwrite = false) {
37
- if (!this.routeNamespace || overwrite) {
38
- this.routeNamespace = namespace;
39
- }
40
- return this;
139
+
140
+ if (isMiddlewareContract(middleware)) {
141
+ if (middleware.handle) {
142
+ this.#routeMiddlewares.handlers[insertionType](
143
+ middleware.handle.bind(middleware),
144
+ )
145
+ }
146
+
147
+ if (middleware.intercept) {
148
+ this.#routeMiddlewares.interceptors[insertionType](
149
+ middleware.intercept.bind(middleware),
150
+ )
151
+ }
152
+
153
+ if (middleware.terminate) {
154
+ this.#routeMiddlewares.terminators[insertionType](
155
+ middleware.terminate.bind(middleware),
156
+ )
157
+ }
158
+
159
+ return this
41
160
  }
42
- middleware(middleware, type = 'handle', prepend = false) {
43
- const dictionary = {
44
- handle: 'handlers',
45
- terminate: 'terminators',
46
- intercept: 'interceptors',
47
- };
48
- const insertionType = prepend ? 'unshift' : 'push';
49
- if (utils_1.Is.String(middleware)) {
50
- const mid = ioc.use(`App/Http/Middlewares/Names/${middleware}`) ||
51
- ioc.safeUse(`App/Http/Middlewares/${middleware}`);
52
- if (!mid) {
53
- throw new MiddlewareNotFoundException_1.MiddlewareNotFoundException(middleware);
54
- }
55
- if (mid.handle) {
56
- this.routeMiddlewares.handlers[insertionType](mid.handle.bind(mid));
57
- }
58
- if (mid.intercept) {
59
- this.routeMiddlewares.interceptors[insertionType](mid.intercept.bind(mid));
60
- }
61
- if (mid.terminate) {
62
- this.routeMiddlewares.terminators[insertionType](mid.terminate.bind(mid));
63
- }
64
- return this;
65
- }
66
- if (isMiddlewareContract_1.isMiddlewareContract(middleware)) {
67
- if (middleware.handle) {
68
- this.routeMiddlewares.handlers[insertionType](middleware.handle.bind(middleware));
69
- }
70
- if (middleware.intercept) {
71
- this.routeMiddlewares.interceptors[insertionType](middleware.intercept.bind(middleware));
72
- }
73
- if (middleware.terminate) {
74
- this.routeMiddlewares.terminators[insertionType](middleware.terminate.bind(middleware));
75
- }
76
- return this;
77
- }
78
- this.routeMiddlewares[dictionary[type]][insertionType](middleware);
79
- return this;
161
+
162
+ this.#routeMiddlewares[dictionary[type]][insertionType](middleware)
163
+
164
+ return this
165
+ }
166
+
167
+ toJSON() {
168
+ const json = {
169
+ url: this.#getUrl(),
170
+ methods: this.#methods,
171
+ middlewares: this.#routeMiddlewares,
80
172
  }
81
- toJSON() {
82
- const json = {
83
- name: this.name,
84
- url: this.getUrl(),
85
- methods: this.methods,
86
- middlewares: this.routeMiddlewares,
87
- meta: {
88
- namespace: this.routeNamespace,
89
- },
90
- };
91
- if (utils_1.Is.String(this.handler)) {
92
- const [controller, method] = this.handler.split('.');
93
- const dependency = ioc.safeUse(`App/Http/Controllers/${controller}`);
94
- if (!dependency[method]) {
95
- throw new UndefinedControllerMethodException_1.UndefinedControllerMethodException(method, controller);
96
- }
97
- json.handler = dependency[method].bind(dependency);
98
- }
99
- else {
100
- json.handler = this.handler;
101
- }
102
- return json;
103
- }
104
- getUrl() {
105
- const url = removeSlash_1.removeSlash(this.url);
106
- const prefix = this.prefixes
107
- .slice()
108
- .reverse()
109
- .map(p => removeSlash_1.removeSlash(p))
110
- .join('');
111
- return prefix ? `${prefix}${url === '/' ? '' : url}` : url;
173
+
174
+ if (Is.String(this.#handler)) {
175
+ const [controller, method] = this.#handler.split('.')
176
+
177
+ const dependency = ioc.safeUse(`App/Http/Controllers/${controller}`)
178
+
179
+ if (!dependency[method]) {
180
+ throw new UndefinedMethodException(method, controller)
181
+ }
182
+
183
+ json.handler = dependency[method].bind(dependency)
184
+ } else {
185
+ json.handler = this.#handler
112
186
  }
187
+
188
+ return json
189
+ }
190
+
191
+ /**
192
+ * Get the route url parsed with prefixes.
193
+ *
194
+ * @return {string}
195
+ */
196
+ #getUrl() {
197
+ const url = removeSlashes(this.#url)
198
+
199
+ const prefix = this.#prefixes
200
+ .slice()
201
+ .reverse()
202
+ .map(p => removeSlashes(p))
203
+ .join('')
204
+
205
+ return prefix ? `${prefix}${url === '/' ? '' : url}` : url
206
+ }
113
207
  }
114
- exports.Route = Route;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * @athenna/http
4
3
  *
@@ -7,45 +6,72 @@
7
6
  * For the full copyright and license information, please view the LICENSE
8
7
  * file that was distributed with this source code.
9
8
  */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.RouteGroup = void 0;
12
- const RouteResource_1 = require("./RouteResource");
13
- const CannotDefineGroupException_1 = require("../Exceptions/CannotDefineGroupException");
14
- class RouteGroup {
15
- constructor(routes) {
16
- this.routes = routes;
9
+
10
+ import { RouteResource } from '#src/Router/RouteResource'
11
+
12
+ export class RouteGroup {
13
+ /**
14
+ * All routes registered in the group.
15
+ *
16
+ * @type {(import('./Route.js').Route | RouteResource | RouteGroup)[]}
17
+ */
18
+ routes
19
+
20
+ /**
21
+ * Creates a new instance of RouteGroup.
22
+ *
23
+ * @param {(import('./Route.js').Route | RouteResource | RouteGroup)[]} routes
24
+ */
25
+ constructor(routes) {
26
+ this.routes = routes
27
+ }
28
+
29
+ /**
30
+ * Set a prefix for the route group.
31
+ *
32
+ * @param {string} prefix
33
+ * @return {RouteGroup}
34
+ */
35
+ prefix(prefix) {
36
+ this.routes.forEach(route => this.#invoke(route, 'prefix', [prefix]))
37
+
38
+ return this
39
+ }
40
+
41
+ /**
42
+ * Set a middleware for the route group.
43
+ *
44
+ * @param {string|any} middleware
45
+ * @param {'handle'|'intercept'|'terminate'} type
46
+ * @param {boolean} prepend
47
+ * @return {RouteGroup}
48
+ */
49
+ middleware(middleware, type = 'handle', prepend = false) {
50
+ this.routes.forEach(route => {
51
+ this.#invoke(route, 'middleware', [middleware, type, prepend])
52
+ })
53
+
54
+ return this
55
+ }
56
+
57
+ /**
58
+ * Invoke a method from route.
59
+ *
60
+ * @param {import('./Route.js').Route|RouteResource|RouteGroup} route
61
+ * @param {string} method
62
+ * @param {any[]} params
63
+ */
64
+ #invoke(route, method, params) {
65
+ if (route instanceof RouteResource) {
66
+ route.routes.forEach(child => this.#invoke(child, method, params))
67
+ return
17
68
  }
18
- prefix(prefix) {
19
- this.routes.forEach(route => this.invoke(route, 'prefix', [prefix]));
20
- return this;
21
- }
22
- as(name) {
23
- this.routes.forEach(route => this.invoke(route, 'as', [name, true]));
24
- return this;
25
- }
26
- namespace(namespace) {
27
- this.routes.forEach(route => this.invoke(route, 'namespace', [namespace]));
28
- return this;
29
- }
30
- middleware(middleware, type = 'handle', prepend = false) {
31
- this.routes.forEach(route => {
32
- this.invoke(route, 'middleware', [middleware, type, prepend]);
33
- });
34
- return this;
35
- }
36
- invoke(route, method, params) {
37
- if (route instanceof RouteResource_1.RouteResource) {
38
- route.routes.forEach(child => this.invoke(child, method, params));
39
- return;
40
- }
41
- if (route instanceof RouteGroup) {
42
- route.routes.forEach(child => this.invoke(child, method, params));
43
- return;
44
- }
45
- if (method === 'as' && !route.name) {
46
- throw new CannotDefineGroupException_1.CannotDefineGroupException();
47
- }
48
- route[method](...params);
69
+
70
+ if (route instanceof RouteGroup) {
71
+ route.routes.forEach(child => this.#invoke(child, method, params))
72
+ return
49
73
  }
74
+
75
+ route[method](...params)
76
+ }
50
77
  }
51
- exports.RouteGroup = RouteGroup;
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * @athenna/http
4
3
  *
@@ -7,78 +6,161 @@
7
6
  * For the full copyright and license information, please view the LICENSE
8
7
  * file that was distributed with this source code.
9
8
  */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.RouteResource = void 0;
12
- const Route_1 = require("./Route");
13
- const utils_1 = require("@secjs/utils");
14
- class RouteResource {
15
- constructor(resource, controller) {
16
- this.routes = [];
17
- this.resource = resource;
18
- this.controller = controller;
19
- this.resourceName = this.resource
20
- .split('.')
21
- .map(string => utils_1.String.toSnakeCase(string))
22
- .join('.');
23
- this.buildRoutes();
24
- }
25
- middleware(middleware, type = 'handle') {
26
- this.routes.forEach(route => route.middleware(middleware, type));
27
- return this;
28
- }
29
- only(names) {
30
- this.filter(names, true).forEach(route => (route.deleted = true));
31
- return this;
32
- }
33
- except(names) {
34
- this.filter(names, false).forEach(route => (route.deleted = true));
35
- return this;
36
- }
37
- namespace(namespace) {
38
- this.routes.forEach(route => {
39
- route.namespace(namespace);
40
- });
41
- return this;
42
- }
43
- as(name) {
44
- name = utils_1.String.toSnakeCase(name);
45
- this.routes.forEach(route => {
46
- route.as(route.name.replace(this.resourceName, name), false);
47
- });
48
- this.resourceName = name;
49
- return this;
50
- }
51
- makeRoute(url, methods, action) {
52
- let handler = '';
53
- if (utils_1.Is.String(this.controller)) {
54
- handler = `${this.controller}.${action}`;
55
- }
56
- else {
57
- handler = this.controller[action];
58
- }
59
- const route = new Route_1.Route(url, methods, handler);
60
- route.as(`${this.resourceName}.${action}`);
61
- this.routes.push(route);
62
- }
63
- buildRoutes() {
64
- this.resource = this.resource.replace(/^\//, '').replace(/\/$/, '');
65
- const resourceTokens = this.resource.split('.');
66
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67
- const mainResource = resourceTokens.pop();
68
- const fullUrl = `${resourceTokens
69
- .map(string => `${string}/:${utils_1.String.toSnakeCase(utils_1.String.singularize(string))}_id`)
70
- .join('/')}/${mainResource}`;
71
- this.makeRoute(fullUrl, ['HEAD', 'GET'], 'index');
72
- this.makeRoute(fullUrl, ['POST'], 'store');
73
- this.makeRoute(`${fullUrl}/:id`, ['HEAD', 'GET'], 'show');
74
- this.makeRoute(`${fullUrl}/:id`, ['PUT', 'PATCH'], 'update');
75
- this.makeRoute(`${fullUrl}/:id`, ['DELETE'], 'delete');
76
- }
77
- filter(names, inverse) {
78
- return this.routes.filter(route => {
79
- const match = names.find(name => route.name.endsWith(name));
80
- return inverse ? !match : match;
81
- });
9
+
10
+ import { Route } from '#src/Router/Route'
11
+ import { Is, String } from '@secjs/utils'
12
+
13
+ export class RouteResource {
14
+ /**
15
+ * All routes registered in the resource.
16
+ *
17
+ * @type {Route[]}
18
+ */
19
+ routes
20
+
21
+ /**
22
+ * The resource name.
23
+ *
24
+ * @type {string}
25
+ */
26
+ #resource
27
+
28
+ /**
29
+ * The resource controller.
30
+ *
31
+ * @type {any}
32
+ */
33
+ #controller
34
+
35
+ /**
36
+ * The resource name.
37
+ *
38
+ * @type {string}
39
+ */
40
+ #resourceName
41
+
42
+ /**
43
+ * Creates a new instance of RouteResource.
44
+ *
45
+ * @param {string} resource
46
+ * @param {any} controller
47
+ * @return {RouteResource}
48
+ */
49
+ constructor(resource, controller) {
50
+ this.routes = []
51
+
52
+ this.#resource = resource
53
+ this.#controller = controller
54
+
55
+ this.#resourceName = this.#resource
56
+ .split('.')
57
+ .map(string => String.toSnakeCase(string))
58
+ .join('.')
59
+
60
+ this.#buildRoutes()
61
+ }
62
+
63
+ /**
64
+ * Set a middleware for the route group.
65
+ *
66
+ * @param {string|any} middleware
67
+ * @param {'handle'|'intercept'|'terminate'} type
68
+ * @return {RouteResource}
69
+ */
70
+ middleware(middleware, type = 'handle') {
71
+ this.routes.forEach(route => route.middleware(middleware, type))
72
+
73
+ return this
74
+ }
75
+
76
+ /**
77
+ * Register only the methods in the array.
78
+ *
79
+ * @param {string[]} names
80
+ * @return {RouteResource}
81
+ */
82
+ only(names) {
83
+ this.#filter(names, true).forEach(route => (route.deleted = true))
84
+
85
+ return this
86
+ }
87
+
88
+ /**
89
+ * Register all methods except the methods in the array.
90
+ *
91
+ * @param {string[]} names
92
+ * @return {RouteResource}
93
+ */
94
+ except(names) {
95
+ this.#filter(names, false).forEach(route => (route.deleted = true))
96
+
97
+ return this
98
+ }
99
+
100
+ /**
101
+ * Create the route.
102
+ *
103
+ * @param {string} url
104
+ * @param {string[]} methods
105
+ * @param {string} action
106
+ * return {void}
107
+ */
108
+ #makeRoute(url, methods, action) {
109
+ let handler = ''
110
+
111
+ if (Is.String(this.#controller)) {
112
+ handler = `${this.#controller}.${action}`
113
+ } else {
114
+ handler = this.#controller[action]
82
115
  }
116
+
117
+ const route = new Route(
118
+ url,
119
+ methods,
120
+ handler,
121
+ `${this.#resourceName}.${action}`,
122
+ )
123
+
124
+ this.routes.push(route)
125
+ }
126
+
127
+ /**
128
+ * Build all the routes of the resource.
129
+ *
130
+ * @return {void}
131
+ */
132
+ #buildRoutes() {
133
+ this.#resource = this.#resource.replace(/^\//, '').replace(/\/$/, '')
134
+
135
+ const resourceTokens = this.#resource.split('.')
136
+ const mainResource = resourceTokens.pop()
137
+
138
+ const fullUrl = `${resourceTokens
139
+ .map(
140
+ string =>
141
+ `${string}/:${String.toSnakeCase(String.singularize(string))}_id`,
142
+ )
143
+ .join('/')}/${mainResource}`
144
+
145
+ this.#makeRoute(fullUrl, ['HEAD', 'GET'], 'index')
146
+ this.#makeRoute(fullUrl, ['POST'], 'store')
147
+ this.#makeRoute(`${fullUrl}/:id`, ['HEAD', 'GET'], 'show')
148
+ this.#makeRoute(`${fullUrl}/:id`, ['PUT', 'PATCH'], 'update')
149
+ this.#makeRoute(`${fullUrl}/:id`, ['DELETE'], 'delete')
150
+ }
151
+
152
+ /**
153
+ * Filter the routes by name.
154
+ *
155
+ * @param {string[]} names
156
+ * @param {boolean} inverse
157
+ * @return {Route[]}
158
+ */
159
+ #filter(names, inverse) {
160
+ return this.routes.filter(route => {
161
+ const match = names.find(name => route.name.endsWith(name))
162
+
163
+ return inverse ? !match : match
164
+ })
165
+ }
83
166
  }
84
- exports.RouteResource = RouteResource;