@avleon/core 0.0.46 → 0.0.48

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 (142) hide show
  1. package/License +21 -21
  2. package/README.md +666 -666
  3. package/dist/chunk-9hOWP6kD.cjs +64 -0
  4. package/dist/chunk-DORXReHP.js +37 -0
  5. package/dist/index-BxIMWhgy.d.ts +1284 -0
  6. package/dist/index-DPn7qtzq.d.cts +1283 -0
  7. package/dist/index.cjs +3194 -0
  8. package/dist/index.cjs.map +1 -0
  9. package/dist/index.js +3022 -79
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib-Bk8hUm06.cjs +7847 -0
  12. package/dist/lib-Bk8hUm06.cjs.map +1 -0
  13. package/dist/lib-CvDxBMkR.js +7843 -0
  14. package/dist/lib-CvDxBMkR.js.map +1 -0
  15. package/package.json +41 -103
  16. package/dist/application.test.d.ts +0 -1
  17. package/dist/application.test.js +0 -15
  18. package/dist/authentication.d.ts +0 -13
  19. package/dist/authentication.js +0 -16
  20. package/dist/cache.d.ts +0 -12
  21. package/dist/cache.js +0 -78
  22. package/dist/cache.test.d.ts +0 -1
  23. package/dist/cache.test.js +0 -36
  24. package/dist/collection.d.ts +0 -43
  25. package/dist/collection.js +0 -231
  26. package/dist/collection.test.d.ts +0 -1
  27. package/dist/collection.test.js +0 -59
  28. package/dist/config.d.ts +0 -18
  29. package/dist/config.js +0 -58
  30. package/dist/config.test.d.ts +0 -1
  31. package/dist/config.test.js +0 -40
  32. package/dist/constants.d.ts +0 -1
  33. package/dist/constants.js +0 -4
  34. package/dist/container.d.ts +0 -30
  35. package/dist/container.js +0 -55
  36. package/dist/controller.d.ts +0 -50
  37. package/dist/controller.js +0 -71
  38. package/dist/controller.test.d.ts +0 -1
  39. package/dist/controller.test.js +0 -97
  40. package/dist/core/application.d.ts +0 -74
  41. package/dist/core/application.js +0 -424
  42. package/dist/core/router.d.ts +0 -44
  43. package/dist/core/router.js +0 -520
  44. package/dist/core/testing.d.ts +0 -21
  45. package/dist/core/testing.js +0 -104
  46. package/dist/core/types.d.ts +0 -67
  47. package/dist/core/types.js +0 -2
  48. package/dist/decorators.d.ts +0 -15
  49. package/dist/decorators.js +0 -41
  50. package/dist/environment-variables.d.ts +0 -49
  51. package/dist/environment-variables.js +0 -130
  52. package/dist/environment-variables.test.d.ts +0 -1
  53. package/dist/environment-variables.test.js +0 -70
  54. package/dist/event-dispatcher.d.ts +0 -22
  55. package/dist/event-dispatcher.js +0 -97
  56. package/dist/event-subscriber.d.ts +0 -14
  57. package/dist/event-subscriber.js +0 -87
  58. package/dist/exceptions/http-exceptions.d.ts +0 -50
  59. package/dist/exceptions/http-exceptions.js +0 -85
  60. package/dist/exceptions/index.d.ts +0 -1
  61. package/dist/exceptions/index.js +0 -17
  62. package/dist/exceptions/system-exception.d.ts +0 -22
  63. package/dist/exceptions/system-exception.js +0 -26
  64. package/dist/file-storage.d.ts +0 -69
  65. package/dist/file-storage.js +0 -323
  66. package/dist/file-storage.test.d.ts +0 -1
  67. package/dist/file-storage.test.js +0 -117
  68. package/dist/helpers.d.ts +0 -11
  69. package/dist/helpers.js +0 -27
  70. package/dist/helpers.test.d.ts +0 -1
  71. package/dist/helpers.test.js +0 -95
  72. package/dist/index.d.ts +0 -57
  73. package/dist/interfaces/avleon-application.d.ts +0 -75
  74. package/dist/interfaces/avleon-application.js +0 -2
  75. package/dist/kenx-provider.d.ts +0 -7
  76. package/dist/kenx-provider.js +0 -44
  77. package/dist/kenx-provider.test.d.ts +0 -1
  78. package/dist/kenx-provider.test.js +0 -36
  79. package/dist/logger.d.ts +0 -12
  80. package/dist/logger.js +0 -87
  81. package/dist/logger.test.d.ts +0 -1
  82. package/dist/logger.test.js +0 -42
  83. package/dist/map-types.d.ts +0 -17
  84. package/dist/map-types.js +0 -89
  85. package/dist/middleware.d.ts +0 -34
  86. package/dist/middleware.js +0 -73
  87. package/dist/middleware.test.d.ts +0 -1
  88. package/dist/middleware.test.js +0 -121
  89. package/dist/multipart.d.ts +0 -17
  90. package/dist/multipart.js +0 -70
  91. package/dist/multipart.test.d.ts +0 -1
  92. package/dist/multipart.test.js +0 -87
  93. package/dist/openapi.d.ts +0 -410
  94. package/dist/openapi.js +0 -59
  95. package/dist/openapi.test.d.ts +0 -1
  96. package/dist/openapi.test.js +0 -111
  97. package/dist/params.d.ts +0 -17
  98. package/dist/params.js +0 -64
  99. package/dist/params.test.d.ts +0 -1
  100. package/dist/params.test.js +0 -83
  101. package/dist/queue.d.ts +0 -29
  102. package/dist/queue.js +0 -84
  103. package/dist/response.d.ts +0 -16
  104. package/dist/response.js +0 -56
  105. package/dist/results.d.ts +0 -20
  106. package/dist/results.js +0 -32
  107. package/dist/route-methods.d.ts +0 -25
  108. package/dist/route-methods.js +0 -60
  109. package/dist/route-methods.test.d.ts +0 -1
  110. package/dist/route-methods.test.js +0 -129
  111. package/dist/swagger-schema.d.ts +0 -37
  112. package/dist/swagger-schema.js +0 -454
  113. package/dist/swagger-schema.test.d.ts +0 -1
  114. package/dist/swagger-schema.test.js +0 -125
  115. package/dist/types/app-builder.interface.d.ts +0 -15
  116. package/dist/types/app-builder.interface.js +0 -8
  117. package/dist/types/application.interface.d.ts +0 -8
  118. package/dist/types/application.interface.js +0 -2
  119. package/dist/utils/common-utils.d.ts +0 -17
  120. package/dist/utils/common-utils.js +0 -108
  121. package/dist/utils/di-utils.d.ts +0 -1
  122. package/dist/utils/di-utils.js +0 -22
  123. package/dist/utils/hash.d.ts +0 -2
  124. package/dist/utils/hash.js +0 -11
  125. package/dist/utils/index.d.ts +0 -2
  126. package/dist/utils/index.js +0 -18
  127. package/dist/utils/object-utils.d.ts +0 -11
  128. package/dist/utils/object-utils.js +0 -198
  129. package/dist/utils/optional-require.d.ts +0 -8
  130. package/dist/utils/optional-require.js +0 -70
  131. package/dist/utils/validation-utils.d.ts +0 -13
  132. package/dist/utils/validation-utils.js +0 -119
  133. package/dist/validation.d.ts +0 -39
  134. package/dist/validation.js +0 -108
  135. package/dist/validation.test.d.ts +0 -1
  136. package/dist/validation.test.js +0 -61
  137. package/dist/validator-extend.d.ts +0 -7
  138. package/dist/validator-extend.js +0 -28
  139. package/dist/websocket.d.ts +0 -10
  140. package/dist/websocket.js +0 -21
  141. package/dist/websocket.test.d.ts +0 -1
  142. package/dist/websocket.test.js +0 -27
@@ -1,520 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.AvleonRouter = void 0;
40
- /**
41
- * @copyright 2024
42
- * @author Tareq Hossain
43
- * @email xtrinsic96@gmail.com
44
- * @url https://github.com/xtareq
45
- */
46
- const helpers_1 = require("../helpers");
47
- const typedi_1 = __importDefault(require("typedi"));
48
- const container_1 = __importStar(require("../container"));
49
- const exceptions_1 = require("../exceptions");
50
- const controller_1 = require("../controller");
51
- const mime_1 = __importDefault(require("mime"));
52
- const stream_1 = __importDefault(require("stream"));
53
- // ---------------------------------------------------------------------------
54
- // Helpers
55
- // ---------------------------------------------------------------------------
56
- /**
57
- * Normalize a flat params/query map like:
58
- * { id: { type: "string", example: "abc-123" } }
59
- * into a valid AJV/JSON Schema object:
60
- * { type: "object", properties: { id: { type: "string", example: "abc-123" } } }
61
- */
62
- function normalizeParamsToJsonSchema(map, requiredKeys = []) {
63
- const properties = {};
64
- for (const [key, val] of Object.entries(map)) {
65
- const { required, ...rest } = val;
66
- properties[key] = { type: "string", ...rest };
67
- }
68
- const schema = { type: "object", properties };
69
- if (requiredKeys.length > 0)
70
- schema.required = requiredKeys;
71
- return schema;
72
- }
73
- /**
74
- * Take a raw @OpenApi schema object and return a Fastify-compatible
75
- * route schema — normalizing params, query → querystring, and headers.
76
- */
77
- function buildRouteSchema(raw) {
78
- const schema = { ...raw };
79
- // ✅ Normalize path params
80
- if (raw.params && typeof raw.params === "object" && !raw.params.type) {
81
- const required = Object.entries(raw.params)
82
- .filter(([, v]) => v.required !== false)
83
- .map(([k]) => k);
84
- schema.params = normalizeParamsToJsonSchema(raw.params, required);
85
- }
86
- // ✅ Normalize query → Fastify uses "querystring", not "query"
87
- if (raw.query && typeof raw.query === "object" && !raw.query.type) {
88
- const required = Object.entries(raw.query)
89
- .filter(([, v]) => v.required === true)
90
- .map(([k]) => k);
91
- schema.querystring = normalizeParamsToJsonSchema(raw.query, required);
92
- delete schema.query;
93
- }
94
- // ✅ Normalize headers
95
- if (raw.headers && typeof raw.headers === "object" && !raw.headers.type) {
96
- schema.headers = normalizeParamsToJsonSchema(raw.headers);
97
- }
98
- return schema;
99
- }
100
- // ---------------------------------------------------------------------------
101
- // Router
102
- // ---------------------------------------------------------------------------
103
- class AvleonRouter {
104
- constructor(app) {
105
- this.routeSet = new Set();
106
- this.metaCache = new Map();
107
- this.middlewares = new Map();
108
- this.rMap = new Map();
109
- this.app = app;
110
- }
111
- setAuthorizeMiddleware(middleware) {
112
- this.authorizeMiddleware = middleware;
113
- }
114
- registerMiddleware(name, instance) {
115
- this.middlewares.set(name, instance);
116
- }
117
- _processMeta(prototype, method) {
118
- const cacheKey = `${prototype.constructor.name}_${method}`;
119
- if (this.metaCache.has(cacheKey)) {
120
- return this.metaCache.get(cacheKey);
121
- }
122
- const meta = {
123
- request: Reflect.getMetadata(controller_1.REQUEST_METADATA_KEY, prototype, method) || [],
124
- params: Reflect.getMetadata(container_1.PARAM_META_KEY, prototype, method) || [],
125
- query: Reflect.getMetadata(container_1.QUERY_META_KEY, prototype, method) || [],
126
- body: Reflect.getMetadata(container_1.REQUEST_BODY_META_KEY, prototype, method) || [],
127
- file: Reflect.getMetadata(container_1.REQUEST_BODY_FILE_KEY, prototype, method) || [],
128
- files: Reflect.getMetadata(container_1.REQUEST_BODY_FILES_KEY, prototype, method) || [],
129
- headers: Reflect.getMetadata(container_1.REQUEST_HEADER_META_KEY, prototype, method) || [],
130
- currentUser: Reflect.getMetadata(container_1.REQUEST_USER_META_KEY, prototype, method) || [],
131
- };
132
- this.metaCache.set(cacheKey, meta);
133
- return meta;
134
- }
135
- executeMiddlewares(target, propertyKey) {
136
- const classMiddlewares = Reflect.getMetadata("controller:middleware", target.constructor) || [];
137
- const methodMiddlewares = propertyKey
138
- ? Reflect.getMetadata("route:middleware", target, propertyKey) || []
139
- : [];
140
- return [...classMiddlewares, ...methodMiddlewares];
141
- }
142
- async buildController(controller) {
143
- var _a, _b;
144
- const ctrl = typedi_1.default.get(controller);
145
- const controllerMeta = Reflect.getMetadata(container_1.CONTROLLER_META_KEY, ctrl.constructor);
146
- if (!controllerMeta)
147
- return;
148
- const prototype = Object.getPrototypeOf(ctrl);
149
- const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
150
- const tag = ctrl.constructor.name.replace("Controller", "");
151
- const swaggerControllerMeta = Reflect.getMetadata("controller:openapi", ctrl.constructor) || {};
152
- const authClsMeata = Reflect.getMetadata(container_1.AUTHORIZATION_META_KEY, ctrl.constructor) || { authorize: false, options: undefined };
153
- for await (const method of methods) {
154
- const methodMeta = Reflect.getMetadata(container_1.ROUTE_META_KEY, prototype, method);
155
- if (!methodMeta)
156
- continue;
157
- const methodmetaOptions = {
158
- method: methodMeta.method.toLowerCase(),
159
- path: (0, helpers_1.formatUrl)(controllerMeta.path + methodMeta.path),
160
- };
161
- const routeKey = `${methodmetaOptions.method}:${methodmetaOptions.path}`;
162
- if (!this.routeSet.has(routeKey)) {
163
- this.routeSet.add(routeKey);
164
- }
165
- const classMiddlewares = this.executeMiddlewares(ctrl, method);
166
- const swaggerMeta = Reflect.getMetadata("route:openapi", prototype, method) || {};
167
- const authClsMethodMeata = Reflect.getMetadata(container_1.AUTHORIZATION_META_KEY, ctrl.constructor, method) || { authorize: false, options: undefined };
168
- const allMeta = this._processMeta(prototype, method);
169
- // --- Build body schema from @Body() decorator ---
170
- let bodySchema = null;
171
- allMeta.body.forEach((r) => {
172
- if (r.schema) {
173
- bodySchema = { ...r.schema };
174
- }
175
- });
176
- // --- Build base schema (single declaration) ---
177
- let schema = { ...swaggerControllerMeta, ...swaggerMeta, tags: [tag] };
178
- // Apply body schema if not manually set in @OpenApi
179
- if (!swaggerMeta.body && bodySchema) {
180
- schema = { ...schema, body: bodySchema };
181
- }
182
- // ✅ Auto-detect querystring from @Query() DTO if not manually set in @OpenApi
183
- if (!swaggerMeta.query && !schema.querystring) {
184
- for (const queryMeta of allMeta.query) {
185
- if (queryMeta.validatorClass && queryMeta.schema) {
186
- schema.querystring = queryMeta.schema;
187
- break;
188
- }
189
- }
190
- }
191
- // ✅ Auto-detect body from @Body() DTO if still not set
192
- if (!swaggerMeta.body && !bodySchema) {
193
- for (const bodyMeta of allMeta.body) {
194
- if (bodyMeta.validatorClass && bodyMeta.schema) {
195
- schema = { ...schema, body: bodyMeta.schema };
196
- break;
197
- }
198
- }
199
- }
200
- const routePath = methodmetaOptions.path === "" ? "/" : methodmetaOptions.path;
201
- // --- Handle multipart ---
202
- const isMultipart = ((_a = schema === null || schema === void 0 ? void 0 : schema.consumes) === null || _a === void 0 ? void 0 : _a.includes("multipart/form-data")) ||
203
- Object.values(((_b = schema === null || schema === void 0 ? void 0 : schema.body) === null || _b === void 0 ? void 0 : _b.properties) || {}).some((p) => p.format === "binary");
204
- if (isMultipart) {
205
- schema.consumes = ["multipart/form-data"];
206
- if (!schema.body) {
207
- schema.body = { type: "object", properties: {} };
208
- }
209
- for (const param of allMeta.body) {
210
- if (param.type === "route:file") {
211
- schema.body.properties[param.key] = {
212
- type: "string",
213
- format: "binary",
214
- };
215
- }
216
- else {
217
- schema.body.properties[param.key] = { type: param.dataType };
218
- }
219
- }
220
- }
221
- // ✅ Normalize params/query/headers into valid JSON Schema
222
- const routeSchema = buildRouteSchema(schema);
223
- this.app.route({
224
- url: routePath,
225
- method: methodmetaOptions.method.toUpperCase(),
226
- schema: routeSchema,
227
- attachValidation: isMultipart,
228
- handler: async (req, res) => {
229
- let reqClone = req;
230
- if (authClsMeata.authorize && this.authorizeMiddleware) {
231
- const cls = container_1.default.get(this.authorizeMiddleware);
232
- await cls.authorize(reqClone, authClsMeata.options);
233
- if (res.sent)
234
- return;
235
- }
236
- if (authClsMethodMeata.authorize && this.authorizeMiddleware) {
237
- const cls = container_1.default.get(this.authorizeMiddleware);
238
- await cls.authorize(reqClone, authClsMethodMeata.options);
239
- if (res.sent)
240
- return;
241
- }
242
- if (classMiddlewares.length > 0) {
243
- for (let m of classMiddlewares) {
244
- const cls = typedi_1.default.get(m.constructor);
245
- reqClone = (await cls.invoke(reqClone, res));
246
- if (res.sent)
247
- return;
248
- }
249
- }
250
- const args = await this._mapArgs(reqClone, allMeta);
251
- for (let paramMeta of allMeta.params) {
252
- if (paramMeta.required) {
253
- (0, helpers_1.validateOrThrow)({ [paramMeta.key]: args[paramMeta.index] }, { [paramMeta.key]: { type: paramMeta.dataType } }, { location: "param" });
254
- }
255
- }
256
- for (let queryMeta of allMeta.query) {
257
- if (queryMeta.validatorClass) {
258
- const err = await (0, helpers_1.validateObjectByInstance)(queryMeta.dataType, args[queryMeta.index]);
259
- if (err) {
260
- return await res.code(400).send({
261
- code: 400,
262
- error: "ValidationError",
263
- errors: err,
264
- message: err.message,
265
- });
266
- }
267
- }
268
- if (queryMeta.required) {
269
- (0, helpers_1.validateOrThrow)({ [queryMeta.key]: args[queryMeta.index] }, { [queryMeta.key]: { type: queryMeta.dataType } }, { location: "queryparam" });
270
- }
271
- }
272
- if (!isMultipart) {
273
- for (let bodyMeta of allMeta.body) {
274
- if (bodyMeta.validatorClass) {
275
- const err = await (0, helpers_1.validateObjectByInstance)(bodyMeta.dataType, args[bodyMeta.index]);
276
- if (err) {
277
- return await res.code(400).send({
278
- code: 400,
279
- error: "ValidationError",
280
- errors: err,
281
- message: err.message,
282
- });
283
- }
284
- }
285
- }
286
- }
287
- const result = await prototype[method].apply(ctrl, args);
288
- if (result === null || result === void 0 ? void 0 : result.download) {
289
- const { stream, filename } = result;
290
- if (!stream || typeof stream.pipe !== "function") {
291
- return res.code(500).send({
292
- code: 500,
293
- error: "INTERNAL_ERROR",
294
- message: "Invalid stream object",
295
- });
296
- }
297
- const contentType = result.contentType ||
298
- mime_1.default.getType(filename) ||
299
- "application/octet-stream";
300
- res.header("Content-Type", contentType);
301
- res.header("Content-Disposition", `attachment; filename="${filename}"`);
302
- stream.on("error", (err) => {
303
- console.error("Stream error:", err);
304
- if (!res.sent) {
305
- res.code(500).send({
306
- code: 500,
307
- error: "StreamError",
308
- message: "Error while streaming file.",
309
- });
310
- }
311
- });
312
- return res.send(stream);
313
- }
314
- if (result instanceof stream_1.default || typeof (result === null || result === void 0 ? void 0 : result.pipe) === "function") {
315
- result.on("error", (err) => {
316
- console.error("Stream error:", err);
317
- if (!res.sent) {
318
- res.code(500).send({
319
- code: 500,
320
- error: "StreamError",
321
- message: "Error while streaming file.",
322
- });
323
- }
324
- });
325
- res.header("Content-Type", "application/octet-stream");
326
- return res.send(result);
327
- }
328
- return res.send(result);
329
- },
330
- });
331
- }
332
- }
333
- async _mapArgs(req, meta) {
334
- var _a, _b, _c, _d;
335
- if (!req.hasOwnProperty("_argsCache")) {
336
- Object.defineProperty(req, "_argsCache", {
337
- value: new Map(),
338
- enumerable: false,
339
- writable: false,
340
- configurable: false,
341
- });
342
- }
343
- const cache = req._argsCache;
344
- const cacheKey = JSON.stringify(meta);
345
- if (cache.has(cacheKey)) {
346
- return cache.get(cacheKey);
347
- }
348
- const maxIndex = Math.max(...meta.params.map((p) => p.index || 0), ...meta.query.map((q) => q.index), ...meta.body.map((b) => b.index), ...meta.currentUser.map((u) => u.index), ...meta.headers.map((h) => h.index), ...(((_a = meta.request) === null || _a === void 0 ? void 0 : _a.map((r) => r.index)) || []), ...(((_b = meta.file) === null || _b === void 0 ? void 0 : _b.map((f) => f.index)) || []), ...(((_c = meta.files) === null || _c === void 0 ? void 0 : _c.map((f) => f.index)) || []), -1) + 1;
349
- const args = new Array(maxIndex).fill(undefined);
350
- meta.params.forEach((p) => {
351
- var _a;
352
- const raw = p.key === "all" ? { ...req.params } : ((_a = req.params[p.key]) !== null && _a !== void 0 ? _a : null);
353
- args[p.index] = (0, helpers_1.autoCast)(raw, p.dataType, p.schema);
354
- });
355
- meta.query.forEach((q) => {
356
- const raw = q.key === "all"
357
- ? (0, helpers_1.normalizeQueryDeep)({ ...req.query })
358
- : req.query[q.key];
359
- args[q.index] = (0, helpers_1.autoCast)(raw, q.dataType, q.schema);
360
- });
361
- meta.body.forEach((body) => {
362
- args[body.index] = { ...req.body, ...req.formData };
363
- });
364
- meta.currentUser.forEach((user) => {
365
- args[user.index] = req.user;
366
- });
367
- meta.headers.forEach((header) => {
368
- args[header.index] =
369
- header.key === "all"
370
- ? { ...req.headers }
371
- : req.headers[header.key];
372
- });
373
- if (meta.request && meta.request.length > 0) {
374
- meta.request.forEach((r) => {
375
- args[r.index] = req;
376
- });
377
- }
378
- const needsFiles = (meta.file && meta.file.length > 0) ||
379
- (meta.files && meta.files.length > 0);
380
- if (needsFiles &&
381
- ((_d = req.headers["content-type"]) === null || _d === void 0 ? void 0 : _d.startsWith("multipart/form-data")) &&
382
- req.saveRequestFiles) {
383
- const files = await req.saveRequestFiles();
384
- if (!files || files.length === 0) {
385
- if (meta.files && meta.files.length > 0) {
386
- throw new exceptions_1.BadRequestException({ error: "No files uploaded" });
387
- }
388
- if (meta.file && meta.file.length > 0) {
389
- meta.file.forEach((f) => {
390
- args[f.index] = null;
391
- });
392
- }
393
- }
394
- else {
395
- const fileInfo = files.map((file) => ({
396
- type: file.type,
397
- filepath: file.filepath,
398
- fieldname: file.fieldname,
399
- filename: file.filename,
400
- encoding: file.encoding,
401
- mimetype: file.mimetype,
402
- fields: file.fields,
403
- toBuffer: file.toBuffer,
404
- }));
405
- if (meta.file && meta.file.length > 0) {
406
- meta.file.forEach((f) => {
407
- if (f.fieldName === "all") {
408
- args[f.index] = fileInfo[0] || null;
409
- }
410
- else {
411
- const file = fileInfo.find((x) => x.fieldname === f.fieldName);
412
- if (!file) {
413
- throw new exceptions_1.BadRequestException(`File field "${f.fieldName}" not found in uploaded files`);
414
- }
415
- args[f.index] = file;
416
- }
417
- });
418
- }
419
- if (meta.files && meta.files.length > 0) {
420
- meta.files.forEach((f) => {
421
- if (f.fieldName === "all") {
422
- args[f.index] = fileInfo;
423
- }
424
- else {
425
- const matchingFiles = fileInfo.filter((x) => x.fieldname === f.fieldName);
426
- if (matchingFiles.length === 0) {
427
- throw new exceptions_1.BadRequestException(`No files found for field "${f.fieldName}"`);
428
- }
429
- args[f.index] = matchingFiles;
430
- }
431
- });
432
- }
433
- }
434
- }
435
- else if (needsFiles) {
436
- throw new exceptions_1.BadRequestException({
437
- error: "Invalid content type. Expected multipart/form-data for file uploads",
438
- });
439
- }
440
- cache.set(cacheKey, args);
441
- return args;
442
- }
443
- _routeHandler(routePath, method, fn) {
444
- const routeKey = method + ":" + routePath;
445
- this.rMap.set(routeKey, {
446
- handler: fn,
447
- middlewares: [],
448
- schema: {},
449
- });
450
- const route = {
451
- useMiddleware: (middlewares) => {
452
- const midds = Array.isArray(middlewares) ? middlewares : [middlewares];
453
- const ms = midds.map((mclass) => {
454
- const cls = typedi_1.default.get(mclass);
455
- this.middlewares.set(mclass.name, cls);
456
- return cls.invoke;
457
- });
458
- const r = this.rMap.get(routeKey);
459
- if (r)
460
- r.middlewares = ms;
461
- return route;
462
- },
463
- useOpenApi: (options) => {
464
- const r = this.rMap.get(routeKey);
465
- if (r)
466
- r.schema = options;
467
- return route;
468
- },
469
- };
470
- return route;
471
- }
472
- mapGet(path = "", fn) {
473
- return this._routeHandler(path, "GET", fn);
474
- }
475
- mapPost(path = "", fn) {
476
- return this._routeHandler(path, "POST", fn);
477
- }
478
- mapPut(path = "", fn) {
479
- return this._routeHandler(path, "PUT", fn);
480
- }
481
- mapDelete(path = "", fn) {
482
- return this._routeHandler(path, "DELETE", fn);
483
- }
484
- async mapRoute(method, path = "", fn) {
485
- this.app[method](path, async (req, res) => {
486
- try {
487
- const result = await fn(req, res);
488
- if (typeof result === "object" && result !== null) {
489
- res.json(result);
490
- }
491
- else {
492
- res.send(result);
493
- }
494
- }
495
- catch (error) {
496
- console.error(`Error in ${method} route handler:`, error);
497
- res.status(500).send({ error: "Internal Server Error" });
498
- }
499
- });
500
- }
501
- processFunctionalRoutes() {
502
- this.rMap.forEach((value, key) => {
503
- var _a;
504
- const colonIdx = key.indexOf(":");
505
- const m = key.slice(0, colonIdx);
506
- const r = key.slice(colonIdx + 1); // ✅ handles paths containing ":"
507
- const routeSchema = buildRouteSchema(value.schema || {});
508
- this.app.route({
509
- method: m.toUpperCase(),
510
- url: r,
511
- schema: routeSchema,
512
- preHandler: (_a = value.middlewares) !== null && _a !== void 0 ? _a : [],
513
- handler: async (req, res) => {
514
- return value.handler(req, res);
515
- },
516
- });
517
- });
518
- }
519
- }
520
- exports.AvleonRouter = AvleonRouter;
@@ -1,21 +0,0 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
- import { AvleonApplication } from "./application";
8
- import { Constructor } from "../helpers";
9
- import { TestApplication, TestAppOptions } from "../interfaces/avleon-application";
10
- export declare class AvleonTest {
11
- private constructor();
12
- static getController<T>(controller: Constructor<T>, deps?: any[]): T;
13
- static getProvider<T>(service: Constructor<T>, deps?: any[]): T;
14
- static createTestApplication(options: TestAppOptions): TestApplication;
15
- static from(app: AvleonApplication): TestApplication;
16
- static clean(): void;
17
- }
18
- export declare class Avleon {
19
- static createApplication(): AvleonApplication;
20
- static createTestApplication(options: TestAppOptions): TestApplication;
21
- }
@@ -1,104 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.Avleon = exports.AvleonTest = void 0;
7
- /**
8
- * @copyright 2024
9
- * @author Tareq Hossain
10
- * @email xtrinsic96@gmail.com
11
- * @url https://github.com/xtareq
12
- */
13
- const application_1 = require("./application");
14
- const typedi_1 = __importDefault(require("typedi"));
15
- const exceptions_1 = require("../exceptions");
16
- const system_exception_1 = require("../exceptions/system-exception");
17
- class AvleonTest {
18
- constructor() {
19
- process.env.NODE_ENV = "test";
20
- }
21
- static getController(controller, deps = []) {
22
- const paramTypes = Reflect.getMetadata("design:paramtypes", controller) || [];
23
- deps.forEach((dep, i) => {
24
- typedi_1.default.set(paramTypes[i], dep);
25
- });
26
- return typedi_1.default.get(controller);
27
- }
28
- static getProvider(service, deps = []) {
29
- const paramTypes = Reflect.getMetadata("design:paramtypes", service) || [];
30
- deps.forEach((dep, i) => {
31
- typedi_1.default.set(paramTypes[i], dep);
32
- });
33
- return typedi_1.default.get(service);
34
- }
35
- static createTestApplication(options) {
36
- const app = application_1.AvleonApplication.getInternalApp({
37
- dataSourceOptions: options.dataSource ? options.dataSource : undefined,
38
- });
39
- // We need to cast options.controllers to any or Constructor[] for compatibility
40
- if (options.controllers) {
41
- app.useControllers(options.controllers);
42
- }
43
- return AvleonTest.from(app);
44
- }
45
- static from(app) {
46
- // Logic to return a TestApplication wrapper around the running app
47
- // This effectively manually builds the routes map if it wasn't run?
48
- // In icore.ts getTestApp() logic was doing a lot of things manually.
49
- // We need to replicate that behavior via the `app` instance.
50
- // BUT, since we split, logic might need access to internals.
51
- // For now, let's implement the wrapper using app.app (fastify instance)
52
- try {
53
- // Note: In original code, getTestApp did _mapControllers().
54
- // We should access private methods or expose public init method.
55
- // Since we are in separate file, we can't access private easily.
56
- // Best approach: add `initForTest()` on AvleonApplication
57
- // Assuming we added public method or we just cast to any to call private methods (naughty but works)
58
- app._mapControllers().catch((e) => console.error(e));
59
- // In icore.ts, it was mapping routes to app.route explicitly.
60
- // In our refactor, _mapControllers calls router.buildController -> which adds routes to app.
61
- // So fastify app should be ready.
62
- app.app.setErrorHandler(async (error, req, res) => {
63
- // Reuse error handler logic or simplified version
64
- if (error instanceof exceptions_1.ValidationErrorException) {
65
- return res.status(400).send({
66
- code: 400,
67
- error: "ValidationError",
68
- errors: error.message,
69
- });
70
- }
71
- return res.status(500).send(error);
72
- });
73
- return {
74
- get: async (url, options) => app.app.inject({ method: "GET", url, ...options }),
75
- post: async (url, options) => app.app.inject({ method: "POST", url, ...options }),
76
- put: async (url, options) => app.app.inject({ method: "PUT", url, ...options }),
77
- patch: async (url, options) => app.app.inject({ method: "PATCH", url, ...options }),
78
- delete: async (url, options) => app.app.inject({ method: "DELETE", url, ...options }),
79
- options: async (url, options) => app.app.inject({ method: "OPTIONS", url, ...options }),
80
- getController: (controller, deps = []) => {
81
- return AvleonTest.getController(controller, deps);
82
- },
83
- };
84
- }
85
- catch (error) {
86
- throw new system_exception_1.SystemUseError("Can't get test appliction");
87
- }
88
- }
89
- static clean() {
90
- typedi_1.default.reset();
91
- }
92
- }
93
- exports.AvleonTest = AvleonTest;
94
- class Avleon {
95
- static createApplication() {
96
- const app = application_1.AvleonApplication.getApp();
97
- return app;
98
- }
99
- static createTestApplication(options) {
100
- const app = AvleonTest.createTestApplication(options);
101
- return app;
102
- }
103
- }
104
- exports.Avleon = Avleon;