@bool-ts/core 1.3.2 → 1.4.0

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 (68) hide show
  1. package/.prettierrc +11 -0
  2. package/LICENSE +21 -21
  3. package/__test/controller.ts +66 -79
  4. package/__test/index.ts +8 -11
  5. package/__test/interfaces.ts +7 -7
  6. package/__test/module.ts +16 -17
  7. package/__test/repository.ts +16 -16
  8. package/__test/service.ts +20 -20
  9. package/bun.lockb +0 -0
  10. package/dist/decorators/arguments.d.ts +31 -0
  11. package/dist/decorators/arguments.js +67 -0
  12. package/dist/decorators/controller.d.ts +2 -2
  13. package/dist/decorators/controller.js +6 -10
  14. package/dist/decorators/http.d.ts +1 -1
  15. package/dist/decorators/http.js +16 -103
  16. package/dist/decorators/index.d.ts +1 -0
  17. package/dist/decorators/index.js +7 -26
  18. package/dist/decorators/inject.js +5 -9
  19. package/dist/decorators/injectable.d.ts +2 -2
  20. package/dist/decorators/injectable.js +4 -8
  21. package/dist/decorators/module.d.ts +4 -2
  22. package/dist/decorators/module.js +4 -8
  23. package/dist/decorators/zodSchema.d.ts +1 -1
  24. package/dist/decorators/zodSchema.js +5 -8
  25. package/dist/entities/index.d.ts +3 -0
  26. package/dist/entities/index.js +3 -0
  27. package/dist/entities/route.d.ts +101 -0
  28. package/dist/entities/route.js +257 -0
  29. package/dist/entities/router.d.ts +10 -0
  30. package/dist/entities/router.js +25 -0
  31. package/dist/entities/routerGroup.d.ts +14 -0
  32. package/dist/entities/routerGroup.js +24 -0
  33. package/dist/hooks/factory.d.ts +12 -12
  34. package/dist/hooks/factory.js +180 -151
  35. package/dist/hooks/index.js +2 -7
  36. package/dist/hooks/injector.js +7 -10
  37. package/dist/http/clientError.d.ts +1 -1
  38. package/dist/http/clientError.js +3 -7
  39. package/dist/http/index.d.ts +12 -2
  40. package/dist/http/index.js +34 -73
  41. package/dist/http/serverError.js +3 -7
  42. package/dist/index.js +5 -21
  43. package/dist/interfaces/index.js +1 -3
  44. package/dist/ultils/asyncFunction.js +1 -4
  45. package/dist/ultils/index.js +1 -17
  46. package/package.json +30 -33
  47. package/src/decorators/arguments.ts +128 -0
  48. package/src/decorators/controller.ts +14 -18
  49. package/src/decorators/http.ts +81 -195
  50. package/src/decorators/index.ts +7 -6
  51. package/src/decorators/inject.ts +13 -19
  52. package/src/decorators/injectable.ts +11 -12
  53. package/src/decorators/module.ts +21 -22
  54. package/src/decorators/zodSchema.ts +20 -27
  55. package/src/entities/index.ts +3 -0
  56. package/src/entities/route.ts +328 -0
  57. package/src/entities/router.ts +35 -0
  58. package/src/entities/routerGroup.ts +34 -0
  59. package/src/hooks/factory.ts +285 -205
  60. package/src/hooks/index.ts +2 -2
  61. package/src/hooks/injector.ts +43 -43
  62. package/src/http/clientError.ts +45 -56
  63. package/src/http/index.ts +63 -72
  64. package/src/http/serverError.ts +38 -38
  65. package/src/index.ts +6 -6
  66. package/src/interfaces/index.ts +3 -3
  67. package/test.http +30 -28
  68. package/tsconfig.json +107 -109
@@ -1,205 +1,285 @@
1
- import "reflect-metadata";
2
- import "colors";
3
-
4
- import * as Qs from "qs";
5
- import * as ResponseTime from "response-time";
6
-
7
- import { type IControllerRoute, type TModuleOptions, controllerKey, controllerRoutesKey, moduleKey } from "../decorators";
8
- import { default as ExpressApp, Router, json, urlencoded, Request, Response, NextFunction, Errback } from "express";
9
- import { Injector } from "./injector";
10
- import { errorInfer } from "../http";
11
-
12
-
13
- export type TBoolFactoryOptions = Partial<{
14
- debug: boolean;
15
- log: Partial<{
16
- methods: Array<"GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS">;
17
- }>;
18
- queryParser: Partial<{
19
- depth: 10,
20
- arrayLimit: 50
21
- }>;
22
- prefix: string;
23
- }>;
24
-
25
-
26
- /**
27
- *
28
- * @param target
29
- * @param router
30
- */
31
- const controllerCreator = (
32
- controllerConstructor: new (...args: any[]) => unknown,
33
- parentRouter: Router = Router()
34
- ) => {
35
- if (!Reflect.getOwnMetadataKeys(controllerConstructor).includes(controllerKey)) {
36
- throw Error(`${controllerConstructor.name} is not a controller.`);
37
- }
38
-
39
- const controller = Injector.get(controllerConstructor);
40
-
41
- if (!controller) {
42
- throw Error("Can not initialize controller.");
43
- }
44
-
45
- const controllerMetadata = Reflect.getOwnMetadata(controllerKey, controllerConstructor) || "/";
46
- const routesMetadata = (Reflect.getOwnMetadata(controllerRoutesKey, controllerConstructor) || []) as Array<IControllerRoute>;
47
- const router = Router();
48
-
49
- routesMetadata.forEach(routeMetadata => {
50
- if (typeof routeMetadata.descriptor.value !== "function") {
51
- return;
52
- }
53
-
54
- const route = router.route(routeMetadata.path);
55
-
56
- switch (routeMetadata.httpMethod) {
57
- case "GET":
58
- return route.get(routeMetadata.descriptor.value.bind(controller));
59
- case "POST":
60
- return route.post(routeMetadata.descriptor.value.bind(controller));
61
- case "PUT":
62
- return route.put(routeMetadata.descriptor.value.bind(controller));
63
- case "PATCH":
64
- return route.patch(routeMetadata.descriptor.value.bind(controller));
65
- case "DELETE":
66
- return route.delete(routeMetadata.descriptor.value.bind(controller));
67
- case "OPTIONS":
68
- return route.options(routeMetadata.descriptor.value.bind(controller));
69
- }
70
- });
71
-
72
- return parentRouter.use(controllerMetadata, router);
73
- }
74
-
75
-
76
- /**
77
- *
78
- * @param target
79
- */
80
- export const BoolFactory = (
81
- target: new (...args: any[]) => unknown,
82
- options?: TBoolFactoryOptions
83
- ) => {
84
- if (!Reflect.getOwnMetadataKeys(target).includes(moduleKey)) {
85
- throw Error(`${target.name} is not a module.`);
86
- }
87
-
88
- const metadata = Reflect.getOwnMetadata(moduleKey, target) as TModuleOptions;
89
- const allowOrigins = !metadata?.allowOrigins ?
90
- ["*"] : typeof metadata.allowOrigins !== "string" ?
91
- metadata.allowOrigins : [metadata.allowOrigins];
92
- const allowMethods = !metadata?.allowMethods ?
93
- ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"] : metadata.allowMethods;
94
- const app = ExpressApp();
95
- const factoryOptions = Object.freeze({
96
- allowLogsMethods: !options?.log?.methods ? ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"] : options.log.methods
97
- });
98
- const routers = !metadata?.controllers ?
99
- [] : metadata.controllers.map(controllerConstructor => controllerCreator(controllerConstructor));
100
-
101
- app.set("etag", "strong");
102
- app.set("query parser", (query: string) => Qs.parse(query, {
103
- depth: !options?.queryParser?.depth || options.queryParser.depth < 0 ? 10 : options.queryParser.depth,
104
- arrayLimit: !options?.queryParser?.arrayLimit || options.queryParser.arrayLimit < 0 ? 50 : options.queryParser.arrayLimit
105
- }));
106
-
107
- app.use(
108
- urlencoded({
109
- extended: true,
110
- inflate: true,
111
- limit: "1mb",
112
- parameterLimit: 20,
113
- type: "application/x-www-form-urlencoded",
114
- verify: undefined
115
- }),
116
- json({
117
- inflate: true,
118
- limit: "5mb",
119
- reviver: undefined,
120
- strict: true,
121
- type: "application/json",
122
- verify: undefined
123
- }),
124
- // Headers parser
125
- (req: Request, res: Response, next: NextFunction) => {
126
- for (const [key, value] of Object.entries(req.headers)) {
127
- req.headers[key] = typeof value !== "string" ? value : decodeURI(value)
128
- }
129
-
130
- next();
131
- },
132
- // Body parser
133
- (req: Request, res: Response, next: NextFunction) => {
134
- if (typeof req.body !== "object" || !req.body) {
135
- req.body = Object.freeze({});
136
- }
137
-
138
- next();
139
- },
140
- // Response time log
141
- ResponseTime.default((req: Request, res: Response, time: number) => {
142
- const requestMethod = req.method.toUpperCase();
143
-
144
- if (!factoryOptions.allowLogsMethods.includes(requestMethod)) {
145
- return;
146
- }
147
-
148
- const convertedMethod = `${requestMethod.yellow}`.bgBlue;
149
- const convertedPID = `${process.pid}`.yellow;
150
- const convertedReqIp = `${req.headers["x-forwarded-for"] || req.headers["x-real-ip"] || req.ip || "<Unknown>"}`.yellow;
151
- const convertedTime = `${Math.round((time + Number.EPSILON) * 10 ** 2) / 10 ** 2}ms`.yellow;
152
-
153
- console.info(`PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${req.originalUrl.blue} - Time: ${convertedTime}`);
154
- })
155
- );
156
-
157
- app.use((req: Request, res: Response, next: NextFunction) => {
158
- if (!allowOrigins.includes("*")) {
159
- if (!allowOrigins.includes(req.headers.origin || "*")) {
160
- return res.status(403).json({
161
- httpCode: 403,
162
- data: {
163
- origin: {
164
- code: "origin:invalid:0x00001",
165
- message: "Invalid origin."
166
- }
167
- }
168
- });
169
- }
170
- }
171
-
172
- res.header("Access-Control-Allow-Origin", req.headers.origin || "*");
173
- res.header("Access-Control-Allow-Headers", "*");
174
- res.header("Access-Control-Allow-Credentials", "true");
175
- res.header("Access-Control-Allow-Methods", allowMethods.join(", "));
176
-
177
- next();
178
- });
179
-
180
- if (routers.length > 0) {
181
- !metadata?.prefix ?
182
- app.use(routers) : app.use(!metadata.prefix.startsWith("/") ?
183
- `/${metadata.prefix}` : metadata.prefix, routers);
184
- }
185
-
186
- // Register error catcher
187
- app.use(
188
- // Error catcher
189
- (err: Errback, req: Request, res: Response, next: NextFunction) => {
190
- errorInfer(res, err);
191
-
192
- if (!options?.debug) {
193
- return;
194
- }
195
-
196
- console.info("Headers:", JSON.stringify(req.headers, null, 4), "\nBody:", JSON.stringify(req.body, null, 4));
197
- console.error("Error:");
198
- console.error(err);
199
- }
200
- );
201
-
202
- return app;
203
- }
204
-
205
- export default BoolFactory;
1
+ import "colors";
2
+ import "reflect-metadata";
3
+
4
+ import Qs from "qs";
5
+ import * as Zod from "zod";
6
+
7
+ import { Router, RouterGroup } from "../entities";
8
+ import { type IControllerRoute, type TModuleOptions, controllerKey, controllerRoutesKey, moduleKey } from "../decorators";
9
+ import { HttpClientError, HttpServerError, jsonErrorInfer, type THttpMethods } from "../http";
10
+ import { Injector } from "./injector";
11
+ import { controllerActionArgumentsKey, EArgumentTypes, type TMetadata as TArgumentsMetadata } from "../decorators/arguments";
12
+
13
+ export type TBoolFactoryOptions = Required<{
14
+ port: number;
15
+ }> &
16
+ Partial<{
17
+ prefix: string;
18
+ debug: boolean;
19
+ log: Partial<{
20
+ methods: Array<"GET" | "POST" | "PUT" | "PATCH" | "DELETE" | "OPTIONS">;
21
+ }>;
22
+ queryParser: Parameters<typeof Qs.parse>[1];
23
+ }>;
24
+
25
+ export const controllerCreator = (controllerConstructor: new (...args: any[]) => unknown, group: RouterGroup) => {
26
+ if (!Reflect.getOwnMetadataKeys(controllerConstructor).includes(controllerKey)) {
27
+ throw Error(`${controllerConstructor.name} is not a controller.`);
28
+ }
29
+
30
+ const controller = Injector.get(controllerConstructor);
31
+
32
+ if (!controller) {
33
+ throw Error("Can not initialize controller.");
34
+ }
35
+
36
+ const controllerMetadata = Reflect.getOwnMetadata(controllerKey, controllerConstructor) || "/";
37
+ const routesMetadata = (Reflect.getOwnMetadata(controllerRoutesKey, controllerConstructor) ||
38
+ []) as Array<IControllerRoute>;
39
+ const router = new Router(controllerMetadata);
40
+
41
+ routesMetadata.forEach((routeMetadata) => {
42
+ if (typeof routeMetadata.descriptor.value !== "function") {
43
+ return;
44
+ }
45
+
46
+ const route = router.route(`/${routeMetadata.path}`);
47
+ const handler = routeMetadata.descriptor.value.bind(controller);
48
+ const routeArgument = {
49
+ constructor: controllerConstructor,
50
+ funcName: routeMetadata.methodName,
51
+ func: handler
52
+ };
53
+
54
+ switch (routeMetadata.httpMethod) {
55
+ case "GET":
56
+ return route.get(routeArgument);
57
+ case "POST":
58
+ return route.post(routeArgument);
59
+ case "PUT":
60
+ return route.put(routeArgument);
61
+ case "PATCH":
62
+ return route.patch(routeArgument);
63
+ case "DELETE":
64
+ return route.delete(routeArgument);
65
+ case "OPTIONS":
66
+ return route.options(routeArgument);
67
+ }
68
+ });
69
+
70
+ return group.add(router);
71
+ };
72
+
73
+ export const controllerActionArgumentsResolution = async (
74
+ data: unknown,
75
+ zodSchema: Zod.Schema,
76
+ argumentIndex: number,
77
+ funcName: string | symbol
78
+ ) => {
79
+ try {
80
+ const validation = await zodSchema.safeParseAsync(data);
81
+
82
+ if (!validation.success) {
83
+ throw new HttpClientError({
84
+ httpCode: 400,
85
+ message: `Validation at the [${funcName.toString()}] method fails at positional argument [${argumentIndex}].`,
86
+ data: validation.error.issues
87
+ });
88
+ }
89
+
90
+ return validation.data;
91
+ } catch (error) {
92
+ if (error instanceof HttpClientError) {
93
+ throw error;
94
+ }
95
+
96
+ throw new HttpServerError({
97
+ httpCode: 500,
98
+ message: `Validation at the [${funcName.toString()}] method error at positional argument [${argumentIndex}].`,
99
+ data: !(error instanceof Error)
100
+ ? error
101
+ : [
102
+ {
103
+ message: error.message,
104
+ code: error.name,
105
+ cause: error.cause
106
+ }
107
+ ]
108
+ });
109
+ }
110
+ };
111
+
112
+ export const BoolFactory = (target: new (...args: any[]) => unknown, options: TBoolFactoryOptions) => {
113
+ if (!Reflect.getOwnMetadataKeys(target).includes(moduleKey)) {
114
+ throw Error(`${target.name} is not a module.`);
115
+ }
116
+
117
+ const moduleMetadata = Reflect.getOwnMetadata(moduleKey, target) as TModuleOptions;
118
+ const allowOrigins = !moduleMetadata?.allowOrigins
119
+ ? ["*"]
120
+ : typeof moduleMetadata.allowOrigins !== "string"
121
+ ? moduleMetadata.allowOrigins
122
+ : [moduleMetadata.allowOrigins];
123
+ const allowMethods = !moduleMetadata?.allowMethods
124
+ ? ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"]
125
+ : moduleMetadata.allowMethods;
126
+ const { allowLogsMethods } = Object.freeze({
127
+ allowLogsMethods: !options?.log?.methods ? ["GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"] : options.log.methods
128
+ });
129
+
130
+ const routerGroup = new RouterGroup();
131
+
132
+ moduleMetadata?.controllers &&
133
+ moduleMetadata.controllers.map((controllerConstructor) => controllerCreator(controllerConstructor, routerGroup));
134
+
135
+ Bun.serve({
136
+ port: options.port,
137
+ async fetch(request) {
138
+ const start = performance.now();
139
+ const url = new URL(request.url);
140
+
141
+ try {
142
+ const headers = request.headers;
143
+ const origin = headers.get("origin");
144
+ const response = new Response();
145
+
146
+ if (!allowOrigins.includes("*")) {
147
+ if (!origin) {
148
+ throw new HttpClientError({
149
+ httpCode: 403,
150
+ message: "Origin not found.",
151
+ data: {
152
+ origin: {
153
+ code: "origin:invalid:0x00001",
154
+ message: "Origin not found."
155
+ }
156
+ }
157
+ });
158
+ }
159
+
160
+ if (!allowOrigins.includes(origin)) {
161
+ throw new HttpClientError({
162
+ httpCode: 403,
163
+ message: "Invalid origin.",
164
+ data: {
165
+ origin: {
166
+ code: "origin:invalid:0x00002",
167
+ message: "Invalid origin."
168
+ }
169
+ }
170
+ });
171
+ }
172
+ }
173
+
174
+ response.headers.set("Access-Control-Allow-Origin", origin || "*");
175
+ response.headers.set("Access-Control-Allow-Headers", "*");
176
+ response.headers.set("Access-Control-Allow-Credentials", "true");
177
+ response.headers.set("Access-Control-Allow-Methods", allowMethods.join(", "));
178
+
179
+ if (!allowMethods.includes(request.method.toUpperCase())) {
180
+ throw new HttpClientError({
181
+ httpCode: 405,
182
+ message: "Method Not Allowed.",
183
+ data: undefined
184
+ });
185
+ }
186
+
187
+ const result = routerGroup.find(url.pathname, request.method as keyof THttpMethods);
188
+
189
+ if (!result) {
190
+ throw new HttpClientError({
191
+ httpCode: 404,
192
+ message: "Route not found.",
193
+ data: undefined
194
+ });
195
+ }
196
+
197
+ const params = result.params;
198
+ const query = Qs.parse(url.search, options.queryParser);
199
+
200
+ for (let i = 0; i < result.handlers.length; i++) {
201
+ const handler = result.handlers[i];
202
+ const handlerMetadata = (Reflect.getOwnMetadata(
203
+ controllerActionArgumentsKey,
204
+ handler.constructor,
205
+ handler.funcName
206
+ ) || {}) as Record<string, TArgumentsMetadata>;
207
+
208
+ const controllerActionArguments = [];
209
+
210
+ if (handlerMetadata) {
211
+ for (const [_key, argsMetadata] of Object.entries(handlerMetadata)) {
212
+ switch (argsMetadata.type) {
213
+ case EArgumentTypes.headers:
214
+ controllerActionArguments[argsMetadata.index] = !argsMetadata.zodSchema
215
+ ? headers
216
+ : await controllerActionArgumentsResolution(
217
+ headers,
218
+ argsMetadata.zodSchema,
219
+ argsMetadata.index,
220
+ handler.funcName
221
+ );
222
+ break;
223
+ case EArgumentTypes.body:
224
+ controllerActionArguments[argsMetadata.index] = !argsMetadata.zodSchema
225
+ ? await request[argsMetadata.parser || "json"]()
226
+ : await controllerActionArgumentsResolution(
227
+ await request[argsMetadata.parser || "json"](),
228
+ argsMetadata.zodSchema,
229
+ argsMetadata.index,
230
+ handler.funcName
231
+ );
232
+ break;
233
+ case EArgumentTypes.params:
234
+ controllerActionArguments[argsMetadata.index] = !argsMetadata.zodSchema
235
+ ? params
236
+ : await controllerActionArgumentsResolution(
237
+ params,
238
+ argsMetadata.zodSchema,
239
+ argsMetadata.index,
240
+ handler.funcName
241
+ );
242
+ break;
243
+ case EArgumentTypes.query:
244
+ controllerActionArguments[argsMetadata.index] = !argsMetadata.zodSchema
245
+ ? query
246
+ : await controllerActionArgumentsResolution(
247
+ query,
248
+ argsMetadata.zodSchema,
249
+ argsMetadata.index,
250
+ handler.funcName
251
+ );
252
+ break;
253
+ }
254
+ }
255
+ }
256
+
257
+ const response = await handler.func(...controllerActionArguments);
258
+
259
+ if (response instanceof Response) {
260
+ return response;
261
+ }
262
+ }
263
+
264
+ return response;
265
+ } catch (error) {
266
+ return jsonErrorInfer(error);
267
+ } finally {
268
+ const end = performance.now();
269
+ const convertedPID = `${process.pid}`.yellow;
270
+ const convertedMethod = `${request.method.yellow}`.bgBlue;
271
+ const convertedReqIp = `${
272
+ request.headers.get("x-forwarded-for") || request.headers.get("x-real-ip") || "<Unknown>"
273
+ }`.yellow;
274
+ const convertedTime = `${Math.round((end - start + Number.EPSILON) * 10 ** 2) / 10 ** 2}ms`.yellow;
275
+
276
+ allowLogsMethods.includes(request.method.toUpperCase()) &&
277
+ console.info(
278
+ `PID: ${convertedPID} - Method: ${convertedMethod} - IP: ${convertedReqIp} - ${url.pathname.blue} - Time: ${convertedTime}`
279
+ );
280
+ }
281
+ }
282
+ });
283
+ };
284
+
285
+ export default BoolFactory;
@@ -1,2 +1,2 @@
1
- export { BoolFactory } from "./factory";
2
- export { Injector } from "./injector";
1
+ export { BoolFactory } from "./factory";
2
+ export { Injector } from "./injector";
@@ -1,43 +1,43 @@
1
- import "reflect-metadata";
2
-
3
- import { injectableKey, injectKey } from "../decorators";
4
-
5
-
6
- interface IInjector {
7
- get<T>(classDefinition: { new(...args: any[]): T }): T
8
- }
9
-
10
- export const Injector: IInjector = new class {
11
-
12
- private readonly _mapper: Map<Function, any> = new Map();
13
-
14
- /**
15
- *
16
- * @param constructor
17
- */
18
- get<T>(
19
- classDefinition: { new(...args: any[]): T }
20
- ) {
21
- if (this._mapper.has(classDefinition)) {
22
- return this._mapper.get(classDefinition) as T;
23
- }
24
-
25
- const ownMetadataKeys = Reflect.getMetadataKeys(classDefinition);
26
-
27
- if (!ownMetadataKeys.includes(injectableKey)) {
28
- throw Error("Missing dependency declaration, please check @Injectable() used on dependency(ies).");
29
- }
30
-
31
- // Initialize dependencies injection
32
- const dependencies: any[] = Reflect.getOwnMetadata(injectKey, classDefinition) || [];
33
- const injections: any[] = dependencies.map(dependency => Injector.get(dependency));
34
- const instance = new classDefinition(...injections);
35
-
36
- this._mapper.set(classDefinition, instance);
37
-
38
- return instance;
39
- }
40
-
41
- }
42
-
43
- export default Injector;
1
+ import "reflect-metadata";
2
+
3
+ import { injectableKey, injectKey } from "../decorators";
4
+
5
+
6
+ interface IInjector {
7
+ get<T>(classDefinition: { new(...args: any[]): T }): T
8
+ }
9
+
10
+ export const Injector: IInjector = new class {
11
+
12
+ private readonly _mapper: Map<Function, any> = new Map();
13
+
14
+ /**
15
+ *
16
+ * @param constructor
17
+ */
18
+ get<T>(
19
+ classDefinition: { new(...args: any[]): T }
20
+ ) {
21
+ if (this._mapper.has(classDefinition)) {
22
+ return this._mapper.get(classDefinition) as T;
23
+ }
24
+
25
+ const ownMetadataKeys = Reflect.getMetadataKeys(classDefinition);
26
+
27
+ if (!ownMetadataKeys.includes(injectableKey)) {
28
+ throw Error("Missing dependency declaration, please check @Injectable() used on dependency(ies).");
29
+ }
30
+
31
+ // Initialize dependencies injection
32
+ const dependencies: any[] = Reflect.getOwnMetadata(injectKey, classDefinition) || [];
33
+ const injections: any[] = dependencies.map(dependency => Injector.get(dependency));
34
+ const instance = new classDefinition(...injections);
35
+
36
+ this._mapper.set(classDefinition, instance);
37
+
38
+ return instance;
39
+ }
40
+
41
+ }
42
+
43
+ export default Injector;