@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
package/dist/index.js CHANGED
@@ -1,83 +1,3026 @@
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];
1
+ import { a as __toCommonJS, i as __require, n as __esmMin, o as __toESM, r as __exportAll } from "./chunk-DORXReHP.js";
2
+ import { getMetadataStorage, validateSync } from "class-validator";
3
+ import Container$1, { Container as Container$2, Service, Token } from "typedi";
4
+ import "reflect-metadata";
5
+ import fs, { createReadStream, existsSync } from "node:fs";
6
+ import crypto from "node:crypto";
7
+ import { instanceToPlain, plainToInstance } from "class-transformer";
8
+ import Fastify from "fastify";
9
+ import path from "node:path";
10
+ import mime from "mime";
11
+ import Stream from "node:stream";
12
+ import { AsyncLocalStorage } from "node:async_hooks";
13
+ import Bull from "bull";
14
+ import { pipeline } from "node:stream/promises";
15
+ import dotenv from "dotenv";
16
+ import pino from "pino";
17
+ //#region src/container.ts
18
+ function registerController(controller) {
19
+ controllerRegistry.add(controller);
20
+ }
21
+ function registerService(service) {
22
+ Container.set(service, service);
23
+ serviceRegistry.add(service);
24
+ }
25
+ function getRegisteredServices() {
26
+ return Array.from(serviceRegistry);
27
+ }
28
+ function getRegisteredControllers() {
29
+ return Array.from(controllerRegistry);
30
+ }
31
+ function isApiController(target) {
32
+ return Reflect.getMetadata(API_CONTROLLER_METADATA_KEY, target) === true;
33
+ }
34
+ function registerDataSource(dataSource) {
35
+ Container.set("idatasource", dataSource);
36
+ }
37
+ function registerKnex(dataSource) {
38
+ Container.set("KnexConnection", dataSource);
39
+ }
40
+ var FEATURE_KEY, ROUTE_META_KEY, CONTROLLER_META_KEY, PARAM_META_KEY, QUERY_META_KEY, REQUEST_BODY_META_KEY, REQUEST_BODY_FILE_KEY, REQUEST_BODY_FILES_KEY, REQUEST_USER_META_KEY, REQUEST_HEADER_META_KEY, DATASOURCE_META_KEY, AUTHORIZATION_META_KEY, controllerRegistry, serviceRegistry, Container, API_CONTROLLER_METADATA_KEY;
41
+ var init_container = __esmMin((() => {
42
+ FEATURE_KEY = Symbol.for("features");
43
+ ROUTE_META_KEY = Symbol("iroute:options");
44
+ CONTROLLER_META_KEY = Symbol("icontroller:options");
45
+ PARAM_META_KEY = Symbol("iparam:options");
46
+ QUERY_META_KEY = Symbol("iparam:options");
47
+ REQUEST_BODY_META_KEY = Symbol("iparam:options");
48
+ REQUEST_BODY_FILE_KEY = Symbol("iparam:options");
49
+ REQUEST_BODY_FILES_KEY = Symbol("iparam:options");
50
+ REQUEST_USER_META_KEY = Symbol("iparam:options");
51
+ REQUEST_HEADER_META_KEY = Symbol("iheader:options");
52
+ DATASOURCE_META_KEY = Symbol("idatasource:options");
53
+ AUTHORIZATION_META_KEY = Symbol("idatasource:authorization");
54
+ controllerRegistry = /* @__PURE__ */ new Set();
55
+ serviceRegistry = /* @__PURE__ */ new Set();
56
+ Container = Container$1;
57
+ API_CONTROLLER_METADATA_KEY = Symbol("apiController");
58
+ Container.set("appName", "Iqra");
12
59
  }));
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;
60
+ //#endregion
61
+ //#region src/swagger-schema.ts
62
+ /**
63
+ * @copyright 2024
64
+ * @author Tareq Hossain
65
+ * @email xtrinsic96@gmail.com
66
+ * @url https://github.com/xtareq
67
+ */
68
+ init_container();
69
+ function OpenApiProperty$1(options) {
70
+ return function(target, propertyKey) {
71
+ let meta = options ? { ...options } : {};
72
+ if (meta.format === "binary") if (meta.isArray) meta = {
73
+ ...meta,
74
+ type: "array",
75
+ items: meta.items ?? {
76
+ type: "string",
77
+ format: "binary"
78
+ },
79
+ description: meta.description || "Array of files"
80
+ };
81
+ else meta = {
82
+ ...meta,
83
+ type: "string",
84
+ format: "binary",
85
+ description: meta.description || "File upload"
86
+ };
87
+ Reflect.defineMetadata("property:openapi", meta, target, propertyKey);
88
+ };
89
+ }
90
+ function extractOpenApiFields(meta) {
91
+ const result = {};
92
+ const jsonSchemaFields = [
93
+ "description",
94
+ "deprecated",
95
+ "example",
96
+ "enum",
97
+ "format",
98
+ "default",
99
+ "minimum",
100
+ "maximum",
101
+ "minLength",
102
+ "maxLength",
103
+ "pattern",
104
+ "oneOf",
105
+ "allOf",
106
+ "anyOf",
107
+ "title",
108
+ "readOnly",
109
+ "writeOnly",
110
+ "nullable"
111
+ ];
112
+ const validFormats = [
113
+ "date-time",
114
+ "date",
115
+ "time",
116
+ "duration",
117
+ "email",
118
+ "idn-email",
119
+ "hostname",
120
+ "idn-hostname",
121
+ "ipv4",
122
+ "ipv6",
123
+ "uri",
124
+ "uri-reference",
125
+ "iri",
126
+ "iri-reference",
127
+ "uuid",
128
+ "uri-template",
129
+ "json-pointer",
130
+ "relative-json-pointer",
131
+ "regex",
132
+ "int32",
133
+ "int64",
134
+ "float",
135
+ "double",
136
+ "byte",
137
+ "binary",
138
+ "password"
139
+ ];
140
+ jsonSchemaFields.forEach((field) => {
141
+ if (meta[field] !== void 0) if (field === "format") {
142
+ const formatValue = meta[field];
143
+ if (validFormats.includes(formatValue)) result[field] = formatValue;
144
+ } else result[field] = meta[field];
145
+ });
146
+ return result;
147
+ }
148
+ function CreateSwaggerObjectSchema(classType) {
149
+ const validationMetadata = getMetadataStorage().getTargetValidationMetadatas(classType, "", true, false);
150
+ const schema = {
151
+ type: "object",
152
+ properties: {},
153
+ required: []
154
+ };
155
+ const prototype = classType.prototype;
156
+ const propertyKeys = /* @__PURE__ */ new Set();
157
+ Object.getOwnPropertyNames(prototype).forEach((k) => propertyKeys.add(k));
158
+ Object.keys(prototype).forEach((k) => propertyKeys.add(k));
159
+ validationMetadata.forEach((m) => propertyKeys.add(m.propertyName));
160
+ try {
161
+ const instance = new classType();
162
+ Reflect.ownKeys(instance).forEach((k) => {
163
+ if (typeof k === "string") propertyKeys.add(k);
164
+ });
165
+ } catch (_) {}
166
+ propertyKeys.forEach((propertyName) => {
167
+ if (!propertyName || propertyName === "constructor") return;
168
+ const openApiMeta = Reflect.getMetadata("property:openapi", prototype, propertyName);
169
+ if (openApiMeta?.exclude) return;
170
+ const propertyType = Reflect.getMetadata("design:type", prototype, propertyName);
171
+ let swaggerProperty = {};
172
+ switch (propertyType) {
173
+ case String:
174
+ swaggerProperty.type = "string";
175
+ break;
176
+ case Number:
177
+ swaggerProperty.type = "number";
178
+ break;
179
+ case Boolean:
180
+ swaggerProperty.type = "boolean";
181
+ break;
182
+ case Date:
183
+ swaggerProperty.type = "string";
184
+ swaggerProperty.format = "date-time";
185
+ break;
186
+ case Array:
187
+ swaggerProperty.type = "array";
188
+ swaggerProperty.items = { type: "string" };
189
+ break;
190
+ case Object:
191
+ swaggerProperty = CreateSwaggerObjectSchema(propertyType);
192
+ break;
193
+ default: if (propertyType && typeof propertyType === "function") swaggerProperty.$ref = `#/components/schemas/${propertyType.name}`;
194
+ else swaggerProperty.type = propertyType?.name?.toLowerCase() || "string";
195
+ }
196
+ if (openApiMeta) {
197
+ swaggerProperty = {
198
+ ...swaggerProperty,
199
+ ...openApiMeta,
200
+ ...extractOpenApiFields(openApiMeta)
201
+ };
202
+ if (openApiMeta.format === "binary") if (openApiMeta.isArray || propertyType === Array) swaggerProperty = {
203
+ type: "array",
204
+ items: {
205
+ type: "string",
206
+ format: "binary"
207
+ },
208
+ description: openApiMeta.description || "Array of files"
209
+ };
210
+ else swaggerProperty = {
211
+ type: "string",
212
+ format: "binary",
213
+ description: openApiMeta.description || "File upload"
214
+ };
215
+ }
216
+ schema.properties[propertyName] = swaggerProperty;
217
+ });
218
+ validationMetadata.forEach((meta) => {
219
+ const propertyName = meta.propertyName;
220
+ const property = schema.properties[propertyName];
221
+ if (!property) return;
222
+ switch (meta.name) {
223
+ case "isNotEmpty":
224
+ case "isDefined":
225
+ if (!schema.required.includes(propertyName)) schema.required.push(propertyName);
226
+ break;
227
+ case "isOptional":
228
+ schema.required = schema.required.filter((item) => item !== propertyName);
229
+ break;
230
+ case "minLength":
231
+ property.minLength = meta.constraints[0];
232
+ break;
233
+ case "maxLength":
234
+ property.maxLength = meta.constraints[0];
235
+ break;
236
+ case "min":
237
+ property.minimum = meta.constraints[0];
238
+ break;
239
+ case "max":
240
+ property.maximum = meta.constraints[0];
241
+ break;
242
+ case "isEmail":
243
+ property.format = "email";
244
+ break;
245
+ case "isDate":
246
+ property.format = "date-time";
247
+ break;
248
+ case "isIn":
249
+ property.enum = meta.constraints[0];
250
+ break;
251
+ case "isNumber":
252
+ property.type = "number";
253
+ break;
254
+ case "isInt":
255
+ property.type = "integer";
256
+ break;
257
+ case "isBoolean":
258
+ property.type = "boolean";
259
+ break;
260
+ case "isString":
261
+ property.type = "string";
262
+ break;
263
+ }
264
+ });
265
+ if (schema.required.length === 0) delete schema.required;
266
+ return schema;
267
+ }
268
+ function generateClassSchema(classType) {
269
+ const schema = {
270
+ type: "object",
271
+ properties: {},
272
+ required: []
273
+ };
274
+ if (!classType || !classType.prototype) return schema;
275
+ const validationMetadata = getMetadataStorage().getTargetValidationMetadatas(classType, "", true, false);
276
+ const prototype = classType.prototype;
277
+ const propertyKeys = new Set([...Object.getOwnPropertyNames(prototype), ...validationMetadata.map((m) => m.propertyName)]);
278
+ try {
279
+ const instance = new classType();
280
+ Reflect.ownKeys(instance).forEach((k) => {
281
+ if (typeof k === "string") propertyKeys.add(k);
282
+ });
283
+ } catch (_) {}
284
+ propertyKeys.forEach((propertyName) => {
285
+ if (!propertyName || propertyName === "constructor") return;
286
+ const openApiMeta = Reflect.getMetadata("property:openapi", prototype, propertyName);
287
+ if (openApiMeta?.exclude) return;
288
+ const propertyType = Reflect.getMetadata("design:type", prototype, propertyName);
289
+ let swaggerProperty = {};
290
+ switch (propertyType) {
291
+ case String:
292
+ swaggerProperty.type = "string";
293
+ break;
294
+ case Number:
295
+ swaggerProperty.type = "number";
296
+ break;
297
+ case Boolean:
298
+ swaggerProperty.type = "boolean";
299
+ break;
300
+ case Date:
301
+ swaggerProperty.type = "string";
302
+ swaggerProperty.format = "date-time";
303
+ break;
304
+ case Array:
305
+ swaggerProperty.type = "array";
306
+ swaggerProperty.items = { type: "string" };
307
+ break;
308
+ case Object:
309
+ swaggerProperty = generateClassSchema(propertyType);
310
+ break;
311
+ default: if (propertyType && typeof propertyType === "function") swaggerProperty.$ref = `#/components/schemas/${propertyType.name}`;
312
+ else swaggerProperty.type = propertyType?.name?.toLowerCase() || "string";
313
+ }
314
+ if (openApiMeta) {
315
+ const { required: _required, exclude: _exclude, isArray: _isArray, ...safeOpenApiMeta } = openApiMeta;
316
+ swaggerProperty = {
317
+ ...swaggerProperty,
318
+ ...extractOpenApiFields(safeOpenApiMeta)
319
+ };
320
+ }
321
+ schema.properties[propertyName] = swaggerProperty;
322
+ });
323
+ validationMetadata.forEach((meta) => {
324
+ const propertyName = meta.propertyName;
325
+ if (!schema.properties[propertyName]) schema.properties[propertyName] = { type: "string" };
326
+ switch (meta.name) {
327
+ case "isNotEmpty":
328
+ case "isDefined":
329
+ if (!schema.required.includes(propertyName)) schema.required.push(propertyName);
330
+ break;
331
+ case "isOptional":
332
+ schema.required = schema.required.filter((item) => item !== propertyName);
333
+ break;
334
+ case "minLength":
335
+ schema.properties[propertyName].minLength = meta.constraints[0];
336
+ break;
337
+ case "maxLength":
338
+ schema.properties[propertyName].maxLength = meta.constraints[0];
339
+ break;
340
+ case "min":
341
+ schema.properties[propertyName].minimum = meta.constraints[0];
342
+ break;
343
+ case "max":
344
+ schema.properties[propertyName].maximum = meta.constraints[0];
345
+ break;
346
+ case "isEmail":
347
+ schema.properties[propertyName].format = "email";
348
+ break;
349
+ case "isDate":
350
+ schema.properties[propertyName].format = "date-time";
351
+ break;
352
+ case "isIn":
353
+ schema.properties[propertyName].enum = meta.constraints[0];
354
+ break;
355
+ case "isNumber":
356
+ schema.properties[propertyName].type = "number";
357
+ break;
358
+ case "isInt":
359
+ schema.properties[propertyName].type = "integer";
360
+ break;
361
+ case "isBoolean":
362
+ schema.properties[propertyName].type = "boolean";
363
+ break;
364
+ case "isString":
365
+ schema.properties[propertyName].type = "string";
366
+ break;
367
+ }
368
+ });
369
+ if (schema.required.length === 0) delete schema.required;
370
+ return schema;
371
+ }
372
+ function generateSwaggerSchema(controllers) {
373
+ if (!Array.isArray(controllers)) return generateClassSchema(controllers);
374
+ const components = {};
375
+ for (const controller of controllers) {
376
+ if (!controller || typeof controller !== "function") continue;
377
+ if (!controller.prototype) continue;
378
+ if (Reflect.getMetadata(CONTROLLER_META_KEY, controller)) continue;
379
+ if (!Reflect.getMetadata("openapi:schema", controller)) continue;
380
+ components[controller.name] = generateClassSchema(controller);
381
+ }
382
+ return { components: Object.keys(components).length > 0 ? { schemas: components } : void 0 };
383
+ }
384
+ function OpenApiResponse$1(code = 200, model, description = "Successful response") {
385
+ let dataSchema;
386
+ if (typeof model === "function") dataSchema = generateClassSchema(model);
387
+ else if (model && typeof model === "object") dataSchema = inferSchemaFromExample(model);
388
+ else dataSchema = { type: "string" };
389
+ let message = "OK";
390
+ switch (code) {
391
+ case 400:
392
+ message = "Error";
393
+ description = "Error: Bad Request";
394
+ break;
395
+ case 401:
396
+ message = "Error";
397
+ description = "Error: Unauthorized";
398
+ break;
399
+ case 403:
400
+ message = "Error";
401
+ description = "Error: Forbidden";
402
+ break;
403
+ case 201:
404
+ message = "Created";
405
+ description = "Success: Created";
406
+ break;
407
+ case 500:
408
+ message = "Error";
409
+ description = "Error: InternalError";
410
+ break;
411
+ }
412
+ return {
413
+ description,
414
+ content: { "application/json": { schema: {
415
+ type: "object",
416
+ properties: {
417
+ code: {
418
+ type: "number",
419
+ example: code
420
+ },
421
+ status: {
422
+ type: "string",
423
+ example: message
424
+ },
425
+ data: dataSchema
426
+ }
427
+ } } }
428
+ };
429
+ }
430
+ function inferSchemaFromExample(obj) {
431
+ if (Array.isArray(obj)) return {
432
+ type: "array",
433
+ items: inferSchemaFromExample(obj[0] ?? {})
434
+ };
435
+ if (obj && typeof obj === "object") {
436
+ const properties = {};
437
+ for (const [key, value] of Object.entries(obj)) properties[key] = inferType(value);
438
+ return {
439
+ type: "object",
440
+ properties
441
+ };
442
+ }
443
+ return inferType(obj);
444
+ }
445
+ function inferType(value) {
446
+ switch (typeof value) {
447
+ case "string": return {
448
+ type: "string",
449
+ example: value
450
+ };
451
+ case "number": return {
452
+ type: "number",
453
+ example: value
454
+ };
455
+ case "boolean": return {
456
+ type: "boolean",
457
+ example: value
458
+ };
459
+ case "object":
460
+ if (Array.isArray(value)) return inferSchemaFromExample(value);
461
+ if (value === null) return { type: "null" };
462
+ return inferSchemaFromExample(value);
463
+ default: return { type: "string" };
464
+ }
465
+ }
466
+ //#endregion
467
+ //#region src/controller.ts
468
+ /**
469
+ * @copyright 2024
470
+ * @author Tareq Hossain
471
+ * @email xtrinsic96@gmail.com
472
+ * @url https://github.com/xtareq
473
+ */
474
+ init_container();
475
+ const REQUEST_METADATA_KEY = Symbol("avleon:request");
476
+ function AvleonRequest() {
477
+ return (target, propertyKey, parameterIndex) => {
478
+ const existingParams = Reflect.getMetadata(REQUEST_METADATA_KEY, target, propertyKey) || [];
479
+ existingParams.push({
480
+ index: parameterIndex,
481
+ type: "request"
482
+ });
483
+ Reflect.defineMetadata(REQUEST_METADATA_KEY, existingParams, target, propertyKey);
484
+ };
485
+ }
486
+ function createControllerDecorator(type = "web") {
487
+ return function(pathOrOptions, maybeOptions) {
488
+ return function(target) {
489
+ let path = "/";
490
+ let options = {};
491
+ if (typeof pathOrOptions === "string") {
492
+ path = pathOrOptions;
493
+ options = maybeOptions || {};
494
+ } else if (typeof pathOrOptions === "object") {
495
+ options = pathOrOptions;
496
+ path = options.path || "/";
497
+ }
498
+ Reflect.defineMetadata(API_CONTROLLER_METADATA_KEY, true, target);
499
+ if (typeof Service === "function") {
500
+ registerController(target);
501
+ Service()(target);
502
+ Reflect.defineMetadata(CONTROLLER_META_KEY, {
503
+ type,
504
+ path,
505
+ options
506
+ }, target);
507
+ } else throw new Error("Service decorator is not a function");
508
+ };
509
+ };
510
+ }
511
+ function ApiController(pathOrOptions = "/", mayBeOptions) {
512
+ if (typeof pathOrOptions == "function") {
513
+ Reflect.defineMetadata(API_CONTROLLER_METADATA_KEY, true, pathOrOptions);
514
+ if (typeof Service === "function") {
515
+ registerController(pathOrOptions);
516
+ Service()(pathOrOptions);
517
+ Reflect.defineMetadata(CONTROLLER_META_KEY, {
518
+ type: "api",
519
+ path: "/",
520
+ options: {}
521
+ }, pathOrOptions);
522
+ } else throw new Error("Service decorator is not a function");
523
+ } else {
524
+ if (mayBeOptions) return createControllerDecorator("api")(pathOrOptions, mayBeOptions);
525
+ return createControllerDecorator("api")(pathOrOptions);
526
+ }
527
+ }
528
+ //#endregion
529
+ //#region src/route-methods.ts
530
+ init_container();
531
+ /**
532
+ * Generic Route decorator factory
533
+ */
534
+ function Route(method, pathOrOptions, maybeOptions) {
535
+ return function(target, propertyKey, descriptor) {
536
+ let path = "/";
537
+ let options = {};
538
+ if (typeof pathOrOptions === "string") {
539
+ path = pathOrOptions || "/";
540
+ options = maybeOptions || {};
541
+ } else if (typeof pathOrOptions === "object" && pathOrOptions !== null) {
542
+ options = pathOrOptions;
543
+ path = options.path || options.name || "/";
544
+ } else {
545
+ options = maybeOptions || {};
546
+ path = "/";
547
+ }
548
+ path = typeof path === "string" ? path : "/";
549
+ Reflect.defineMetadata("route:path", path, target, propertyKey);
550
+ Reflect.defineMetadata("route:method", method, target, propertyKey);
551
+ Reflect.defineMetadata(ROUTE_META_KEY, {
552
+ ...options,
553
+ method,
554
+ path,
555
+ controller: target.constructor.name
556
+ }, target, propertyKey);
557
+ if (options) Reflect.defineMetadata("route:options", options, target, propertyKey);
558
+ };
559
+ }
560
+ const Get = (pathOrOptions, maybeOptions) => Route("GET", pathOrOptions, maybeOptions);
561
+ const Post = (pathOrOptions, maybeOptions) => Route("POST", pathOrOptions, maybeOptions);
562
+ const Put = (pathOrOptions, maybeOptions) => Route("PUT", pathOrOptions, maybeOptions);
563
+ const Delete = (pathOrOptions, maybeOptions) => Route("DELETE", pathOrOptions, maybeOptions);
564
+ const Patch = (pathOrOptions, maybeOptions) => Route("PATCH", pathOrOptions, maybeOptions);
565
+ const Options = (pathOrOptions, maybeOptions) => Route("OPTIONS", pathOrOptions, maybeOptions);
566
+ const All = (pathOrOptions, maybeOptions) => Route("ALL", pathOrOptions, maybeOptions);
567
+ //#endregion
568
+ //#region src/openapi.ts
569
+ /**
570
+ * Normalize a flat ParamsSchemaMap into a valid JSON Schema object
571
+ * that Fastify/AJV can validate against.
572
+ *
573
+ * Input: { id: { type: "string", example: "abc-123" } }
574
+ * Output: { type: "object", properties: { id: { type: "string", example: "abc-123" } } }
575
+ */
576
+ function normalizeParamsToJsonSchema(params, requiredKeys = []) {
577
+ const properties = {};
578
+ for (const [key, val] of Object.entries(params)) properties[key] = {
579
+ type: "string",
580
+ ...val
581
+ };
582
+ const schema = {
583
+ type: "object",
584
+ properties
585
+ };
586
+ if (requiredKeys.length > 0) schema.required = requiredKeys;
587
+ return schema;
588
+ }
589
+ function OpenApiSchema() {
590
+ return function(target) {
591
+ Reflect.defineMetadata("openapi:schema", true, target);
592
+ };
593
+ }
594
+ function OpenApi(options) {
595
+ return function(target, propertyKey, descriptor) {
596
+ if (typeof target === "function" && !propertyKey) Reflect.defineMetadata("controller:openapi", options, target);
597
+ else if (descriptor) Reflect.defineMetadata("route:openapi", options, target, propertyKey);
598
+ else if (propertyKey) Reflect.defineMetadata("property:openapi", options, target, propertyKey);
599
+ };
600
+ }
601
+ //#endregion
602
+ //#region src/utils/common-utils.ts
603
+ /**
604
+ * @copyright 2024
605
+ * @author Tareq Hossain
606
+ * @email xtrinsic96@gmail.com
607
+ * @url https://github.com/xtareq
608
+ */
609
+ function isConstructor(func) {
610
+ if (typeof func !== "function") return false;
611
+ if (func === Function.prototype.bind || func instanceof RegExp) return false;
612
+ if (func.prototype && typeof func.prototype === "object") return true;
613
+ try {
614
+ return typeof new func() === "object";
615
+ } catch (e) {
616
+ return false;
617
+ }
618
+ }
619
+ function formatUrl(path) {
620
+ if (typeof path !== "string") throw new Error("The path must be a string");
621
+ path = path.trim();
622
+ if (!path.startsWith("/")) path = "/" + path;
623
+ path = path.replace(/\/\/+/g, "/");
624
+ if (path.endsWith("/")) path = path.slice(0, -1);
625
+ return path;
626
+ }
627
+ function parsedPath(ipath) {
628
+ return !ipath.startsWith("/") ? "/" + ipath : ipath;
629
+ }
630
+ function normalizePath(base = "/", subPath = "/") {
631
+ return `/${base}/${subPath}`.replace(/\/+/g, "/").replace(/\/$/, "");
632
+ }
633
+ function extrctParamFromUrl(url) {
634
+ return url.split("/").filter((x) => x.startsWith(":") || x.startsWith("?:")).map((f) => ({
635
+ key: f.replace(/(\?|:)/g, ""),
636
+ required: !f.startsWith("?:")
637
+ }));
638
+ }
639
+ function findDuplicates(arr) {
640
+ const seen = /* @__PURE__ */ new Set();
641
+ const duplicates = /* @__PURE__ */ new Set();
642
+ for (const str of arr) if (seen.has(str)) duplicates.add(str);
643
+ else seen.add(str);
644
+ return Array.from(duplicates);
645
+ }
646
+ function sleep(ms) {
647
+ return new Promise((resolve) => setTimeout(resolve, ms));
648
+ }
649
+ var uuid, getLineNumber;
650
+ var init_common_utils = __esmMin((() => {
651
+ uuid = crypto.randomUUID();
652
+ getLineNumber = (filePath, rpath) => {
653
+ let numbers = [];
654
+ try {
655
+ const lines = fs.readFileSync(filePath, "utf8").split("\n");
656
+ for (let i = 0; i < lines.length; i++) {
657
+ const match = lines[i].match(rpath);
658
+ if (match) {
659
+ console.log(match);
660
+ numbers.push({
661
+ line: i + 1,
662
+ column: match.index ?? 0
663
+ });
664
+ }
665
+ }
666
+ return numbers;
667
+ } catch (error) {
668
+ return numbers;
669
+ }
670
+ };
671
+ }));
672
+ //#endregion
673
+ //#region src/utils/object-utils.ts
674
+ /**
675
+ * @copyright 2024
676
+ * @author Tareq Hossain
677
+ * @email xtrinsic96@gmail.com
678
+ * @url https://github.com/xtareq
679
+ */
680
+ function pick(obj, paths) {
681
+ const result = {};
682
+ for (const path of paths) {
683
+ const keys = path.split(".");
684
+ let source = obj;
685
+ let target = result;
686
+ for (let i = 0; i < keys.length; i++) {
687
+ const key = keys[i];
688
+ if (!(key in source)) break;
689
+ if (i === keys.length - 1) target[key] = source[key];
690
+ else {
691
+ source = source[key];
692
+ target[key] = target[key] || {};
693
+ target = target[key];
694
+ }
695
+ }
696
+ }
697
+ return result;
698
+ }
699
+ function exclude(obj, paths) {
700
+ if (Array.isArray(obj)) return obj.map((item) => exclude(item, paths));
701
+ const clone = structuredClone(obj);
702
+ for (const path of paths) {
703
+ const keys = path.split(".");
704
+ let target = clone;
705
+ for (let i = 0; i < keys.length - 1; i++) {
706
+ if (!(keys[i] in target)) break;
707
+ target = target[keys[i]];
708
+ }
709
+ delete target?.[keys[keys.length - 1]];
710
+ }
711
+ return clone;
712
+ }
713
+ function autoCast(value, typeHint, schema) {
714
+ if (value === null || value === void 0) return value;
715
+ if (Array.isArray(value)) {
716
+ const elementType = Array.isArray(typeHint) ? typeHint[0] : void 0;
717
+ return value.map((v) => autoCast(v, elementType));
718
+ }
719
+ if (typeof value === "object" && !(value instanceof Date)) {
720
+ const result = {};
721
+ for (const [key, val] of Object.entries(value)) {
722
+ let fieldType = void 0;
723
+ if (schema?.properties?.[key]?.type) {
724
+ const t = schema.properties[key].type;
725
+ fieldType = t === "integer" || t === "number" ? Number : t === "boolean" ? Boolean : t === "array" ? Array : t === "object" ? Object : String;
726
+ }
727
+ result[key] = autoCast(val, fieldType);
728
+ }
729
+ return result;
730
+ }
731
+ if (typeof value !== "string") return value;
732
+ const trimmed = value.trim();
733
+ if (typeHint === Boolean || trimmed.toLowerCase() === "true") return true;
734
+ if (trimmed.toLowerCase() === "false") return false;
735
+ if (typeHint === Number || !isNaN(Number(trimmed)) && trimmed !== "") {
736
+ const n = Number(trimmed);
737
+ if (!isNaN(n)) return n;
738
+ }
739
+ if (trimmed.startsWith("{") && trimmed.endsWith("}") || trimmed.startsWith("[") && trimmed.endsWith("]")) try {
740
+ return autoCast(JSON.parse(trimmed), typeHint, schema);
741
+ } catch {
742
+ return trimmed;
743
+ }
744
+ if (typeHint === Date || /^\d{4}-\d{2}-\d{2}([Tt]\d{2}:\d{2})?/.test(trimmed)) {
745
+ const d = new Date(trimmed);
746
+ if (!isNaN(d.getTime())) return d;
747
+ }
748
+ return trimmed;
749
+ }
750
+ /**
751
+ * Deeply normalizes query strings into nested JS objects.
752
+ */
753
+ function normalizeQueryDeep(query) {
754
+ const result = {};
755
+ const setDeep = (obj, path, value) => {
756
+ let current = obj;
757
+ for (let i = 0; i < path.length; i++) {
758
+ const key = path[i];
759
+ const nextKey = path[i + 1];
760
+ if (i === path.length - 1) if (key === "") {
761
+ if (!Array.isArray(current)) current = [];
762
+ current.push(value);
763
+ } else if (Array.isArray(current[key])) current[key].push(value);
764
+ else if (current[key] !== void 0) current[key] = [current[key], value];
765
+ else current[key] = value;
766
+ else {
767
+ if (!current[key]) current[key] = nextKey === "" || /^\d+$/.test(nextKey) ? [] : {};
768
+ current = current[key];
769
+ }
770
+ }
771
+ };
772
+ for (const [rawKey, rawValue] of Object.entries(query)) {
773
+ const path = [];
774
+ const regex = /([^\[\]]+)|(\[\])/g;
775
+ let match;
776
+ while ((match = regex.exec(rawKey)) !== null) if (match[1]) path.push(match[1]);
777
+ else if (match[2]) path.push("");
778
+ if (path.length === 0) if (result[rawKey]) if (Array.isArray(result[rawKey])) result[rawKey].push(rawValue);
779
+ else result[rawKey] = [result[rawKey], rawValue];
780
+ else result[rawKey] = rawValue;
781
+ else setDeep(result, path, rawValue);
782
+ }
783
+ return result;
784
+ }
785
+ function transformObjectByInstanceToObject(instance, value) {
786
+ return instanceToPlain(plainToInstance(instance, value), {
787
+ excludeExtraneousValues: true,
788
+ exposeUnsetFields: true
789
+ });
790
+ }
791
+ function jsonToJs(value) {
792
+ try {
793
+ return JSON.parse(value);
794
+ } catch (err) {
795
+ return false;
796
+ }
797
+ }
798
+ function jsonToInstance(value, instance) {
799
+ try {
800
+ return plainToInstance(instance, JSON.parse(value));
801
+ } catch (err) {
802
+ return false;
803
+ }
804
+ }
805
+ var init_object_utils = __esmMin((() => {}));
806
+ //#endregion
807
+ //#region src/exceptions/http-exceptions.ts
808
+ var BaseHttpException, BadRequestException, ValidationErrorException, InternalErrorException, NotFoundException, UnauthorizedException, ForbiddenException, HttpExceptions;
809
+ var init_http_exceptions = __esmMin((() => {
810
+ BaseHttpException = class extends Error {
811
+ code = 500;
812
+ name = "HttpException";
813
+ payload;
814
+ constructor(message) {
815
+ const stringMessage = typeof message === "string" ? message : JSON.stringify(message);
816
+ super(stringMessage);
817
+ this.payload = typeof message === "string" ? { message } : message;
818
+ }
819
+ isCustomException() {
820
+ return true;
821
+ }
822
+ };
823
+ BadRequestException = class extends BaseHttpException {
824
+ name = "BadRequest";
825
+ code = 400;
826
+ constructor(message) {
827
+ super(message);
828
+ }
829
+ };
830
+ ValidationErrorException = class extends BadRequestException {
831
+ name = "ValidationError";
832
+ };
833
+ InternalErrorException = class extends BaseHttpException {
834
+ name = "InternalError";
835
+ code = 500;
836
+ constructor(message = "Something going wrong") {
837
+ super(message);
838
+ }
839
+ };
840
+ NotFoundException = class extends BaseHttpException {
841
+ name = "NotFound";
842
+ code = 404;
843
+ constructor(message) {
844
+ super(message);
845
+ }
846
+ };
847
+ UnauthorizedException = class extends BaseHttpException {
848
+ name = "Unauthorized";
849
+ code = 401;
850
+ constructor(message) {
851
+ super(message);
852
+ }
853
+ };
854
+ ForbiddenException = class extends BaseHttpException {
855
+ name = "Forbidden";
856
+ code = 403;
857
+ constructor(message) {
858
+ super(message);
859
+ }
860
+ };
861
+ HttpExceptions = {
862
+ notFound: (message = "") => new NotFoundException(message),
863
+ validationError: (message = "") => new ValidationErrorException(message),
864
+ badRequest: (message = "") => new BadRequestException(message),
865
+ unauthorized: (message = "") => new UnauthorizedException(message),
866
+ forbidden: (message = "") => new ForbiddenException(message),
867
+ internalError: (message = "") => new InternalErrorException(message)
868
+ };
869
+ }));
870
+ //#endregion
871
+ //#region src/exceptions/index.ts
872
+ var init_exceptions = __esmMin((() => {
873
+ init_http_exceptions();
874
+ }));
875
+ //#endregion
876
+ //#region src/utils/validation-utils.ts
877
+ /**
878
+ * @copyright 2024
879
+ * @author Tareq Hossain
880
+ * @email xtrinsic96@gmail.com
881
+ * @url https://github.com/xtareq
882
+ */
883
+ function getDataType(expectedType) {
884
+ switch (expectedType.name) {
885
+ case "Object":
886
+ if (Array.isArray(expectedType)) return "array";
887
+ return "object";
888
+ case "String": return "string";
889
+ case "Number": return "number";
890
+ case "Boolean": return "boolean";
891
+ default: return expectedType;
892
+ }
893
+ }
894
+ function isValidType(value, expectedType) {
895
+ if (value === void 0 || value === null) return true;
896
+ switch (expectedType.name) {
897
+ case "String": return typeof value === "string";
898
+ case "Number": return typeof value === "number" || !isNaN(Number(value));
899
+ case "Boolean": return typeof value === "boolean";
900
+ default: return value instanceof expectedType;
901
+ }
902
+ }
903
+ function isValidJsonString(value) {
904
+ try {
905
+ return JSON.parse(value);
906
+ } catch (err) {
907
+ return false;
908
+ }
909
+ }
910
+ async function validateObjectByInstance(target, value = {}, options = "array") {
911
+ try {
912
+ const { validateOrReject } = __require("class-validator");
913
+ const { plainToInstance } = __require("class-transformer");
914
+ await validateOrReject(plainToInstance(target, value));
915
+ } catch (error) {
916
+ if (typeof error == "object" && Array.isArray(error)) return options == "object" ? error.reduce((acc, x) => {
917
+ acc[x.property] = x.constraints;
918
+ return acc;
919
+ }, {}) : error.map((x) => ({
920
+ path: x.property,
921
+ constraints: x.constraints
922
+ }));
923
+ else throw new InternalErrorException("Can't validate object");
924
+ }
925
+ }
926
+ function validateRequestBody(target, value, options = "array") {
927
+ if (!isClassValidatorClass(target)) return {
928
+ count: 0,
929
+ errors: {}
930
+ };
931
+ const error = validateSync(plainToInstance(target, value ? value : {}));
932
+ const errors = options == "object" ? error.reduce((acc, x) => {
933
+ acc[x.property] = x.constraints;
934
+ return acc;
935
+ }, {}) : error.map((x) => ({
936
+ path: x.property,
937
+ constraints: x.constraints
938
+ }));
939
+ return {
940
+ count: error.length,
941
+ errors
942
+ };
943
+ }
944
+ var isClassValidator, isClassValidatorClass;
945
+ var init_validation_utils = __esmMin((() => {
946
+ init_exceptions();
947
+ isClassValidator = (target) => {
948
+ try {
949
+ __require("class-validator");
950
+ return getMetadataStorage().getTargetValidationMetadatas(target, "", false, false).length > 0;
951
+ } catch (err) {
952
+ console.log(err);
953
+ return false;
954
+ }
955
+ };
956
+ isClassValidatorClass = (target) => {
957
+ try {
958
+ return __require("class-validator").getMetadataStorage().getTargetValidationMetadatas(target, void 0, false, false).length > 0;
959
+ } catch (err) {
960
+ return false;
961
+ }
962
+ };
963
+ }));
964
+ //#endregion
965
+ //#region src/exceptions/system-exception.ts
966
+ var SystemUseError, EnvironmentVariableNotFound;
967
+ var init_system_exception = __esmMin((() => {
968
+ SystemUseError = class extends Error {
969
+ constructor(message) {
970
+ super(message);
971
+ }
972
+ };
973
+ EnvironmentVariableNotFound = class extends Error {
974
+ constructor(key) {
975
+ super(`${key} not found in environment variables.`);
976
+ }
977
+ };
978
+ }));
979
+ //#endregion
980
+ //#region src/utils/di-utils.ts
981
+ function inject(cls) {
982
+ try {
983
+ return Container.get(cls);
984
+ } catch (error) {
985
+ throw new SystemUseError("Not a project class. Maybe you wanna register it first.");
986
+ }
987
+ }
988
+ var init_di_utils = __esmMin((() => {
989
+ init_container();
990
+ init_system_exception();
991
+ }));
992
+ //#endregion
993
+ //#region src/validation.ts
994
+ function validateOrThrow(obj, rules, options) {
995
+ const errors = new Validator(rules, options).validate(obj);
996
+ if (errors[0].length > 0) throw new BadRequestException(errors[0]);
997
+ return errors[1];
998
+ }
999
+ var PValidationRule, Validator, isBool, parseBoolean;
1000
+ var init_validation = __esmMin((() => {
1001
+ init_exceptions();
1002
+ PValidationRule = class {
1003
+ name;
1004
+ type;
1005
+ message;
1006
+ constructor(name, type, message) {
1007
+ this.name = name;
1008
+ this.type = type;
1009
+ this.message = message;
1010
+ }
1011
+ };
1012
+ Validator = class {
1013
+ rules = [];
1014
+ options = {};
1015
+ constructor(obj, options) {
1016
+ this.init(obj);
1017
+ if (options) this.options = options;
1018
+ }
1019
+ init(obj) {
1020
+ Object.keys(obj).forEach((key) => {
1021
+ const rule = obj[key];
1022
+ this.rules.push(new PValidationRule(key, rule.type, rule.message));
1023
+ });
1024
+ }
1025
+ validate(obj, options) {
1026
+ const erors = [];
1027
+ this.rules.forEach((k) => {
1028
+ const r = Object.keys(obj).find((key) => key == k.name);
1029
+ let messages = [];
1030
+ if (!r || obj[r] == void 0 || obj[r] == "") messages.push({
1031
+ constraint: "required",
1032
+ message: k.name + " is required"
1033
+ });
1034
+ if (k.type == "string" && typeof obj[k.name] != "string") messages.push({
1035
+ constraint: "type",
1036
+ message: `${k.name} must be type ${k.type}`
1037
+ });
1038
+ if (k.type == "number" && !parseInt(obj[k.name])) messages.push({
1039
+ constraint: "type",
1040
+ message: `${k.name} must be type ${k.type}`
1041
+ });
1042
+ if (k.type == "number") obj[k.name] = parseInt(obj[k.name]);
1043
+ if (k.type == "boolean" && !isBool(obj[k.name])) messages.push({
1044
+ constraint: "type",
1045
+ message: `${k.name} must be type ${k.type}`
1046
+ });
1047
+ if (k.type == "boolean") obj[k.name] = parseBoolean(obj[k.name]);
1048
+ if (messages.length > 0) erors.push({
1049
+ path: k.name,
1050
+ ...this.options.location ? { location: this.options.location } : {},
1051
+ constraints: messages
1052
+ });
1053
+ });
1054
+ return [erors, obj];
1055
+ }
1056
+ };
1057
+ isBool = (val) => {
1058
+ if (typeof val == "boolean") return true;
1059
+ if (parseInt(val) == 0 || parseInt(val) == 1) return true;
1060
+ if (val == "true" || val == "false") return true;
1061
+ return false;
1062
+ };
1063
+ parseBoolean = (val) => {
1064
+ if (typeof val === "boolean") return val;
1065
+ if (parseInt(val) == 1) return true;
1066
+ if (typeof val === "string") return val.trim().toLowerCase() === "true";
1067
+ return false;
1068
+ };
1069
+ }));
1070
+ //#endregion
1071
+ //#region src/helpers.ts
1072
+ var init_helpers = __esmMin((() => {
1073
+ init_common_utils();
1074
+ init_object_utils();
1075
+ init_validation_utils();
1076
+ init_di_utils();
1077
+ init_validation();
1078
+ }));
1079
+ //#endregion
1080
+ //#region src/params.ts
1081
+ init_container();
1082
+ init_helpers();
1083
+ function createParamDecorator(type) {
1084
+ return function(key, options = {}) {
1085
+ return function(target, propertyKey, parameterIndex) {
1086
+ let metaKey;
1087
+ switch (type) {
1088
+ case "route:param":
1089
+ metaKey = PARAM_META_KEY;
1090
+ break;
1091
+ case "route:query":
1092
+ metaKey = QUERY_META_KEY;
1093
+ break;
1094
+ case "route:body":
1095
+ metaKey = REQUEST_BODY_META_KEY;
1096
+ break;
1097
+ case "route:user":
1098
+ metaKey = REQUEST_USER_META_KEY;
1099
+ break;
1100
+ case "route:header":
1101
+ metaKey = REQUEST_HEADER_META_KEY;
1102
+ break;
1103
+ default: throw new Error(`Unknown param decorator type: ${String(type)}`);
1104
+ }
1105
+ const existingParams = Reflect.getMetadata(metaKey, target, propertyKey) || [];
1106
+ const paramNames = target[propertyKey].toString().match(/\(([^)]*)\)/)?.[1]?.split(",").map((n) => n.trim()) || [];
1107
+ const paramDataType = (Reflect.getMetadata("design:paramtypes", target, propertyKey) || [])[parameterIndex];
1108
+ existingParams.push({
1109
+ index: parameterIndex,
1110
+ key: typeof key === "string" ? key : "all",
1111
+ name: paramNames[parameterIndex],
1112
+ required: options.required ?? true,
1113
+ validate: options.validate ?? true,
1114
+ dataType: getDataType(paramDataType),
1115
+ validatorClass: isClassValidatorClass(paramDataType),
1116
+ schema: isClassValidatorClass(paramDataType) ? generateClassSchema(paramDataType) : null,
1117
+ type
1118
+ });
1119
+ Reflect.defineMetadata(metaKey, existingParams, target, propertyKey);
1120
+ };
1121
+ };
1122
+ }
1123
+ const Param = createParamDecorator("route:param");
1124
+ const Query = createParamDecorator("route:query");
1125
+ const Body = createParamDecorator("route:body");
1126
+ const Header = createParamDecorator("route:header");
1127
+ const AuthUser = createParamDecorator("route:user");
1128
+ //#endregion
1129
+ //#region src/decorators.ts
1130
+ /**
1131
+ * @copyright 2024
1132
+ * @author Tareq Hossain
1133
+ * @email xtrinsic96@gmail.com
1134
+ * @url https://github.com/xtareq
1135
+ */
1136
+ function AppService(target) {
1137
+ if (target) Service()(target);
1138
+ else return function(tg) {
1139
+ Service()(tg);
1140
+ };
1141
+ }
1142
+ const Utility = Service;
1143
+ const Helper = Service;
1144
+ //#endregion
1145
+ //#region src/core/router.ts
1146
+ init_helpers();
1147
+ init_container();
1148
+ init_exceptions();
1149
+ /**
1150
+ * Normalize a flat params/query map like:
1151
+ * { id: { type: "string", example: "abc-123" } }
1152
+ * into a valid AJV/JSON Schema object:
1153
+ * { type: "object", properties: { id: { type: "string", example: "abc-123" } } }
1154
+ */
1155
+ function normalizeParamsToJsonSchema$1(map, requiredKeys = []) {
1156
+ const properties = {};
1157
+ for (const [key, val] of Object.entries(map)) {
1158
+ const { required, ...rest } = val;
1159
+ properties[key] = {
1160
+ type: "string",
1161
+ ...rest
1162
+ };
1163
+ }
1164
+ const schema = {
1165
+ type: "object",
1166
+ properties
1167
+ };
1168
+ if (requiredKeys.length > 0) schema.required = requiredKeys;
1169
+ return schema;
1170
+ }
1171
+ /**
1172
+ * Take a raw @OpenApi schema object and return a Fastify-compatible
1173
+ * route schema — normalizing params, query → querystring, and headers.
1174
+ */
1175
+ function buildRouteSchema(raw) {
1176
+ const schema = { ...raw };
1177
+ if (raw.params && typeof raw.params === "object" && !raw.params.type) {
1178
+ const required = Object.entries(raw.params).filter(([, v]) => v.required !== false).map(([k]) => k);
1179
+ schema.params = normalizeParamsToJsonSchema$1(raw.params, required);
1180
+ }
1181
+ if (raw.query && typeof raw.query === "object" && !raw.query.type) {
1182
+ const required = Object.entries(raw.query).filter(([, v]) => v.required === true).map(([k]) => k);
1183
+ schema.querystring = normalizeParamsToJsonSchema$1(raw.query, required);
1184
+ delete schema.query;
1185
+ }
1186
+ if (raw.headers && typeof raw.headers === "object" && !raw.headers.type) schema.headers = normalizeParamsToJsonSchema$1(raw.headers);
1187
+ return schema;
1188
+ }
1189
+ var AvleonRouter = class {
1190
+ routeSet = /* @__PURE__ */ new Set();
1191
+ metaCache = /* @__PURE__ */ new Map();
1192
+ middlewares = /* @__PURE__ */ new Map();
1193
+ rMap = /* @__PURE__ */ new Map();
1194
+ app;
1195
+ authorizeMiddleware;
1196
+ constructor(app) {
1197
+ this.app = app;
1198
+ }
1199
+ setAuthorizeMiddleware(middleware) {
1200
+ this.authorizeMiddleware = middleware;
1201
+ }
1202
+ registerMiddleware(name, instance) {
1203
+ this.middlewares.set(name, instance);
1204
+ }
1205
+ _processMeta(prototype, method) {
1206
+ const cacheKey = `${prototype.constructor.name}_${method}`;
1207
+ if (this.metaCache.has(cacheKey)) return this.metaCache.get(cacheKey);
1208
+ const meta = {
1209
+ request: Reflect.getMetadata(REQUEST_METADATA_KEY, prototype, method) || [],
1210
+ params: Reflect.getMetadata(PARAM_META_KEY, prototype, method) || [],
1211
+ query: Reflect.getMetadata(QUERY_META_KEY, prototype, method) || [],
1212
+ body: Reflect.getMetadata(REQUEST_BODY_META_KEY, prototype, method) || [],
1213
+ file: Reflect.getMetadata(REQUEST_BODY_FILE_KEY, prototype, method) || [],
1214
+ files: Reflect.getMetadata(REQUEST_BODY_FILES_KEY, prototype, method) || [],
1215
+ headers: Reflect.getMetadata(REQUEST_HEADER_META_KEY, prototype, method) || [],
1216
+ currentUser: Reflect.getMetadata(REQUEST_USER_META_KEY, prototype, method) || []
1217
+ };
1218
+ this.metaCache.set(cacheKey, meta);
1219
+ return meta;
1220
+ }
1221
+ executeMiddlewares(target, propertyKey) {
1222
+ const classMiddlewares = Reflect.getMetadata("controller:middleware", target.constructor) || [];
1223
+ const methodMiddlewares = propertyKey ? Reflect.getMetadata("route:middleware", target, propertyKey) || [] : [];
1224
+ return [...classMiddlewares, ...methodMiddlewares];
1225
+ }
1226
+ async buildController(controller) {
1227
+ const ctrl = Container$1.get(controller);
1228
+ const controllerMeta = Reflect.getMetadata(CONTROLLER_META_KEY, ctrl.constructor);
1229
+ if (!controllerMeta) return;
1230
+ const prototype = Object.getPrototypeOf(ctrl);
1231
+ const methods = Object.getOwnPropertyNames(prototype).filter((name) => name !== "constructor");
1232
+ const tag = ctrl.constructor.name.replace("Controller", "");
1233
+ const swaggerControllerMeta = Reflect.getMetadata("controller:openapi", ctrl.constructor) || {};
1234
+ const authClsMeata = Reflect.getMetadata(AUTHORIZATION_META_KEY, ctrl.constructor) || {
1235
+ authorize: false,
1236
+ options: void 0
1237
+ };
1238
+ for await (const method of methods) {
1239
+ const methodMeta = Reflect.getMetadata(ROUTE_META_KEY, prototype, method);
1240
+ if (!methodMeta) continue;
1241
+ const methodmetaOptions = {
1242
+ method: methodMeta.method.toLowerCase(),
1243
+ path: formatUrl(controllerMeta.path + methodMeta.path)
1244
+ };
1245
+ const routeKey = `${methodmetaOptions.method}:${methodmetaOptions.path}`;
1246
+ if (!this.routeSet.has(routeKey)) this.routeSet.add(routeKey);
1247
+ const classMiddlewares = this.executeMiddlewares(ctrl, method);
1248
+ const swaggerMeta = Reflect.getMetadata("route:openapi", prototype, method) || {};
1249
+ const authClsMethodMeata = Reflect.getMetadata(AUTHORIZATION_META_KEY, ctrl.constructor, method) || {
1250
+ authorize: false,
1251
+ options: void 0
1252
+ };
1253
+ const allMeta = this._processMeta(prototype, method);
1254
+ let bodySchema = null;
1255
+ allMeta.body.forEach((r) => {
1256
+ if (r.schema) bodySchema = { ...r.schema };
1257
+ });
1258
+ let schema = {
1259
+ ...swaggerControllerMeta,
1260
+ ...swaggerMeta,
1261
+ tags: [tag]
1262
+ };
1263
+ if (!swaggerMeta.body && bodySchema) schema = {
1264
+ ...schema,
1265
+ body: bodySchema
1266
+ };
1267
+ if (!swaggerMeta.query && !schema.querystring) {
1268
+ for (const queryMeta of allMeta.query) if (queryMeta.validatorClass && queryMeta.schema) {
1269
+ schema.querystring = queryMeta.schema;
1270
+ break;
1271
+ }
1272
+ }
1273
+ if (!swaggerMeta.body && !bodySchema) {
1274
+ for (const bodyMeta of allMeta.body) if (bodyMeta.validatorClass && bodyMeta.schema) {
1275
+ schema = {
1276
+ ...schema,
1277
+ body: bodyMeta.schema
1278
+ };
1279
+ break;
1280
+ }
1281
+ }
1282
+ const routePath = methodmetaOptions.path === "" ? "/" : methodmetaOptions.path;
1283
+ const isMultipart = schema?.consumes?.includes("multipart/form-data") || Object.values(schema?.body?.properties || {}).some((p) => p.format === "binary");
1284
+ if (isMultipart) {
1285
+ schema.consumes = ["multipart/form-data"];
1286
+ if (!schema.body) schema.body = {
1287
+ type: "object",
1288
+ properties: {}
1289
+ };
1290
+ for (const param of allMeta.body) if (param.type === "route:file") schema.body.properties[param.key] = {
1291
+ type: "string",
1292
+ format: "binary"
1293
+ };
1294
+ else schema.body.properties[param.key] = { type: param.dataType };
1295
+ }
1296
+ const routeSchema = buildRouteSchema(schema);
1297
+ this.app.route({
1298
+ url: routePath,
1299
+ method: methodmetaOptions.method.toUpperCase(),
1300
+ schema: routeSchema,
1301
+ attachValidation: isMultipart,
1302
+ handler: async (req, res) => {
1303
+ let reqClone = req;
1304
+ if (authClsMeata.authorize && this.authorizeMiddleware) {
1305
+ await Container.get(this.authorizeMiddleware).authorize(reqClone, authClsMeata.options);
1306
+ if (res.sent) return;
1307
+ }
1308
+ if (authClsMethodMeata.authorize && this.authorizeMiddleware) {
1309
+ await Container.get(this.authorizeMiddleware).authorize(reqClone, authClsMethodMeata.options);
1310
+ if (res.sent) return;
1311
+ }
1312
+ if (classMiddlewares.length > 0) for (let m of classMiddlewares) {
1313
+ reqClone = await Container$1.get(m.constructor).invoke(reqClone, res);
1314
+ if (res.sent) return;
1315
+ }
1316
+ const args = await this._mapArgs(reqClone, allMeta);
1317
+ for (let paramMeta of allMeta.params) if (paramMeta.required) validateOrThrow({ [paramMeta.key]: args[paramMeta.index] }, { [paramMeta.key]: { type: paramMeta.dataType } }, { location: "param" });
1318
+ for (let queryMeta of allMeta.query) {
1319
+ if (queryMeta.validatorClass) {
1320
+ const err = await validateObjectByInstance(queryMeta.dataType, args[queryMeta.index]);
1321
+ if (err) return await res.code(400).send({
1322
+ code: 400,
1323
+ error: "ValidationError",
1324
+ errors: err,
1325
+ message: err.message
1326
+ });
1327
+ }
1328
+ if (queryMeta.required) validateOrThrow({ [queryMeta.key]: args[queryMeta.index] }, { [queryMeta.key]: { type: queryMeta.dataType } }, { location: "queryparam" });
1329
+ }
1330
+ if (!isMultipart) {
1331
+ for (let bodyMeta of allMeta.body) if (bodyMeta.validatorClass) {
1332
+ const err = await validateObjectByInstance(bodyMeta.dataType, args[bodyMeta.index]);
1333
+ if (err) return await res.code(400).send({
1334
+ code: 400,
1335
+ error: "ValidationError",
1336
+ errors: err,
1337
+ message: err.message
1338
+ });
1339
+ }
1340
+ }
1341
+ const result = await prototype[method].apply(ctrl, args);
1342
+ if (result?.download) {
1343
+ const { stream, filename } = result;
1344
+ if (!stream || typeof stream.pipe !== "function") return res.code(500).send({
1345
+ code: 500,
1346
+ error: "INTERNAL_ERROR",
1347
+ message: "Invalid stream object"
1348
+ });
1349
+ const contentType = result.contentType || mime.getType(filename) || "application/octet-stream";
1350
+ res.header("Content-Type", contentType);
1351
+ res.header("Content-Disposition", `attachment; filename="${filename}"`);
1352
+ stream.on("error", (err) => {
1353
+ console.error("Stream error:", err);
1354
+ if (!res.sent) res.code(500).send({
1355
+ code: 500,
1356
+ error: "StreamError",
1357
+ message: "Error while streaming file."
1358
+ });
1359
+ });
1360
+ return res.send(stream);
1361
+ }
1362
+ if (result instanceof Stream || typeof result?.pipe === "function") {
1363
+ result.on("error", (err) => {
1364
+ console.error("Stream error:", err);
1365
+ if (!res.sent) res.code(500).send({
1366
+ code: 500,
1367
+ error: "StreamError",
1368
+ message: "Error while streaming file."
1369
+ });
1370
+ });
1371
+ res.header("Content-Type", "application/octet-stream");
1372
+ return res.send(result);
1373
+ }
1374
+ return res.send(result);
1375
+ }
1376
+ });
1377
+ }
1378
+ }
1379
+ async _mapArgs(req, meta) {
1380
+ if (!req.hasOwnProperty("_argsCache")) Object.defineProperty(req, "_argsCache", {
1381
+ value: /* @__PURE__ */ new Map(),
1382
+ enumerable: false,
1383
+ writable: false,
1384
+ configurable: false
1385
+ });
1386
+ const cache = req._argsCache;
1387
+ const cacheKey = JSON.stringify(meta);
1388
+ if (cache.has(cacheKey)) return cache.get(cacheKey);
1389
+ 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), ...meta.request?.map((r) => r.index) || [], ...meta.file?.map((f) => f.index) || [], ...meta.files?.map((f) => f.index) || [], -1) + 1;
1390
+ const args = new Array(maxIndex).fill(void 0);
1391
+ meta.params.forEach((p) => {
1392
+ const raw = p.key === "all" ? { ...req.params } : req.params[p.key] ?? null;
1393
+ args[p.index] = autoCast(raw, p.dataType, p.schema);
1394
+ });
1395
+ meta.query.forEach((q) => {
1396
+ const raw = q.key === "all" ? normalizeQueryDeep({ ...req.query }) : req.query[q.key];
1397
+ args[q.index] = autoCast(raw, q.dataType, q.schema);
1398
+ });
1399
+ meta.body.forEach((body) => {
1400
+ args[body.index] = {
1401
+ ...req.body,
1402
+ ...req.formData
1403
+ };
1404
+ });
1405
+ meta.currentUser.forEach((user) => {
1406
+ args[user.index] = req.user;
1407
+ });
1408
+ meta.headers.forEach((header) => {
1409
+ args[header.index] = header.key === "all" ? { ...req.headers } : req.headers[header.key];
1410
+ });
1411
+ if (meta.request && meta.request.length > 0) meta.request.forEach((r) => {
1412
+ args[r.index] = req;
1413
+ });
1414
+ const needsFiles = meta.file && meta.file.length > 0 || meta.files && meta.files.length > 0;
1415
+ if (needsFiles && req.headers["content-type"]?.startsWith("multipart/form-data") && req.saveRequestFiles) {
1416
+ const files = await req.saveRequestFiles();
1417
+ if (!files || files.length === 0) {
1418
+ if (meta.files && meta.files.length > 0) throw new BadRequestException({ error: "No files uploaded" });
1419
+ if (meta.file && meta.file.length > 0) meta.file.forEach((f) => {
1420
+ args[f.index] = null;
1421
+ });
1422
+ } else {
1423
+ const fileInfo = files.map((file) => ({
1424
+ type: file.type,
1425
+ filepath: file.filepath,
1426
+ fieldname: file.fieldname,
1427
+ filename: file.filename,
1428
+ encoding: file.encoding,
1429
+ mimetype: file.mimetype,
1430
+ fields: file.fields,
1431
+ toBuffer: file.toBuffer
1432
+ }));
1433
+ if (meta.file && meta.file.length > 0) meta.file.forEach((f) => {
1434
+ if (f.fieldName === "all") args[f.index] = fileInfo[0] || null;
1435
+ else {
1436
+ const file = fileInfo.find((x) => x.fieldname === f.fieldName);
1437
+ if (!file) throw new BadRequestException(`File field "${f.fieldName}" not found in uploaded files`);
1438
+ args[f.index] = file;
1439
+ }
1440
+ });
1441
+ if (meta.files && meta.files.length > 0) meta.files.forEach((f) => {
1442
+ if (f.fieldName === "all") args[f.index] = fileInfo;
1443
+ else {
1444
+ const matchingFiles = fileInfo.filter((x) => x.fieldname === f.fieldName);
1445
+ if (matchingFiles.length === 0) throw new BadRequestException(`No files found for field "${f.fieldName}"`);
1446
+ args[f.index] = matchingFiles;
1447
+ }
1448
+ });
1449
+ }
1450
+ } else if (needsFiles) throw new BadRequestException({ error: "Invalid content type. Expected multipart/form-data for file uploads" });
1451
+ cache.set(cacheKey, args);
1452
+ return args;
1453
+ }
1454
+ _routeHandler(routePath, method, fn) {
1455
+ const routeKey = method + ":" + routePath;
1456
+ this.rMap.set(routeKey, {
1457
+ handler: fn,
1458
+ middlewares: [],
1459
+ schema: {}
1460
+ });
1461
+ const route = {
1462
+ useMiddleware: (middlewares) => {
1463
+ const ms = (Array.isArray(middlewares) ? middlewares : [middlewares]).map((mclass) => {
1464
+ const cls = Container$1.get(mclass);
1465
+ this.middlewares.set(mclass.name, cls);
1466
+ return cls.invoke;
1467
+ });
1468
+ const r = this.rMap.get(routeKey);
1469
+ if (r) r.middlewares = ms;
1470
+ return route;
1471
+ },
1472
+ useOpenApi: (options) => {
1473
+ const r = this.rMap.get(routeKey);
1474
+ if (r) r.schema = options;
1475
+ return route;
1476
+ }
1477
+ };
1478
+ return route;
1479
+ }
1480
+ mapGet(path = "", fn) {
1481
+ return this._routeHandler(path, "GET", fn);
1482
+ }
1483
+ mapPost(path = "", fn) {
1484
+ return this._routeHandler(path, "POST", fn);
1485
+ }
1486
+ mapPut(path = "", fn) {
1487
+ return this._routeHandler(path, "PUT", fn);
1488
+ }
1489
+ mapDelete(path = "", fn) {
1490
+ return this._routeHandler(path, "DELETE", fn);
1491
+ }
1492
+ async mapRoute(method, path = "", fn) {
1493
+ this.app[method](path, async (req, res) => {
1494
+ try {
1495
+ const result = await fn(req, res);
1496
+ if (typeof result === "object" && result !== null) res.json(result);
1497
+ else res.send(result);
1498
+ } catch (error) {
1499
+ console.error(`Error in ${method} route handler:`, error);
1500
+ res.status(500).send({ error: "Internal Server Error" });
1501
+ }
1502
+ });
1503
+ }
1504
+ processFunctionalRoutes() {
1505
+ this.rMap.forEach((value, key) => {
1506
+ const colonIdx = key.indexOf(":");
1507
+ const m = key.slice(0, colonIdx);
1508
+ const r = key.slice(colonIdx + 1);
1509
+ const routeSchema = buildRouteSchema(value.schema || {});
1510
+ this.app.route({
1511
+ method: m.toUpperCase(),
1512
+ url: r,
1513
+ schema: routeSchema,
1514
+ preHandler: value.middlewares ?? [],
1515
+ handler: async (req, res) => {
1516
+ return value.handler(req, res);
1517
+ }
1518
+ });
1519
+ });
1520
+ }
1521
+ };
1522
+ //#endregion
1523
+ //#region \0@oxc-project+runtime@0.121.0/helpers/decorateMetadata.js
1524
+ function __decorateMetadata(k, v) {
1525
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
1526
+ }
1527
+ var init_decorateMetadata = __esmMin((() => {}));
1528
+ //#endregion
1529
+ //#region \0@oxc-project+runtime@0.121.0/helpers/decorate.js
1530
+ function __decorate(decorators, target, key, desc) {
1531
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1532
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1533
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1534
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1535
+ }
1536
+ var init_decorate = __esmMin((() => {}));
1537
+ //#endregion
1538
+ //#region src/kenx-provider.ts
1539
+ var kenx_provider_exports = /* @__PURE__ */ __exportAll({ DB: () => DB });
1540
+ var DB;
1541
+ var init_kenx_provider = __esmMin((() => {
1542
+ init_decorateMetadata();
1543
+ init_decorate();
1544
+ DB = class DB {
1545
+ connection;
1546
+ constructor() {
1547
+ const existing = Container$2.has("KnexConnection") ? Container$2.get("KnexConnection") : null;
1548
+ if (existing) this.connection = existing;
1549
+ }
1550
+ init(config) {
1551
+ if (!this.connection) {
1552
+ this.connection = __require("knex")(config);
1553
+ Container$2.set("KnexConnection", this.connection);
1554
+ }
1555
+ return this.connection;
1556
+ }
1557
+ get client() {
1558
+ if (!this.connection) throw new Error("Knex is not initialized. Call DB.init(config) first.");
1559
+ return this.connection;
1560
+ }
1561
+ };
1562
+ DB = __decorate([Service(), __decorateMetadata("design:paramtypes", [])], DB);
1563
+ }));
1564
+ //#endregion
1565
+ //#region src/websocket.ts
1566
+ var websocket_exports = /* @__PURE__ */ __exportAll({
1567
+ AvleonSocketIo: () => AvleonSocketIo,
1568
+ SocketIoServer: () => SocketIoServer
1569
+ });
1570
+ var SocketIoServer, AvleonSocketIo;
1571
+ var init_websocket = __esmMin((() => {
1572
+ init_decorate();
1573
+ SocketIoServer = new Token("SocketIoServer");
1574
+ AvleonSocketIo = class AvleonSocketIo {
1575
+ io;
1576
+ sendToAll() {}
1577
+ sendOnly() {}
1578
+ sendRoom() {}
1579
+ receive(channel) {}
1580
+ };
1581
+ AvleonSocketIo = __decorate([Service()], AvleonSocketIo);
1582
+ }));
1583
+ //#endregion
1584
+ //#region src/event-dispatcher.ts
1585
+ var event_dispatcher_exports = /* @__PURE__ */ __exportAll({
1586
+ Dispatch: () => Dispatch,
1587
+ EventDispatcher: () => EventDispatcher,
1588
+ SocketContextService: () => SocketContextService
1589
+ });
1590
+ function Dispatch(event, options) {
1591
+ return function(target, propertyKey, descriptor) {
1592
+ const original = descriptor.value;
1593
+ descriptor.value = async function(...args) {
1594
+ const result = await original.apply(this, args);
1595
+ await Container$2.get(EventDispatcher).dispatch(event, result, options);
1596
+ return result;
1597
+ };
1598
+ };
1599
+ }
1600
+ var _ref$1, SocketContextService, EventDispatcher;
1601
+ var init_event_dispatcher = __esmMin((() => {
1602
+ init_websocket();
1603
+ init_helpers();
1604
+ init_decorate();
1605
+ init_decorateMetadata();
1606
+ SocketContextService = class SocketContextService {
1607
+ storage = new AsyncLocalStorage();
1608
+ run(socket, fn) {
1609
+ this.storage.run({ socket }, fn);
1610
+ }
1611
+ getSocket() {
1612
+ return this.storage.getStore()?.socket;
1613
+ }
1614
+ };
1615
+ SocketContextService = __decorate([Service()], SocketContextService);
1616
+ EventDispatcher = class EventDispatcher {
1617
+ constructor(_context) {
1618
+ this._context = _context;
1619
+ }
1620
+ async dispatch(event, data, options = {}) {
1621
+ const retryCount = options.retry ?? 0;
1622
+ const delay = options.retryDelay ?? 300;
1623
+ for (let attempt = 0; attempt <= retryCount; attempt++) try {
1624
+ await this.dispatchToTransports(event, data, options);
1625
+ break;
1626
+ } catch (err) {
1627
+ if (attempt === retryCount) throw err;
1628
+ await sleep(delay * (attempt + 1));
1629
+ }
1630
+ }
1631
+ async dispatchToTransports(event, data, options) {
1632
+ const transports = options.transports ?? ["socket"];
1633
+ for (const transport of transports) if (transport === "socket") {
1634
+ const io = Container$2.get(SocketIoServer);
1635
+ const socket = Container$2.get(SocketContextService).getSocket();
1636
+ if (options.broadcast && socket) if (options.room) socket.broadcast.to(options.room).emit(event, data);
1637
+ else socket.broadcast.emit(event, data);
1638
+ else if (options.room) io.to(options.room).emit(event, data);
1639
+ else io.emit(event, data);
1640
+ }
1641
+ }
1642
+ };
1643
+ EventDispatcher = __decorate([Service(), __decorateMetadata("design:paramtypes", [typeof (_ref$1 = typeof SocketContextService !== "undefined" && SocketContextService) === "function" ? _ref$1 : Object])], EventDispatcher);
1644
+ }));
1645
+ //#endregion
1646
+ //#region src/event-subscriber.ts
1647
+ var event_subscriber_exports = /* @__PURE__ */ __exportAll({
1648
+ EventSubscriberRegistry: () => EventSubscriberRegistry,
1649
+ Private: () => Private,
1650
+ Subscribe: () => Subscribe,
1651
+ getPrivateChannelResolver: () => getPrivateChannelResolver,
1652
+ getSocketSubscribers: () => getSocketSubscribers,
1653
+ isPrivate: () => isPrivate,
1654
+ registerSocketSubscriber: () => registerSocketSubscriber
1655
+ });
1656
+ function Private(channelResolver) {
1657
+ return function(target, propertyKey) {
1658
+ Reflect.defineMetadata(PRIVATE_META_KEY, true, target, propertyKey);
1659
+ Reflect.defineMetadata(`private:channel:${propertyKey}`, channelResolver, target);
1660
+ };
1661
+ }
1662
+ function isPrivate(target, propertyKey) {
1663
+ return Reflect.getMetadata(PRIVATE_META_KEY, target, propertyKey) || false;
1664
+ }
1665
+ function getPrivateChannelResolver(target, propertyKey) {
1666
+ return Reflect.getMetadata(`private:channel:${propertyKey}`, target);
1667
+ }
1668
+ function registerSocketSubscriber(target) {
1669
+ socketSubscriberClasses.add(target);
1670
+ }
1671
+ function getSocketSubscribers() {
1672
+ return Array.from(socketSubscriberClasses);
1673
+ }
1674
+ function Subscribe(event) {
1675
+ return (target, propertyKey) => {
1676
+ Reflect.defineMetadata("socket:event", event, target, propertyKey);
1677
+ registerSocketSubscriber(target.constructor);
1678
+ };
1679
+ }
1680
+ var _ref, PRIVATE_META_KEY, socketSubscriberClasses, EventSubscriberRegistry;
1681
+ var init_event_subscriber = __esmMin((() => {
1682
+ init_event_dispatcher();
1683
+ init_decorateMetadata();
1684
+ init_decorate();
1685
+ PRIVATE_META_KEY = "avleon:private";
1686
+ socketSubscriberClasses = /* @__PURE__ */ new Set();
1687
+ EventSubscriberRegistry = class EventSubscriberRegistry {
1688
+ constructor(socketContext) {
1689
+ this.socketContext = socketContext;
1690
+ }
1691
+ register(socket) {
1692
+ const subscriberClasses = getSocketSubscribers();
1693
+ for (const SubscriberClass of subscriberClasses) {
1694
+ const instance = Container$2.get(SubscriberClass);
1695
+ const prototype = Object.getPrototypeOf(instance);
1696
+ const methodNames = Object.getOwnPropertyNames(prototype).filter((name) => typeof prototype[name] === "function");
1697
+ for (const methodName of methodNames) {
1698
+ const event = Reflect.getMetadata("socket:event", prototype, methodName);
1699
+ const isPrivateListener = isPrivate(instance, methodName);
1700
+ const channelResolver = getPrivateChannelResolver(instance, methodName);
1701
+ if (event) {
1702
+ const channel = isPrivateListener && channelResolver ? channelResolver(socket) : event;
1703
+ console.log("Channel", channel);
1704
+ socket.on(channel, (payload) => {
1705
+ this.socketContext.run(socket, async () => {
1706
+ if (isPrivateListener) {
1707
+ if (!socket.data.user) return;
1708
+ }
1709
+ await instance[methodName](payload, socket.data);
1710
+ });
1711
+ });
1712
+ }
1713
+ }
1714
+ }
1715
+ }
1716
+ };
1717
+ EventSubscriberRegistry = __decorate([Service(), __decorateMetadata("design:paramtypes", [typeof (_ref = typeof SocketContextService !== "undefined" && SocketContextService) === "function" ? _ref : Object])], EventSubscriberRegistry);
1718
+ }));
1719
+ //#endregion
1720
+ //#region src/core/application.ts
1721
+ /**
1722
+ * @copyright 2024
1723
+ * @author Tareq Hossain
1724
+ * @email xtrinsic96@gmail.com
1725
+ * @url https://github.com/xtareq
1726
+ */
1727
+ init_exceptions();
1728
+ init_system_exception();
1729
+ init_container();
1730
+ function requireTypeorm() {
1731
+ try {
1732
+ return __require("typeorm");
1733
+ } catch {
1734
+ throw new Error("[Avleon] typeorm is not installed.\nRun: npm install typeorm\nThen install a driver: npm install pg (or mysql2, sqlite3, etc.)");
1735
+ }
1736
+ }
1737
+ function requireSocketIo() {
1738
+ try {
1739
+ return __require("fastify-socket.io");
1740
+ } catch {
1741
+ throw new Error("[Avleon] fastify-socket.io is not installed.\nRun: npm install fastify-socket.io socket.io");
1742
+ }
1743
+ }
1744
+ function requireSwagger() {
1745
+ try {
1746
+ return __require("@fastify/swagger");
1747
+ } catch {
1748
+ throw new Error("[Avleon] @fastify/swagger is not installed.\nRun: npm install @fastify/swagger @fastify/swagger-ui");
1749
+ }
1750
+ }
1751
+ function requireSwaggerUi() {
1752
+ try {
1753
+ return __require("@fastify/swagger-ui");
1754
+ } catch {
1755
+ throw new Error("[Avleon] @fastify/swagger-ui is not installed.\nRun: npm install @fastify/swagger-ui");
1756
+ }
1757
+ }
1758
+ function requireScalar() {
1759
+ try {
1760
+ return __require("@scalar/fastify-api-reference");
1761
+ } catch {
1762
+ throw new Error("[Avleon] @scalar/fastify-api-reference is not installed.\nRun: npm install @scalar/fastify-api-reference");
1763
+ }
1764
+ }
1765
+ function requireCors() {
1766
+ try {
1767
+ return __require("@fastify/cors");
1768
+ } catch {
1769
+ throw new Error("[Avleon] @fastify/cors is not installed.\nRun: npm install @fastify/cors");
1770
+ }
1771
+ }
1772
+ function requireMultipart() {
1773
+ try {
1774
+ return __require("@fastify/multipart");
1775
+ } catch {
1776
+ throw new Error("[Avleon] @fastify/multipart is not installed.\nRun: npm install @fastify/multipart");
1777
+ }
1778
+ }
1779
+ function requireStatic() {
1780
+ try {
1781
+ return __require("@fastify/static");
1782
+ } catch {
1783
+ throw new Error("[Avleon] @fastify/static is not installed.\nRun: npm install @fastify/static");
1784
+ }
1785
+ }
1786
+ var AvleonApplication = class AvleonApplication {
1787
+ app;
1788
+ router;
1789
+ static instance;
1790
+ alreadyRun = false;
1791
+ hasSwagger = false;
1792
+ globalSwaggerOptions;
1793
+ dataSourceOptions = null;
1794
+ dataSource = null;
1795
+ isMapFeatures = false;
1796
+ registerControllerAuto = false;
1797
+ registerControllerPath = "src/controllers";
1798
+ controllers = [];
1799
+ _hasWebsocket = false;
1800
+ io;
1801
+ constructor(options) {
1802
+ this.app = Fastify({
1803
+ ...options?.server,
1804
+ ajv: { customOptions: {
1805
+ strict: false,
1806
+ ...options?.server?.ajv?.customOptions
1807
+ } }
1808
+ });
1809
+ this.router = new AvleonRouter(this.app);
1810
+ if (options?.dataSourceOptions) {
1811
+ this.dataSourceOptions = options.dataSourceOptions;
1812
+ if (this.dataSourceOptions) {
1813
+ const { DataSource } = requireTypeorm();
1814
+ this.dataSource = new DataSource(this.dataSourceOptions);
1815
+ Container$1.set(DataSource, this.dataSource);
1816
+ }
1817
+ }
1818
+ }
1819
+ static getApp(options) {
1820
+ if (!AvleonApplication.instance) AvleonApplication.instance = new AvleonApplication(options);
1821
+ return AvleonApplication.instance;
1822
+ }
1823
+ /** @deprecated Use `getApp` instead. This is internal. */
1824
+ static getInternalApp(options) {
1825
+ return new AvleonApplication(options);
1826
+ }
1827
+ useCors(options) {
1828
+ this.app.register(requireCors(), options);
1829
+ return this;
1830
+ }
1831
+ useDatasource(dataSource) {
1832
+ const { DataSource } = requireTypeorm();
1833
+ this.dataSource = dataSource;
1834
+ Container$1.set(DataSource, this.dataSource);
1835
+ return this;
1836
+ }
1837
+ useMultipart(options) {
1838
+ this.app.register(requireMultipart(), {
1839
+ attachFieldsToBody: true,
1840
+ limits: { fileSize: 10 * 1024 * 1024 },
1841
+ ...options
1842
+ });
1843
+ return this;
1844
+ }
1845
+ useOpenApi(options) {
1846
+ this.hasSwagger = true;
1847
+ this.globalSwaggerOptions = options;
1848
+ return this;
1849
+ }
1850
+ async initSwagger(options) {
1851
+ const baseSchema = generateSwaggerSchema((this.controllers ?? []).filter((c) => c != null && typeof c === "function"));
1852
+ await this.app.register(requireSwagger(), { openapi: {
1853
+ ...baseSchema,
1854
+ info: options?.info || {
1855
+ title: "API",
1856
+ version: "1.0.0"
1857
+ },
1858
+ servers: options?.servers,
1859
+ tags: options?.tags,
1860
+ components: {
1861
+ ...baseSchema?.components,
1862
+ ...options?.components,
1863
+ schemas: {
1864
+ ...baseSchema?.components?.schemas,
1865
+ ...options?.components?.schemas
1866
+ }
1867
+ },
1868
+ security: options?.security,
1869
+ externalDocs: options?.externalDocs
1870
+ } });
1871
+ const routePrefix = options?.routePrefix || "/swagger";
1872
+ if (options?.provider === "scalar") await this.app.register(requireScalar(), {
1873
+ routePrefix,
1874
+ configuration: {
1875
+ spec: { content: () => requireSwagger() },
1876
+ ...options?.uiConfig
1877
+ }
1878
+ });
1879
+ else await this.app.register(requireSwaggerUi(), {
1880
+ routePrefix,
1881
+ uiConfig: {
1882
+ docExpansion: "full",
1883
+ deepLinking: false,
1884
+ ...options?.uiConfig
1885
+ },
1886
+ uiHooks: {
1887
+ onRequest: function(request, reply, next) {
1888
+ next();
1889
+ },
1890
+ preHandler: function(request, reply, next) {
1891
+ next();
1892
+ }
1893
+ },
1894
+ staticCSP: true,
1895
+ transformSpecificationClone: true
1896
+ });
1897
+ }
1898
+ useMiddlewares(middlewares) {
1899
+ middlewares.forEach((m) => {
1900
+ const cls = Container$1.get(m);
1901
+ this.app.addHook("preHandler", async (req, res) => {
1902
+ await cls.invoke(req, res);
1903
+ });
1904
+ });
1905
+ return this;
1906
+ }
1907
+ useAuthorization(authorization) {
1908
+ this.router.setAuthorizeMiddleware(authorization);
1909
+ return this;
1910
+ }
1911
+ useSerialization() {
1912
+ return this;
1913
+ }
1914
+ useControllers(controllers) {
1915
+ if (Array.isArray(controllers)) {
1916
+ this.controllers = controllers;
1917
+ controllers.forEach((controller) => {
1918
+ if (!this.controllers.includes(controller)) this.controllers.push(controller);
1919
+ });
1920
+ } else {
1921
+ this.registerControllerAuto = true;
1922
+ if (controllers.path) this.registerControllerPath = controllers.path;
1923
+ }
1924
+ return this;
1925
+ }
1926
+ useStaticFiles(options) {
1927
+ this.app.register(requireStatic(), options);
1928
+ return this;
1929
+ }
1930
+ useHttps(options) {
1931
+ return this;
1932
+ }
1933
+ useGlobal(options) {
1934
+ if (options.cors) this.useCors(options.cors);
1935
+ if (options.openApi) this.useOpenApi(options.openApi);
1936
+ if (options.controllers) this.useControllers(options.controllers);
1937
+ if (options.middlewares) this.useMiddlewares(options.middlewares);
1938
+ if (options.authorization) this.useAuthorization(options.authorization);
1939
+ if (options.multipart) this.useMultipart(options.multipart);
1940
+ if (options.staticFiles) this.useStaticFiles(options.staticFiles);
1941
+ return this;
1942
+ }
1943
+ useSocketIo(options) {
1944
+ this._hasWebsocket = true;
1945
+ this.app.register(requireSocketIo(), options);
1946
+ return this;
1947
+ }
1948
+ useKnex(options) {
1949
+ try {
1950
+ const { DB } = (init_kenx_provider(), __toCommonJS(kenx_provider_exports));
1951
+ Container$1.get(DB).init(options.config ?? options);
1952
+ } catch (e) {
1953
+ if (e.message?.includes("knex")) throw e;
1954
+ throw new Error("[Avleon] Failed to initialize Knex. Make sure knex and a database driver are installed.\nRun: npm install knex pg (or mysql2, sqlite3, etc.)");
1955
+ }
1956
+ return this;
1957
+ }
1958
+ mapFeatures() {
1959
+ this.isMapFeatures = true;
1960
+ return this;
1961
+ }
1962
+ isDevelopment() {
1963
+ return process.env.NODE_ENV === "development" || !process.env.NODE_ENV;
1964
+ }
1965
+ async _mapControllers() {
1966
+ const safeControllers = (this.controllers ?? []).filter((c) => c != null && typeof c === "function");
1967
+ if (safeControllers.length > 0) for (const controller of safeControllers) if (isApiController(controller)) await this.router.buildController(controller);
1968
+ else throw new SystemUseError("Not an API controller.");
1969
+ }
1970
+ _resolveControllerDir(dir) {
1971
+ const isTsNode = process.env.TS_NODE_DEV || process.env.TS_NODE_PROJECT || process[Symbol.for("ts-node.register.instance")];
1972
+ const controllerDir = path.join(process.cwd(), this.registerControllerPath);
1973
+ return isTsNode ? controllerDir : controllerDir.replace("src", "dist");
1974
+ }
1975
+ async autoControllers(controllersPath) {
1976
+ const conDir = this._resolveControllerDir(controllersPath);
1977
+ const isTsNode = process.env.TS_NODE_DEV || process.env.TS_NODE_PROJECT || process[Symbol.for("ts-node.register.instance")];
1978
+ try {
1979
+ const files = fs.readdirSync(conDir, {
1980
+ recursive: true,
1981
+ encoding: "utf-8"
1982
+ });
1983
+ for (const file of files) {
1984
+ if (/\.(test|spec|e2e-spec)\.(ts|js)$/.test(file)) continue;
1985
+ if (isTsNode ? file.endsWith(".ts") : file.endsWith(".js")) {
1986
+ const module = await import(path.join(conDir, file));
1987
+ for (const exported of Object.values(module)) if (typeof exported === "function" && isApiController(exported)) {
1988
+ if (!this.controllers.some((con) => exported.name === con.name)) this.controllers.push(exported);
1989
+ }
1990
+ }
1991
+ }
1992
+ } catch (e) {
1993
+ console.warn("Could not auto-register controllers from " + conDir, e);
1994
+ }
1995
+ }
1996
+ _mapFeatures() {
1997
+ try {
1998
+ Container$1.get("features");
1999
+ } catch {}
2000
+ }
2001
+ async initializeDatabase() {
2002
+ if (this.dataSourceOptions && this.dataSource) await this.dataSource.initialize();
2003
+ }
2004
+ handleSocket(socket) {
2005
+ try {
2006
+ const { SocketContextService } = (init_event_dispatcher(), __toCommonJS(event_dispatcher_exports));
2007
+ const { EventSubscriberRegistry } = (init_event_subscriber(), __toCommonJS(event_subscriber_exports));
2008
+ const { SocketIoServer } = (init_websocket(), __toCommonJS(websocket_exports));
2009
+ const contextService = Container$1.get(SocketContextService);
2010
+ Container$1.get(EventSubscriberRegistry).register(socket);
2011
+ const originalOn = socket.on.bind(socket);
2012
+ socket.on = (event, handler) => {
2013
+ return originalOn(event, (...args) => {
2014
+ contextService.run(socket, () => handler(...args));
2015
+ });
2016
+ };
2017
+ } catch (e) {
2018
+ console.warn("[Avleon] Socket handler error:", e);
2019
+ }
2020
+ }
2021
+ mapGet(path = "", fn) {
2022
+ return this.router.mapGet(path, fn);
2023
+ }
2024
+ mapPost(path = "", fn) {
2025
+ return this.router.mapPost(path, fn);
2026
+ }
2027
+ mapPut(path = "", fn) {
2028
+ return this.router.mapPut(path, fn);
2029
+ }
2030
+ mapDelete(path = "", fn) {
2031
+ return this.router.mapDelete(path, fn);
2032
+ }
2033
+ async run(port = 4e3, fn) {
2034
+ if (this.alreadyRun) throw new SystemUseError("App already running");
2035
+ this.alreadyRun = true;
2036
+ if (this.hasSwagger) await this.initSwagger(this.globalSwaggerOptions);
2037
+ await this.initializeDatabase();
2038
+ if (this.isMapFeatures) this._mapFeatures();
2039
+ if (this.registerControllerAuto) await this.autoControllers();
2040
+ await this._mapControllers();
2041
+ this.router.processFunctionalRoutes();
2042
+ this.app.setErrorHandler((error, request, reply) => {
2043
+ const isDev = process.env.NODE_ENV === "development";
2044
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2045
+ const requestInfo = `${request.method} ${request.url}`;
2046
+ if (error.statusCode === 400 || error.validation) {
2047
+ console.warn(`[${timestamp}] HTTP 400 ${requestInfo} — ${error.message}`);
2048
+ return reply.status(400).send({
2049
+ code: 400,
2050
+ status: "Error",
2051
+ message: error.message,
2052
+ errors: error.validation ?? void 0
2053
+ });
2054
+ }
2055
+ if (error instanceof BaseHttpException) {
2056
+ console.warn(`[${timestamp}] HTTP ${error.code} ${requestInfo} — ${error.message}`);
2057
+ return reply.status(error.code || 500).type("application/json").serializer((payload) => JSON.stringify(payload)).send({
2058
+ code: error.code,
2059
+ status: "Error",
2060
+ message: error.message,
2061
+ data: error.payload
2062
+ });
2063
+ }
2064
+ console.error(`\n❌ UNHANDLED ERROR @ ${timestamp}`);
2065
+ console.error(` ${requestInfo}`);
2066
+ console.error(` ${error.name}: ${error.message}`);
2067
+ if (error.stack) console.error(` Stack:\n${error.stack.split("\n").slice(1).map((l) => ` ${l.trim()}`).join("\n")}`);
2068
+ if (isDev) {
2069
+ console.error(` Params:`, JSON.stringify(request.params));
2070
+ console.error(` Query: `, JSON.stringify(request.query));
2071
+ console.error(` Body: `, JSON.stringify(request.body));
2072
+ }
2073
+ console.error("");
2074
+ return reply.status(500).send({
2075
+ code: 500,
2076
+ status: "Error",
2077
+ message: isDev ? error.message : "Internal Server Error",
2078
+ ...isDev && {
2079
+ error: error.name,
2080
+ stack: error.stack?.split("\n").slice(0, 5)
2081
+ }
2082
+ });
2083
+ });
2084
+ await this.app.ready();
2085
+ if (this._hasWebsocket) {
2086
+ if (!this.app.io) throw new Error("Socket.IO not initialized. Make sure fastify-socket.io is registered correctly.");
2087
+ try {
2088
+ const { SocketIoServer } = (init_websocket(), __toCommonJS(websocket_exports));
2089
+ Container$1.set(SocketIoServer, this.app.io);
2090
+ await this.app.io.on("connection", this.handleSocket.bind(this));
2091
+ } catch (e) {
2092
+ console.warn("[Avleon] WebSocket setup error:", e);
2093
+ }
2094
+ }
2095
+ await this.app.listen({ port });
2096
+ console.log(`Application running on http://127.0.0.1:${port}`);
2097
+ if (fn) fn();
2098
+ }
2099
+ };
2100
+ //#endregion
2101
+ //#region src/core/testing.ts
2102
+ /**
2103
+ * @copyright 2024
2104
+ * @author Tareq Hossain
2105
+ * @email xtrinsic96@gmail.com
2106
+ * @url https://github.com/xtareq
2107
+ */
2108
+ init_exceptions();
2109
+ init_system_exception();
2110
+ var AvleonTest = class AvleonTest {
2111
+ constructor() {
2112
+ process.env.NODE_ENV = "test";
2113
+ }
2114
+ static getController(controller, deps = []) {
2115
+ const paramTypes = Reflect.getMetadata("design:paramtypes", controller) || [];
2116
+ deps.forEach((dep, i) => {
2117
+ Container$1.set(paramTypes[i], dep);
2118
+ });
2119
+ return Container$1.get(controller);
2120
+ }
2121
+ static getProvider(service, deps = []) {
2122
+ const paramTypes = Reflect.getMetadata("design:paramtypes", service) || [];
2123
+ deps.forEach((dep, i) => {
2124
+ Container$1.set(paramTypes[i], dep);
2125
+ });
2126
+ return Container$1.get(service);
2127
+ }
2128
+ static createTestApplication(options) {
2129
+ const app = AvleonApplication.getInternalApp({ dataSourceOptions: options.dataSource ? options.dataSource : void 0 });
2130
+ if (options.controllers) app.useControllers(options.controllers);
2131
+ return AvleonTest.from(app);
2132
+ }
2133
+ static from(app) {
2134
+ try {
2135
+ app._mapControllers().catch((e) => console.error(e));
2136
+ app.app.setErrorHandler(async (error, req, res) => {
2137
+ if (error instanceof ValidationErrorException) return res.status(400).send({
2138
+ code: 400,
2139
+ error: "ValidationError",
2140
+ errors: error.message
2141
+ });
2142
+ return res.status(500).send(error);
2143
+ });
2144
+ return {
2145
+ get: async (url, options) => app.app.inject({
2146
+ method: "GET",
2147
+ url,
2148
+ ...options
2149
+ }),
2150
+ post: async (url, options) => app.app.inject({
2151
+ method: "POST",
2152
+ url,
2153
+ ...options
2154
+ }),
2155
+ put: async (url, options) => app.app.inject({
2156
+ method: "PUT",
2157
+ url,
2158
+ ...options
2159
+ }),
2160
+ patch: async (url, options) => app.app.inject({
2161
+ method: "PATCH",
2162
+ url,
2163
+ ...options
2164
+ }),
2165
+ delete: async (url, options) => app.app.inject({
2166
+ method: "DELETE",
2167
+ url,
2168
+ ...options
2169
+ }),
2170
+ options: async (url, options) => app.app.inject({
2171
+ method: "OPTIONS",
2172
+ url,
2173
+ ...options
2174
+ }),
2175
+ getController: (controller, deps = []) => {
2176
+ return AvleonTest.getController(controller, deps);
2177
+ }
2178
+ };
2179
+ } catch (error) {
2180
+ throw new SystemUseError("Can't get test appliction");
2181
+ }
2182
+ }
2183
+ static clean() {
2184
+ Container$1.reset();
2185
+ }
2186
+ };
2187
+ var Avleon = class {
2188
+ static createApplication() {
2189
+ return AvleonApplication.getApp();
2190
+ }
2191
+ static createTestApplication(options) {
2192
+ return AvleonTest.createTestApplication(options);
2193
+ }
2194
+ };
2195
+ //#endregion
2196
+ //#region src/response.ts
2197
+ /**
2198
+ * @copyright 2024
2199
+ * @author Tareq Hossain
2200
+ * @email xtrinsic96@gmail.com
2201
+ * @url https://github.com/xtareq
2202
+ */
2203
+ var HttpResponse = class {
2204
+ static Ok(obj, s) {
2205
+ if (s) {
2206
+ const isPaginated = obj?.hasOwnProperty("total");
2207
+ const transformedData = plainToInstance(s, isPaginated ? obj.data : obj, {
2208
+ enableImplicitConversion: true,
2209
+ excludeExtraneousValues: true
2210
+ });
2211
+ return {
2212
+ message: "success",
2213
+ ...isPaginated ? {
2214
+ ...obj,
2215
+ data: instanceToPlain(transformedData)
2216
+ } : { data: instanceToPlain(transformedData) }
2217
+ };
2218
+ }
2219
+ return {
2220
+ message: "success",
2221
+ data: obj
2222
+ };
2223
+ }
2224
+ static Created(obj, s) {
2225
+ if (s) return {
2226
+ message: "created",
2227
+ data: instanceToPlain(plainToInstance(s, obj, {
2228
+ enableImplicitConversion: true,
2229
+ excludeExtraneousValues: true
2230
+ }))
2231
+ };
2232
+ return {
2233
+ message: "created",
2234
+ data: obj
2235
+ };
2236
+ }
2237
+ static NoContent() {
2238
+ return {
2239
+ message: "no content",
2240
+ data: null
2241
+ };
2242
+ }
2243
+ };
2244
+ //#endregion
2245
+ //#region src/middleware.ts
2246
+ /**
2247
+ * @copyright 2024
2248
+ * @author Tareq Hossain
2249
+ * @email xtrinsic96@gmail.com
2250
+ * @url https://github.com/xtareq
2251
+ */
2252
+ init_container();
2253
+ var AvleonMiddleware = class {};
2254
+ var AuthorizeMiddleware = class {};
2255
+ function CanAuthorize(target) {
2256
+ if (typeof target.prototype.authorize !== "function") throw new Error(`Class "${target.name}" must implement an "authorize" method.`);
2257
+ Service()(target);
2258
+ }
2259
+ function AppAuthorization(target) {
2260
+ if (typeof target.prototype.authorize !== "function") throw new Error(`Class "${target.name}" must implement an "authorize" method.`);
2261
+ Service()(target);
2262
+ }
2263
+ function Authorized(options = {}) {
2264
+ return function(target, propertyKey, descriptor) {
2265
+ if (propertyKey && descriptor) Reflect.defineMetadata(AUTHORIZATION_META_KEY, {
2266
+ authorize: true,
2267
+ options
2268
+ }, target.constructor, propertyKey);
2269
+ else Reflect.defineMetadata(AUTHORIZATION_META_KEY, {
2270
+ authorize: true,
2271
+ options
2272
+ }, target);
2273
+ };
2274
+ }
2275
+ function AppMiddleware(target) {
2276
+ if (typeof target.prototype.invoke !== "function") throw new Error(`Class "${target.name}" must implement an "invoke" method.`);
2277
+ Service()(target);
2278
+ }
2279
+ /**
2280
+ * A decorator function that applies one or more middleware to a class or a method.
2281
+ *
2282
+ * When applied to a class, the middleware are registered for the entire controller.
2283
+ * When applied to a method, the middleware are registered for that specific route.
2284
+ *
2285
+ * @param options - A single middleware instance/class or an array of middleware instances/classes to be applied.
2286
+ * @returns A decorator that registers the middleware metadata.
2287
+ */
2288
+ function UseMiddleware(options) {
2289
+ return function(target, propertyKey, descriptor) {
2290
+ const normalizeMiddleware = (middleware) => typeof middleware === "function" ? new middleware() : middleware;
2291
+ const middlewareList = (Array.isArray(options) ? options : [options]).map(normalizeMiddleware);
2292
+ if (typeof target === "function" && !propertyKey) {
2293
+ const existingMiddlewares = Reflect.getMetadata("controller:middleware", target) || [];
2294
+ Reflect.defineMetadata("controller:middleware", [...existingMiddlewares, ...middlewareList], target);
2295
+ } else if (descriptor) {
2296
+ const existingMiddlewares = Reflect.getMetadata("route:middleware", target, propertyKey) || [];
2297
+ Reflect.defineMetadata("route:middleware", [...existingMiddlewares, ...middlewareList], target, propertyKey);
2298
+ }
2299
+ };
2300
+ }
2301
+ //#endregion
2302
+ //#region src/collection.ts
2303
+ /**
2304
+ * @copyright 2024
2305
+ * @author Tareq Hossain
2306
+ * @email xtrinsic96@gmail.com
2307
+ * @url https://github.com/xtareq
2308
+ */
2309
+ init_exceptions();
2310
+ var BasicCollectionImpl = class BasicCollectionImpl {
2311
+ items;
2312
+ constructor(items) {
2313
+ this.items = items;
2314
+ }
2315
+ static from(items) {
2316
+ return new BasicCollectionImpl(items);
2317
+ }
2318
+ clear() {
2319
+ this.items = [];
2320
+ }
2321
+ find(predicate) {
2322
+ if (this.isFunction(predicate)) return this.items.filter(predicate);
2323
+ return Array.from(this.items);
2324
+ }
2325
+ async findAsync(predicate) {
2326
+ return Array.from(this.items);
2327
+ }
2328
+ _matches(item, where) {
2329
+ if ("$or" in where) return where.$or.some((cond) => this._matches(item, cond));
2330
+ if ("$and" in where) return where.$and.every((cond) => this._matches(item, cond));
2331
+ if ("$not" in where) return !this._matches(item, where.$not);
2332
+ return Object.entries(where).every(([key, condition]) => {
2333
+ const itemValue = item[key];
2334
+ if (condition && typeof condition === "object" && !Array.isArray(condition)) {
2335
+ const op = condition;
2336
+ if ("$in" in op && Array.isArray(op.$in)) return op.$in.includes(itemValue);
2337
+ }
2338
+ return itemValue === condition;
2339
+ });
2340
+ }
2341
+ findOne(predicate) {
2342
+ if (this.isFunction(predicate)) return this.items.find(predicate);
2343
+ const result = this.items.filter((item) => this._matches(item, predicate.where));
2344
+ if (result.length > 0) return result[0];
2345
+ }
2346
+ async findOneAsync(predicate) {
2347
+ if (this.isFunction(predicate)) return this.items.find(predicate);
2348
+ return this.items.find((item) => this._matches(item, predicate.where));
2349
+ }
2350
+ isFunction(value) {
2351
+ return typeof value === "function";
2352
+ }
2353
+ add(item) {
2354
+ this.items.push(item);
2355
+ return this.items[this.items.length - 1];
2356
+ }
2357
+ addAll(items) {
2358
+ this.items.push(...items);
2359
+ }
2360
+ update(predicate, updater) {
2361
+ const item = this.items.find(predicate);
2362
+ if (item) {
2363
+ const index = this.items.indexOf(item);
2364
+ this.items[index] = {
2365
+ ...item,
2366
+ ...updater
2367
+ };
2368
+ } else throw new NotFoundException("Item not found");
2369
+ }
2370
+ updateAll(predicate, updater) {
2371
+ for (let i = 0; i < this.items.length; i++) if (predicate(this.items[i])) this.items[i] = updater(this.items[i]);
2372
+ }
2373
+ delete(predicate) {
2374
+ const index = this.items.findIndex(predicate);
2375
+ if (index !== -1) this.items.splice(index, 1);
2376
+ }
2377
+ deleteAll(predicate) {
2378
+ this.items = this.items.filter((item) => !predicate(item));
2379
+ }
2380
+ max(key) {
2381
+ return Math.max(...this.items.map((item) => item[key]));
2382
+ }
2383
+ min(key) {
2384
+ return Math.max(...this.items.map((item) => item[key]));
2385
+ }
2386
+ sum(key) {
2387
+ return this.items.flatMap((x) => x[key]).reduce((sum, num) => sum + num, 0);
2388
+ }
2389
+ avg(key) {
2390
+ const nums = this.items.flatMap((x) => x[key]);
2391
+ return nums.reduce((sum, num) => sum + num, 0) / nums.length;
2392
+ }
2393
+ paginate(options) {
2394
+ const take = options?.take || 10;
2395
+ const skip = options?.skip || 0;
2396
+ const total = this.items.length;
2397
+ const data = this.items.slice(skip, take);
2398
+ return {
2399
+ total,
2400
+ totalPage: Math.ceil(total / take),
2401
+ next: skip + take < total ? skip + take : null,
2402
+ data
2403
+ };
2404
+ }
2405
+ getDeepValue(item, path) {
2406
+ if (typeof path !== "string") return item[path];
2407
+ return path.split(".").reduce((acc, key) => acc?.[key], item);
2408
+ }
2409
+ };
2410
+ var AsynchronousCollection = class AsynchronousCollection {
2411
+ model;
2412
+ repo;
2413
+ constructor(model) {
2414
+ this.model = model;
2415
+ }
2416
+ static fromRepository(model) {
2417
+ return new AsynchronousCollection(model);
2418
+ }
2419
+ getRepository() {
2420
+ if (!this.repo) {
2421
+ const dataSource = Container$1.get("idatasource");
2422
+ console.log("datasource", dataSource);
2423
+ const repository = dataSource.getRepository(this.model);
2424
+ this.repo = repository;
2425
+ return repository;
2426
+ }
2427
+ return this.repo;
2428
+ }
2429
+ async paginate(options) {
2430
+ const take = options?.take || 10;
2431
+ const skip = options?.skip || 0;
2432
+ const [data, total] = await this.getRepository().findAndCount({
2433
+ take,
2434
+ skip
2435
+ });
2436
+ return {
2437
+ total,
2438
+ totalPage: Math.ceil(total / take),
2439
+ next: skip + take < total ? skip + take : null,
2440
+ prev: skip + take < total ? skip + take : null,
2441
+ data
2442
+ };
2443
+ }
2444
+ };
2445
+ var Collection = class {
2446
+ constructor() {}
2447
+ static from(items) {
2448
+ return BasicCollectionImpl.from(items);
2449
+ }
2450
+ static fromRepository(entity) {
2451
+ return AsynchronousCollection.fromRepository(entity).getRepository();
2452
+ }
2453
+ };
2454
+ function InjectRepository(model) {
2455
+ return function(object, propertyName, index) {
2456
+ let repo;
2457
+ try {
2458
+ Container$1.registerHandler({
2459
+ object,
2460
+ propertyName,
2461
+ index,
2462
+ value: (containerInstance) => {
2463
+ repo = containerInstance.get("idatasource").getRepository(model).extend({ paginate: () => {} });
2464
+ repo.paginate = async function(options = {
2465
+ take: 10,
2466
+ skip: 0
2467
+ }) {
2468
+ const [data, total] = await this.findAndCount({
2469
+ take: options.take || 10,
2470
+ skip: options.skip || 0
2471
+ });
2472
+ return {
2473
+ total,
2474
+ totalPage: Math.ceil(total / (options.take || 10)),
2475
+ next: options.skip + options.take < total ? options.skip + options.take : null,
2476
+ data
2477
+ };
2478
+ };
2479
+ return repo;
2480
+ }
2481
+ });
2482
+ } catch (error) {
2483
+ if (error.name && error.name == "ServiceNotFoundError") console.log("Database didn't initialized.");
2484
+ }
2485
+ };
2486
+ }
2487
+ //#endregion
2488
+ //#region src/queue.ts
2489
+ var AvleonQueue = class {
2490
+ queue;
2491
+ handlerFn;
2492
+ constructor(name, adapter, handler) {
2493
+ this.name = name;
2494
+ this.adapter = adapter;
2495
+ this.queue = new Bull(name || "default", adapter);
2496
+ this.handlerFn = handler;
2497
+ if (typeof this.handler === "function" && !this.handlerFn) this.handlerFn = (job) => this.handler(job);
2498
+ if (this.handlerFn) this.queue.process(this.handlerFn);
2499
+ }
2500
+ add(data, options) {
2501
+ return this.queue.add(data, options);
2502
+ }
2503
+ delay(data, delayMs, options) {
2504
+ return this.queue.add(data, {
2505
+ ...options,
2506
+ delay: delayMs
2507
+ });
2508
+ }
2509
+ process(handler) {
2510
+ this.handlerFn = handler;
2511
+ this.queue.process(handler);
2512
+ }
2513
+ processConcurrent(concurrency, handler) {
2514
+ this.handlerFn = handler;
2515
+ this.queue.process(concurrency, handler);
2516
+ }
2517
+ getQueue() {
2518
+ return this.queue;
2519
+ }
2520
+ async clean(grace, status) {
2521
+ return this.queue.clean(grace, status);
2522
+ }
2523
+ async close() {
2524
+ await this.queue.close();
2525
+ }
2526
+ async pause() {
2527
+ await this.queue.pause();
2528
+ }
2529
+ async resume() {
2530
+ await this.queue.resume();
2531
+ }
2532
+ async getJob(jobId) {
2533
+ return this.queue.getJob(jobId);
2534
+ }
2535
+ async getJobs(types, start, end) {
2536
+ return this.queue.getJobs(types, start, end);
2537
+ }
2538
+ };
2539
+ function Queue(config) {
2540
+ return function(target) {
2541
+ const DecoratedClass = class extends target {
2542
+ constructor(...args) {
2543
+ super(config.name, config.adapter, config.handler);
2544
+ }
2545
+ };
2546
+ Object.defineProperty(DecoratedClass, "name", {
2547
+ value: target.name,
2548
+ writable: false
2549
+ });
2550
+ Service()(DecoratedClass);
2551
+ return DecoratedClass;
2552
+ };
2553
+ }
2554
+ //#endregion
2555
+ //#region src/file-storage.ts
2556
+ init_system_exception();
2557
+ init_http_exceptions();
2558
+ init_decorateMetadata();
2559
+ init_decorate();
2560
+ let FileStorage = class FileStorage {
2561
+ transformOptions = null;
2562
+ baseDir;
2563
+ maxFileSize = 50 * 1024 * 1024;
2564
+ constructor() {
2565
+ this.baseDir = path.join(process.cwd(), "public");
2566
+ this.ensureDirectoryExists(this.baseDir);
2567
+ }
2568
+ /**
2569
+ * Set transformation options for the next save operation
2570
+ */
2571
+ transform(options) {
2572
+ this.transformOptions = options;
2573
+ return this;
2574
+ }
2575
+ async getUploadFile(fliePath) {
2576
+ return await fs.promises.readFile(path.join(this.baseDir, fliePath));
2577
+ }
2578
+ async download(filepath) {
2579
+ const filename = filepath.toString().split(/[\/\\]/).pop() || "file";
2580
+ return {
2581
+ download: true,
2582
+ stream: createReadStream(filepath),
2583
+ filename
2584
+ };
2585
+ }
2586
+ async downloadAs(filepath, filename) {
2587
+ return {
2588
+ download: true,
2589
+ stream: createReadStream(filepath),
2590
+ filename
2591
+ };
2592
+ }
2593
+ /**
2594
+ * Save a single file with optional transformations
2595
+ */
2596
+ async save(f, options) {
2597
+ const opts = {
2598
+ overwrite: options?.overwrite ?? true,
2599
+ to: options?.to,
2600
+ saveAs: options?.saveAs
2601
+ };
2602
+ if (f.type !== "file") throw new SystemUseError("Invalid file type");
2603
+ try {
2604
+ const filename = opts.saveAs || f.filename;
2605
+ this.validateFilename(filename);
2606
+ const uploadDir = opts.to ? path.join(this.baseDir, opts.to) : this.baseDir;
2607
+ const fullPath = path.join(uploadDir, filename);
2608
+ if (!fullPath.startsWith(this.baseDir)) throw new SystemUseError("Invalid file path");
2609
+ if (!opts.overwrite && this.isFileExists(fullPath)) throw new SystemUseError("File already exists");
2610
+ await this.ensureDirectoryExists(uploadDir);
2611
+ let sourceStream;
2612
+ const savedFile = f;
2613
+ if (savedFile.filepath && !f.file) sourceStream = fs.createReadStream(savedFile.filepath);
2614
+ else if (f.file) sourceStream = f.file;
2615
+ else throw new SystemUseError("No file stream or filepath available");
2616
+ if (this.transformOptions && this.isImageFile(filename)) await this.processImage(sourceStream, fullPath);
2617
+ else await pipeline(sourceStream, fs.createWriteStream(fullPath));
2618
+ if (savedFile.filepath && fs.existsSync(savedFile.filepath)) this.removeFileSync(savedFile.filepath);
2619
+ if (opts.saveAs) f.filename = opts.saveAs;
2620
+ return {
2621
+ uploadPath: options?.to ? "/uploads/" + options.to + "/" + f.filename : "/uploads/" + f.filename,
2622
+ staticPath: options?.to ? "/static/" + options.to + "/" + f.filename : "/static/" + f.filename
2623
+ };
2624
+ } catch (err) {
2625
+ if (err instanceof SystemUseError || err instanceof InternalErrorException) throw err;
2626
+ console.error("File save error:", err);
2627
+ throw new SystemUseError("Failed to upload file");
2628
+ }
2629
+ }
2630
+ /**
2631
+ * Save multiple files
2632
+ */
2633
+ async saveAll(files, options) {
2634
+ if (!files || files.length === 0) return [];
2635
+ const opts = {
2636
+ overwrite: options?.overwrite ?? true,
2637
+ to: options?.to
2638
+ };
2639
+ const uploadDir = opts.to ? path.join(this.baseDir, opts.to) : this.baseDir;
2640
+ await this.ensureDirectoryExists(uploadDir);
2641
+ const results = [];
2642
+ for (const f of files) try {
2643
+ this.validateFilename(f.filename);
2644
+ const fullPath = path.join(uploadDir, f.filename);
2645
+ if (!fullPath.startsWith(this.baseDir)) throw new SystemUseError(`Invalid file path for ${f.filename}`);
2646
+ if (!opts.overwrite && this.isFileExists(fullPath)) throw new SystemUseError(`File ${f.filename} already exists`);
2647
+ if (f.file) if (this.transformOptions && this.isImageFile(f.filename)) await this.processImage(f.file, fullPath);
2648
+ else await pipeline(f.file, fs.createWriteStream(fullPath));
2649
+ else {
2650
+ const fp = f;
2651
+ if (!fp.filepath) throw new SystemUseError(`No filepath for ${f.filename}`);
2652
+ if (this.transformOptions && this.isImageFile(f.filename)) await this.processImage(fs.createReadStream(fp.filepath), fullPath);
2653
+ else await pipeline(fs.createReadStream(fp.filepath), fs.createWriteStream(fullPath));
2654
+ this.removeFileSync(fp.filepath);
2655
+ }
2656
+ results.push({
2657
+ uploadPath: options?.to ? "/uploads/" + options.to + "/" + f.filename : "/uploads/" + f.filename,
2658
+ staticPath: options?.to ? "/static/" + options.to + "/" + f.filename : "/static/" + f.filename
2659
+ });
2660
+ } catch (error) {
2661
+ console.error(`Failed to save file ${f.filename}:`, error);
2662
+ throw new SystemUseError(`Failed to upload file ${f.filename}`);
2663
+ }
2664
+ return results;
2665
+ }
2666
+ /**
2667
+ * Remove a file from storage
2668
+ */
2669
+ async remove(filepath) {
2670
+ const fullPath = path.join(this.baseDir, filepath);
2671
+ if (!fullPath.startsWith(this.baseDir)) throw new SystemUseError("Invalid file path");
2672
+ if (!this.isFileExists(fullPath)) throw new SystemUseError("File doesn't exist");
2673
+ try {
2674
+ fs.unlinkSync(fullPath);
2675
+ } catch (error) {
2676
+ console.error("File removal error:", error);
2677
+ throw new SystemUseError("Failed to remove file");
2678
+ }
2679
+ }
2680
+ /**
2681
+ * Process image with transformations using sharp
2682
+ */
2683
+ async processImage(fileStream, outputPath) {
2684
+ try {
2685
+ let sharpPipeline = (await import("./lib-CvDxBMkR.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1))).default();
2686
+ if (this.transformOptions?.resize) sharpPipeline = sharpPipeline.resize(this.transformOptions.resize.width, this.transformOptions.resize.height, {
2687
+ fit: "inside",
2688
+ withoutEnlargement: true
2689
+ });
2690
+ if (this.transformOptions?.format) {
2691
+ const quality = this.transformOptions.quality || 80;
2692
+ switch (this.transformOptions.format) {
2693
+ case "jpeg":
2694
+ sharpPipeline = sharpPipeline.jpeg({ quality });
2695
+ break;
2696
+ case "png":
2697
+ sharpPipeline = sharpPipeline.png({ quality });
2698
+ break;
2699
+ case "webp":
2700
+ sharpPipeline = sharpPipeline.webp({ quality });
2701
+ break;
2702
+ case "avif":
2703
+ sharpPipeline = sharpPipeline.avif({ quality });
2704
+ break;
2705
+ }
2706
+ }
2707
+ await pipeline(fileStream, sharpPipeline, fs.createWriteStream(outputPath));
2708
+ } catch (error) {
2709
+ if (error.code === "MODULE_NOT_FOUND" && error.message.includes("sharp")) throw new InternalErrorException("sharp module not found. Please install sharp to use image transformations.");
2710
+ console.error("Image processing failed:", error);
2711
+ throw new InternalErrorException("Image processing failed");
2712
+ } finally {
2713
+ this.transformOptions = null;
2714
+ }
2715
+ }
2716
+ /**
2717
+ * Helper methods
2718
+ */
2719
+ isFileExists(fpath) {
2720
+ return fs.existsSync(fpath);
2721
+ }
2722
+ async ensureDirectoryExists(dirPath) {
2723
+ if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true });
2724
+ }
2725
+ removeFileSync(filepath) {
2726
+ try {
2727
+ if (fs.existsSync(filepath)) fs.unlinkSync(filepath);
2728
+ } catch (error) {
2729
+ console.error("Failed to remove temp file:", error);
2730
+ }
2731
+ }
2732
+ isImageFile(filename) {
2733
+ const ext = path.extname(filename).toLowerCase();
2734
+ return [
2735
+ ".jpg",
2736
+ ".jpeg",
2737
+ ".png",
2738
+ ".webp",
2739
+ ".avif",
2740
+ ".gif",
2741
+ ".bmp"
2742
+ ].includes(ext);
2743
+ }
2744
+ validateFilename(filename) {
2745
+ if (!filename || filename.trim() === "") throw new SystemUseError("Invalid filename");
2746
+ if (filename.includes("..") || filename.includes("/") || filename.includes("\\")) throw new SystemUseError("Invalid filename: path traversal detected");
2747
+ if (filename.includes("\0")) throw new SystemUseError("Invalid filename: null byte detected");
2748
+ }
2749
+ };
2750
+ FileStorage = __decorate([AppService, __decorateMetadata("design:paramtypes", [])], FileStorage);
2751
+ //#endregion
2752
+ //#region src/environment-variables.ts
2753
+ /**
2754
+ * @copyright 2024
2755
+ * @author Tareq Hossain
2756
+ * @email xtrinsic96@gmail.com
2757
+ * @url https://github.com/xtareq
2758
+ */
2759
+ init_system_exception();
2760
+ init_decorate();
2761
+ dotenv.config({
2762
+ path: path.join(process.cwd(), ".env"),
2763
+ quiet: true
17
2764
  });
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
36
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
- };
38
- var __importDefault = (this && this.__importDefault) || function (mod) {
39
- return (mod && mod.__esModule) ? mod : { "default": mod };
40
- };
41
- Object.defineProperty(exports, "__esModule", { value: true });
42
- exports.AvleonContainer = exports.OpenApiProperty = exports.OpenApiResponse = exports.OpenApiOk = exports.GetObjectSchema = exports.GetSchema = void 0;
43
- /**
44
- * @copyright 2024
45
- * @author Tareq Hossain
46
- * @email xtrinsic96@gmail.com
47
- * @url https://github.com/xtareq
48
- */
49
- const sw = __importStar(require("./swagger-schema"));
50
- require("reflect-metadata");
51
- __exportStar(require("./decorators"), exports);
52
- __exportStar(require("./interfaces/avleon-application"), exports);
53
- __exportStar(require("./core/application"), exports);
54
- __exportStar(require("./core/testing"), exports);
55
- __exportStar(require("./core/types"), exports);
56
- __exportStar(require("./helpers"), exports);
57
- __exportStar(require("./response"), exports);
58
- __exportStar(require("./exceptions"), exports);
59
- __exportStar(require("./openapi"), exports);
60
- __exportStar(require("./swagger-schema"), exports);
61
- __exportStar(require("./container"), exports);
62
- __exportStar(require("./middleware"), exports);
63
- __exportStar(require("./kenx-provider"), exports);
64
- __exportStar(require("./collection"), exports);
65
- __exportStar(require("./event-dispatcher"), exports);
66
- __exportStar(require("./event-subscriber"), exports);
67
- __exportStar(require("./queue"), exports);
68
- __exportStar(require("./file-storage"), exports);
69
- __exportStar(require("./config"), exports);
70
- __exportStar(require("./logger"), exports);
71
- __exportStar(require("./cache"), exports);
72
- __exportStar(require("./results"), exports);
73
- __exportStar(require("./environment-variables"), exports);
74
- exports.GetSchema = sw.generateSwaggerSchema;
75
- exports.GetObjectSchema = sw.CreateSwaggerObjectSchema;
2765
+ let Environment = class Environment {
2766
+ /**
2767
+ * Parses the given `.env` file and merges it with `process.env`.
2768
+ * Values from `process.env` take precedence.
2769
+ *
2770
+ * @private
2771
+ * @param filePath - Absolute path to the `.env` file.
2772
+ * @returns A dictionary of merged environment variables.
2773
+ */
2774
+ parseEnvFile(filePath) {
2775
+ try {
2776
+ if (!existsSync(filePath)) return { ...process.env };
2777
+ const fileContent = fs.readFileSync(filePath, "utf8");
2778
+ return {
2779
+ ...dotenv.parse(fileContent),
2780
+ ...process.env
2781
+ };
2782
+ } catch (error) {
2783
+ console.error(`Error parsing .env file: ${error}`);
2784
+ return {};
2785
+ }
2786
+ }
2787
+ /**
2788
+ * Retrieves the value of the specified environment variable.
2789
+ *
2790
+ * @template T
2791
+ * @param key - The name of the environment variable.
2792
+ * @returns The value of the variable, or `undefined` if not found.
2793
+ */
2794
+ get(key) {
2795
+ return this.parseEnvFile(path.join(process.cwd(), ".env"))[key];
2796
+ }
2797
+ /**
2798
+ * Retrieves the value of the specified environment variable.
2799
+ * Throws an error if the variable is not found.
2800
+ *
2801
+ * @template T
2802
+ * @param key - The name of the environment variable.
2803
+ * @throws {EnvironmentVariableNotFound} If the variable does not exist.
2804
+ * @returns The value of the variable.
2805
+ */
2806
+ getOrThrow(key) {
2807
+ const parsedEnv = this.parseEnvFile(path.join(process.cwd(), ".env"));
2808
+ if (!Object(parsedEnv).hasOwnProperty(key)) throw new EnvironmentVariableNotFound(key);
2809
+ return parsedEnv[key];
2810
+ }
2811
+ /**
2812
+ * Retrieves all available environment variables,
2813
+ * with `process.env` values taking precedence over `.env` values.
2814
+ *
2815
+ * @template T
2816
+ * @returns An object containing all environment variables.
2817
+ */
2818
+ getAll() {
2819
+ return this.parseEnvFile(path.join(process.cwd(), ".env"));
2820
+ }
2821
+ };
2822
+ Environment = __decorate([Service()], Environment);
2823
+ //#endregion
2824
+ //#region src/config.ts
2825
+ /**
2826
+ * @copyright 2024
2827
+ * @author Tareq Hossain
2828
+ * @email xtrinsic96@gmail.com
2829
+ * @url https://github.com/xtareq
2830
+ */
2831
+ init_helpers();
2832
+ function AppConfig(target) {
2833
+ Container$2.set({
2834
+ id: target,
2835
+ type: target
2836
+ });
2837
+ }
2838
+ var AvleonConfig = class {
2839
+ get(configClass) {
2840
+ const instance = Container$2.get(configClass);
2841
+ if (!instance) throw new Error(`Configuration for ${configClass.name} not found.`);
2842
+ return instance.config(new Environment());
2843
+ }
2844
+ };
2845
+ function GetConfig(token) {
2846
+ if (typeof token === "function" && token.prototype != null && typeof token.prototype.config === "function") {
2847
+ const instance = Container$2.get(token);
2848
+ if (!instance) throw new Error(`Class "${token.name}" is not registered as a config.`);
2849
+ return instance.config(inject(Environment));
2850
+ }
2851
+ const stored = Container$2.get(token);
2852
+ if (!stored) throw new Error("Config object is not registered.");
2853
+ return stored;
2854
+ }
2855
+ function CreateConfig(token, callback) {
2856
+ let env;
2857
+ try {
2858
+ env = Container$2.get(Environment);
2859
+ } catch (error) {
2860
+ env = new Environment();
2861
+ }
2862
+ let config = callback(env);
2863
+ Container$2.set(token, config);
2864
+ }
2865
+ //#endregion
2866
+ //#region src/logger.ts
2867
+ init_decorateMetadata();
2868
+ init_decorate();
2869
+ let LoggerService = class LoggerService {
2870
+ logger;
2871
+ constructor() {
2872
+ this.logger = pino({
2873
+ level: process.env.LOG_LEVEL || "info",
2874
+ transport: {
2875
+ target: "pino-pretty",
2876
+ options: {
2877
+ translateTime: "SYS:standard",
2878
+ ignore: "pid,hostname"
2879
+ }
2880
+ }
2881
+ });
2882
+ }
2883
+ getLogger() {
2884
+ return this.logger;
2885
+ }
2886
+ info(message, obj) {
2887
+ if (obj) this.logger.info(obj, message);
2888
+ else this.logger.info(message);
2889
+ }
2890
+ error(message, obj) {
2891
+ if (obj) this.logger.error(obj, message);
2892
+ else this.logger.error(message);
2893
+ }
2894
+ warn(message, obj) {
2895
+ if (obj) this.logger.warn(obj, message);
2896
+ else this.logger.warn(message);
2897
+ }
2898
+ debug(message, obj) {
2899
+ if (obj) this.logger.debug(obj, message);
2900
+ else this.logger.debug(message);
2901
+ }
2902
+ fatal(message, obj) {
2903
+ if (obj) this.logger.fatal(obj, message);
2904
+ else this.logger.fatal(message);
2905
+ }
2906
+ trace(message, obj) {
2907
+ if (obj) this.logger.trace(obj, message);
2908
+ else this.logger.trace(message);
2909
+ }
2910
+ };
2911
+ LoggerService = __decorate([AppService, __decorateMetadata("design:paramtypes", [])], LoggerService);
2912
+ //#endregion
2913
+ //#region src/cache.ts
2914
+ var CacheManager = class {
2915
+ store = /* @__PURE__ */ new Map();
2916
+ tagsMap = /* @__PURE__ */ new Map();
2917
+ redis = null;
2918
+ constructor(redisInstance) {
2919
+ this.redis = redisInstance || null;
2920
+ }
2921
+ redisTagKey(tag) {
2922
+ return `cache-tags:${tag}`;
2923
+ }
2924
+ async get(key) {
2925
+ if (this.redis) {
2926
+ const val = await this.redis.get(key);
2927
+ return val ? JSON.parse(val) : null;
2928
+ }
2929
+ const cached = this.store.get(key);
2930
+ return cached ? cached.data : null;
2931
+ }
2932
+ async set(key, value, tags = [], ttl = 3600) {
2933
+ const entry = {
2934
+ data: value,
2935
+ timestamp: Date.now()
2936
+ };
2937
+ if (this.redis) {
2938
+ await this.redis.set(key, JSON.stringify(entry.data), "EX", ttl);
2939
+ for (const tag of tags) await this.redis.sadd(this.redisTagKey(tag), key);
2940
+ } else {
2941
+ this.store.set(key, entry);
2942
+ for (const tag of tags) {
2943
+ if (!this.tagsMap.has(tag)) this.tagsMap.set(tag, /* @__PURE__ */ new Set());
2944
+ this.tagsMap.get(tag).add(key);
2945
+ }
2946
+ }
2947
+ }
2948
+ async delete(key) {
2949
+ if (this.redis) {
2950
+ await this.redis.del(key);
2951
+ const tagKeys = await this.redis.keys("cache-tags:*");
2952
+ for (const tagKey of tagKeys) await this.redis.srem(tagKey, key);
2953
+ } else {
2954
+ this.store.delete(key);
2955
+ for (const keys of this.tagsMap.values()) keys.delete(key);
2956
+ }
2957
+ }
2958
+ async invalidateTag(tag) {
2959
+ if (this.redis) {
2960
+ const tagKey = this.redisTagKey(tag);
2961
+ const keys = await this.redis.smembers(tagKey);
2962
+ if (keys.length) {
2963
+ await this.redis.del(...keys);
2964
+ await this.redis.del(tagKey);
2965
+ }
2966
+ } else {
2967
+ const keys = this.tagsMap.get(tag);
2968
+ if (keys) {
2969
+ for (const key of keys) this.store.delete(key);
2970
+ this.tagsMap.delete(tag);
2971
+ }
2972
+ }
2973
+ }
2974
+ };
2975
+ //#endregion
2976
+ //#region src/results.ts
2977
+ var Results = class {
2978
+ static code = 500;
2979
+ message = "Something going wrong";
2980
+ static Ok(data) {
2981
+ return new Ok(data);
2982
+ }
2983
+ static NoContent() {
2984
+ this.code = 204;
2985
+ }
2986
+ static OkStream() {}
2987
+ static NotFound(message) {
2988
+ return new NotFound(message);
2989
+ }
2990
+ };
2991
+ var Ok = class {
2992
+ constructor(data) {
2993
+ this.data = data;
2994
+ }
2995
+ };
2996
+ var NotFound = class {
2997
+ constructor(message) {
2998
+ this.message = message;
2999
+ }
3000
+ };
3001
+ //#endregion
3002
+ //#region src/index.ts
3003
+ /**
3004
+ * @copyright 2024
3005
+ * @author Tareq Hossain
3006
+ * @email xtrinsic96@gmail.com
3007
+ * @url https://github.com/xtareq
3008
+ */
3009
+ init_helpers();
3010
+ init_exceptions();
3011
+ init_container();
3012
+ init_kenx_provider();
3013
+ init_event_dispatcher();
3014
+ init_event_subscriber();
3015
+ init_container();
3016
+ const GetSchema = generateSwaggerSchema;
3017
+ const GetObjectSchema = CreateSwaggerObjectSchema;
76
3018
  const OpenApiOk = (args1) => {
77
- return sw.OpenApiResponse(200, args1, "Success");
3019
+ return OpenApiResponse$1(200, args1, "Success");
78
3020
  };
79
- exports.OpenApiOk = OpenApiOk;
80
- exports.OpenApiResponse = sw.OpenApiResponse;
81
- exports.OpenApiProperty = sw.OpenApiProperty;
82
- var container_1 = require("./container");
83
- Object.defineProperty(exports, "AvleonContainer", { enumerable: true, get: function () { return __importDefault(container_1).default; } });
3021
+ const OpenApiResponse = OpenApiResponse$1;
3022
+ const OpenApiProperty = OpenApiProperty$1;
3023
+ //#endregion
3024
+ export { API_CONTROLLER_METADATA_KEY, AUTHORIZATION_META_KEY, All, ApiController, AppAuthorization, AppConfig, AppMiddleware, AppService, AuthUser, AuthorizeMiddleware, Authorized, Avleon, AvleonApplication, AvleonConfig, Container as AvleonContainer, AvleonMiddleware, AvleonQueue, AvleonRequest, AvleonTest, BadRequestException, BaseHttpException, Body, CONTROLLER_META_KEY, CacheManager, CanAuthorize, Collection, CreateConfig, CreateSwaggerObjectSchema, DATASOURCE_META_KEY, DB, Delete, Dispatch, Environment, EventDispatcher, EventSubscriberRegistry, FEATURE_KEY, FileStorage, ForbiddenException, Get, GetConfig, GetObjectSchema, GetSchema, Header, Helper, HttpExceptions, HttpResponse, InjectRepository, InternalErrorException, LoggerService, NotFound, NotFoundException, Ok, OpenApi, OpenApiOk, OpenApiProperty, OpenApiResponse, OpenApiSchema, Options, PARAM_META_KEY, Param, Patch, Post, Private, Put, QUERY_META_KEY, Query, Queue, REQUEST_BODY_FILES_KEY, REQUEST_BODY_FILE_KEY, REQUEST_BODY_META_KEY, REQUEST_HEADER_META_KEY, REQUEST_METADATA_KEY, REQUEST_USER_META_KEY, ROUTE_META_KEY, Results, Route, SocketContextService, Subscribe, UnauthorizedException, UseMiddleware, Utility, ValidationErrorException, Validator, autoCast, createControllerDecorator, exclude, extrctParamFromUrl, findDuplicates, formatUrl, generateClassSchema, generateSwaggerSchema, getDataType, getLineNumber, getPrivateChannelResolver, getRegisteredControllers, getRegisteredServices, getSocketSubscribers, inject, isApiController, isClassValidator, isClassValidatorClass, isConstructor, isPrivate, isValidJsonString, isValidType, jsonToInstance, jsonToJs, normalizeParamsToJsonSchema, normalizePath, normalizeQueryDeep, parsedPath, pick, registerController, registerDataSource, registerKnex, registerService, registerSocketSubscriber, sleep, transformObjectByInstanceToObject, uuid, validateObjectByInstance, validateOrThrow, validateRequestBody };
3025
+
3026
+ //# sourceMappingURL=index.js.map