@avleon/core 0.0.13 → 0.0.14

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.
File without changes
@@ -0,0 +1 @@
1
+ "use strict";
@@ -39,12 +39,3 @@ export declare class ForbiddenException extends BaseHttpException {
39
39
  constructor(message: any);
40
40
  }
41
41
  export type HttpException = NotFoundException | BadRequestException | UnauthorizedException | InternalErrorException | ForbiddenException;
42
- export type HttpExceptions = {
43
- NotFound: (message: any) => NotFoundException;
44
- ValidationError: (message: any) => ValidationErrorException;
45
- BadRequest: (message: any) => BadRequestException;
46
- Unauthorized: (message: any) => UnauthorizedException;
47
- Forbidden: (message: any) => ForbiddenException;
48
- InternalError: (message: any) => InternalErrorException;
49
- };
50
- export declare const httpExcepitoins: HttpExceptions;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.httpExcepitoins = exports.ForbiddenException = exports.UnauthorizedException = exports.NotFoundException = exports.InternalErrorException = exports.ValidationErrorException = exports.BadRequestException = exports.BaseHttpException = void 0;
3
+ exports.ForbiddenException = exports.UnauthorizedException = exports.NotFoundException = exports.InternalErrorException = exports.ValidationErrorException = exports.BadRequestException = exports.BaseHttpException = void 0;
4
4
  /**
5
5
  * @copyright 2024
6
6
  * @author Tareq Hossain
@@ -65,11 +65,19 @@ class ForbiddenException extends BaseHttpException {
65
65
  }
66
66
  }
67
67
  exports.ForbiddenException = ForbiddenException;
68
- exports.httpExcepitoins = {
69
- NotFound: (message) => new NotFoundException(message),
70
- ValidationError: (message) => new ValidationErrorException(message),
71
- BadRequest: (message) => new BadRequestException(message),
72
- Unauthorized: (message) => new UnauthorizedException(message),
73
- Forbidden: (message) => new ForbiddenException(message),
74
- InternalError: (message) => new InternalErrorException(message)
75
- };
68
+ // export type HttpExceptions = {
69
+ // NotFound: (message: any) => NotFoundException,
70
+ // ValidationError: (message: any) =>ValidationErrorException,
71
+ // BadRequest: (message: any) => BadRequestException,
72
+ // Unauthorized: (message: any) => UnauthorizedException,
73
+ // Forbidden: (message: any) => ForbiddenException,
74
+ // InternalError: (message: any) => InternalErrorException
75
+ // }
76
+ // export const httpExcepitoins: HttpExceptions = {
77
+ // NotFound:(message:any)=>new NotFoundException(message),
78
+ // ValidationError:(message:any)=>new ValidationErrorException(message),
79
+ // BadRequest:(message:any)=>new BadRequestException(message),
80
+ // Unauthorized:(message:any)=>new UnauthorizedException(message),
81
+ // Forbidden:(message:any)=>new ForbiddenException(message),
82
+ // InternalError: (message:any)=> new InternalErrorException(message)
83
+ // }
package/dist/helpers.d.ts CHANGED
@@ -23,10 +23,10 @@ export declare function jsonToJs(value: string): any;
23
23
  export declare function jsonToInstance(value: string, instance: Constructor): any;
24
24
  export declare function transformObjectByInstanceToObject(instance: Constructor, value: object): Record<string, any>;
25
25
  export declare const isClassValidatorClass: (target: Constructor) => boolean;
26
- export declare function validateObjectByInstance(target: Constructor, value?: object, options?: 'object' | 'array'): Promise<any>;
26
+ export declare function validateObjectByInstance(target: Constructor, value?: object, options?: "object" | "array"): Promise<any>;
27
27
  type ValidationError = {
28
28
  count: number;
29
29
  errors: any;
30
30
  };
31
- export declare function validateRequestBody(target: Constructor, value: object, options?: 'object' | 'array'): ValidationError;
31
+ export declare function validateRequestBody(target: Constructor, value: object, options?: "object" | "array"): ValidationError;
32
32
  export {};
package/dist/helpers.js CHANGED
@@ -43,7 +43,7 @@ function inject(cls) {
43
43
  }
44
44
  function isConstructor(func) {
45
45
  // Check if the func is a function
46
- if (typeof func !== 'function') {
46
+ if (typeof func !== "function") {
47
47
  return false;
48
48
  }
49
49
  // Check if it's an arrow function or a built-in JavaScript function
@@ -51,13 +51,13 @@ function isConstructor(func) {
51
51
  return false;
52
52
  }
53
53
  // Check if it has a `prototype` property
54
- if (func.prototype && typeof func.prototype === 'object') {
54
+ if (func.prototype && typeof func.prototype === "object") {
55
55
  return true;
56
56
  }
57
57
  // If it's not a constructor, check if it can be called with the new keyword
58
58
  try {
59
59
  const instance = new func();
60
- return typeof instance === 'object';
60
+ return typeof instance === "object";
61
61
  }
62
62
  catch (e) {
63
63
  return false;
@@ -83,8 +83,7 @@ function parsedPath(ipath) {
83
83
  const isClassValidator = (target) => {
84
84
  try {
85
85
  const clsval = require("class-validator");
86
- const result = (0, class_validator_1.getMetadataStorage)()
87
- .getTargetValidationMetadatas(target, '', false, false);
86
+ const result = (0, class_validator_1.getMetadataStorage)().getTargetValidationMetadatas(target, "", false, false);
88
87
  return result.length > 0;
89
88
  }
90
89
  catch (err) {
@@ -216,7 +215,7 @@ const isClassValidatorClass = (target) => {
216
215
  }
217
216
  };
218
217
  exports.isClassValidatorClass = isClassValidatorClass;
219
- async function validateObjectByInstance(target, value = {}, options = 'array') {
218
+ async function validateObjectByInstance(target, value = {}, options = "array") {
220
219
  try {
221
220
  const { validateOrReject } = require("class-validator");
222
221
  const { plainToInstance } = require("class-transformer");
@@ -224,11 +223,16 @@ async function validateObjectByInstance(target, value = {}, options = 'array') {
224
223
  }
225
224
  catch (error) {
226
225
  if (typeof error == "object" && Array.isArray(error)) {
227
- const errors = options == 'object' ? error.reduce((acc, x) => {
228
- //acc[x.property] = Object.values(x.constraints);
229
- acc[x.property] = x.constraints;
230
- return acc;
231
- }, {}) : error.map(x => ({ path: x.property, constraints: x.constraints }));
226
+ const errors = options == "object"
227
+ ? error.reduce((acc, x) => {
228
+ //acc[x.property] = Object.values(x.constraints);
229
+ acc[x.property] = x.constraints;
230
+ return acc;
231
+ }, {})
232
+ : error.map((x) => ({
233
+ path: x.property,
234
+ constraints: x.constraints,
235
+ }));
232
236
  return errors;
233
237
  }
234
238
  else {
@@ -236,14 +240,16 @@ async function validateObjectByInstance(target, value = {}, options = 'array') {
236
240
  }
237
241
  }
238
242
  }
239
- function validateRequestBody(target, value, options = 'array') {
243
+ function validateRequestBody(target, value, options = "array") {
240
244
  if (!(0, exports.isClassValidatorClass)(target))
241
245
  return { count: 0, errors: {} };
242
246
  const error = (0, class_validator_1.validateSync)((0, class_transformer_1.plainToInstance)(target, value ? value : {}));
243
- const errors = options == 'object' ? error.reduce((acc, x) => {
244
- //acc[x.property] = Object.values(x.constraints);
245
- acc[x.property] = x.constraints;
246
- return acc;
247
- }, {}) : error.map(x => ({ path: x.property, constraints: x.constraints }));
247
+ const errors = options == "object"
248
+ ? error.reduce((acc, x) => {
249
+ //acc[x.property] = Object.values(x.constraints);
250
+ acc[x.property] = x.constraints;
251
+ return acc;
252
+ }, {})
253
+ : error.map((x) => ({ path: x.property, constraints: x.constraints }));
248
254
  return { count: error.length, errors };
249
255
  }
package/dist/icore.d.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  * @email xtrinsic96@gmail.com
5
5
  * @url https://github.com/xtareq
6
6
  */
7
- import { FastifyInstance, FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
7
+ import { FastifyReply, FastifyRequest, HookHandlerDoneFunction, InjectOptions, LightMyRequestResponse } from "fastify";
8
8
  import { Constructable } from "typedi";
9
9
  import { Constructor } from "./helpers";
10
10
  import { PathLike } from "fs";
@@ -27,9 +27,19 @@ export interface IRequest extends FastifyRequest {
27
27
  headers: any;
28
28
  user?: any;
29
29
  }
30
+ export interface DoneFunction extends HookHandlerDoneFunction {
31
+ }
30
32
  export interface IResponse extends FastifyReply {
31
33
  }
32
- export interface DoneFunction extends HookHandlerDoneFunction {
34
+ export type TestResponseType = LightMyRequestResponse;
35
+ export type TestResponse = TestResponseType | Promise<TestResponseType>;
36
+ export interface TestApplication {
37
+ get: (url: string, options?: InjectOptions) => TestResponse;
38
+ post: (url: string, options?: InjectOptions) => TestResponse;
39
+ put: (url: string, options?: InjectOptions) => TestResponse;
40
+ patch: (url: string, options?: InjectOptions) => TestResponse;
41
+ delete: (url: string, options?: InjectOptions) => TestResponse;
42
+ options: (url: string, options?: InjectOptions) => TestResponse;
33
43
  }
34
44
  export interface ParamMetaOptions {
35
45
  index: number;
@@ -39,6 +49,7 @@ export interface ParamMetaOptions {
39
49
  validate: boolean;
40
50
  dataType: any;
41
51
  validatorClass: boolean;
52
+ schema?: any;
42
53
  type: "route:param" | "route:query" | "route:body" | "route:header" | "route:user" | "route:file" | "route:files";
43
54
  }
44
55
  export interface ParamMetaFilesOptions {
@@ -64,7 +75,6 @@ type StaticFileOptions = {
64
75
  type MultipartOptions = {
65
76
  destination: PathLike;
66
77
  } & FastifyMultipartOptions;
67
- type AvleonApp = FastifyInstance;
68
78
  export type TestAppOptions = {
69
79
  controllers: Constructor[];
70
80
  };
@@ -78,7 +88,7 @@ export interface IAvleonApplication {
78
88
  useCors(corsOptions?: FastifyCorsOptions): void;
79
89
  useOpenApi<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
80
90
  useSwagger(options: OpenApiUiOptions): Promise<void>;
81
- useMultipart(options: MultipartOptions): IAvleonApplication;
91
+ useMultipart(options: MultipartOptions): void;
82
92
  useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]): void;
83
93
  useAuthoriztion<T extends any>(middleware: Constructor<T>): void;
84
94
  mapRoute<T extends (...args: any[]) => any>(method: "get" | "post" | "put" | "delete", path: string, fn: T): Promise<void>;
@@ -89,7 +99,7 @@ export interface IAvleonApplication {
89
99
  mapControllers(controllers: any[]): any;
90
100
  useStaticFiles(options?: StaticFileOptions): void;
91
101
  run(port?: number): Promise<void>;
92
- getTestApp(): any;
102
+ getTestApp(): TestApplication;
93
103
  }
94
104
  declare class AvleonApplication implements IAvleonApplication {
95
105
  private static instance;
@@ -120,7 +130,7 @@ declare class AvleonApplication implements IAvleonApplication {
120
130
  * Will remove in next major version
121
131
  */
122
132
  useSwagger(options: OpenApiUiOptions): Promise<void>;
123
- useMultipart(options: MultipartOptions): this;
133
+ useMultipart(options: MultipartOptions): void;
124
134
  private handleMiddlewares;
125
135
  private executeMiddlewares;
126
136
  /**
@@ -173,7 +183,7 @@ declare class AvleonApplication implements IAvleonApplication {
173
183
  useStaticFiles(options?: StaticFileOptions): void;
174
184
  initializeDatabase(): Promise<void>;
175
185
  run(port?: number): Promise<void>;
176
- getTestApp(buildOptions?: any): Promise<any>;
186
+ getTestApp(buildOptions?: any): TestApplication;
177
187
  }
178
188
  export type Application = typeof AvleonApplication;
179
189
  export interface ITestBuilder {
@@ -193,11 +203,11 @@ export declare class TestBuilder {
193
203
  static createBuilder(): TestBuilder;
194
204
  getController<T>(controller: Constructor<T>): T;
195
205
  getService<T>(service: Constructor<T>): T;
196
- getTestApplication(options: TestAppOptions): Promise<AvleonApp>;
197
- build(app: IAvleonApplication): any;
198
- fromApplication(app: IAvleonApplication): any;
206
+ getTestApplication(options: TestAppOptions): TestApplication;
207
+ build(app: IAvleonApplication): TestApplication;
208
+ fromApplication(app: IAvleonApplication): TestApplication;
199
209
  }
200
- export declare class Builder implements ITestBuilder, IAppBuilder {
210
+ export declare class Builder implements IAppBuilder {
201
211
  private static instance;
202
212
  private alreadyBuilt;
203
213
  private database;
@@ -207,12 +217,9 @@ export declare class Builder implements ITestBuilder, IAppBuilder {
207
217
  private testBuilder;
208
218
  private appConfig;
209
219
  private constructor();
210
- getTestApplication(): AvleonTestAppliction;
211
220
  static createAppBuilder(): Builder;
212
- static creatTestAppBuilder(): ITestBuilder;
213
221
  registerPlugin<T extends Function, S extends {}>(plugin: T, options: S): Promise<void>;
214
222
  addDataSource<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
215
- createTestApplication<T extends AvleonTestAppliction>(buildOptions?: any): any;
216
223
  build<T extends IAvleonApplication>(): T;
217
224
  }
218
225
  export {};
package/dist/icore.js CHANGED
@@ -94,7 +94,9 @@ class AvleonApplication {
94
94
  this.authorizeMiddleware = undefined;
95
95
  this.dataSource = undefined;
96
96
  this.metaCache = new Map();
97
- this.app = (0, fastify_1.default)();
97
+ this.app = (0, fastify_1.default)({
98
+ frameworkErrors: (error, req, res) => { },
99
+ });
98
100
  this.appConfig = new config_1.AppConfig();
99
101
  // this.app.setValidatorCompiler(() => () => true);
100
102
  }
@@ -163,8 +165,7 @@ class AvleonApplication {
163
165
  }
164
166
  useMultipart(options) {
165
167
  this.multipartOptions = options;
166
- this.app.register(multipart_1.default, options);
167
- return this;
168
+ this.app.register(multipart_1.default, Object.assign(Object.assign({}, this.multipartOptions), { attachFieldsToBody: true }));
168
169
  }
169
170
  handleMiddlewares(mclasses) {
170
171
  for (const mclass of mclasses) {
@@ -222,11 +223,21 @@ class AvleonApplication {
222
223
  const swaggerMeta = Reflect.getMetadata("route:openapi", prototype, method) || {};
223
224
  const authClsMethodMeata = Reflect.getMetadata(container_1.AUTHORIZATION_META_KEY, ctrl.constructor, method) || { authorize: false, options: undefined };
224
225
  const allMeta = this._processMeta(prototype, method);
226
+ let bodySchema = null;
227
+ allMeta.body.forEach((r) => {
228
+ if (r.schema) {
229
+ bodySchema = Object.assign({}, r.schema);
230
+ }
231
+ });
225
232
  const routePath = methodmetaOptions.path == "" ? "/" : methodmetaOptions.path;
233
+ let schema = Object.assign(Object.assign(Object.assign({}, swaggerControllerMeta), swaggerMeta), { tags: [tag] });
234
+ if (!swaggerMeta.body && bodySchema) {
235
+ schema = Object.assign(Object.assign({}, schema), { body: bodySchema });
236
+ }
226
237
  this.app.route({
227
238
  url: routePath,
228
239
  method: methodmetaOptions.method.toUpperCase(),
229
- schema: Object.assign(Object.assign(Object.assign({}, swaggerControllerMeta), swaggerMeta), { tags: [tag] }),
240
+ schema: Object.assign({}, schema),
230
241
  handler: async (req, res) => {
231
242
  let reqClone = req;
232
243
  if (authClsMethodMeata.authorize && this.authorizeMiddleware) {
@@ -279,6 +290,7 @@ class AvleonApplication {
279
290
  */
280
291
  async _mapArgs(req, meta) {
281
292
  var _a, e_2, _b, _c, _d, e_3, _e, _f;
293
+ var _g;
282
294
  if (!req.hasOwnProperty("_argsCache")) {
283
295
  Object.defineProperty(req, "_argsCache", {
284
296
  value: new Map(),
@@ -298,9 +310,9 @@ class AvleonApplication {
298
310
  header.key === "all" ? req.headers : req.headers[header.key]));
299
311
  if (meta.file) {
300
312
  try {
301
- for (var _g = true, _h = __asyncValues(meta.file), _j; _j = await _h.next(), _a = _j.done, !_a; _g = true) {
302
- _c = _j.value;
303
- _g = false;
313
+ for (var _h = true, _j = __asyncValues(meta.file), _k; _k = await _j.next(), _a = _k.done, !_a; _h = true) {
314
+ _c = _k.value;
315
+ _h = false;
304
316
  let f = _c;
305
317
  args[f.index] = await req.file();
306
318
  }
@@ -308,12 +320,13 @@ class AvleonApplication {
308
320
  catch (e_2_1) { e_2 = { error: e_2_1 }; }
309
321
  finally {
310
322
  try {
311
- if (!_g && !_a && (_b = _h.return)) await _b.call(_h);
323
+ if (!_h && !_a && (_b = _j.return)) await _b.call(_j);
312
324
  }
313
325
  finally { if (e_2) throw e_2.error; }
314
326
  }
315
327
  }
316
- if (meta.files) {
328
+ if (meta.files &&
329
+ ((_g = req.headers["content-type"]) === null || _g === void 0 ? void 0 : _g.startsWith("multipart/form-data")) === true) {
317
330
  const files = await req.saveRequestFiles();
318
331
  if (!files || files.length === 0) {
319
332
  throw new exceptions_1.BadRequestException({ error: "No files uploaded" });
@@ -328,9 +341,9 @@ class AvleonApplication {
328
341
  fields: file.fields,
329
342
  }));
330
343
  try {
331
- for (var _k = true, _l = __asyncValues(meta.files), _m; _m = await _l.next(), _d = _m.done, !_d; _k = true) {
332
- _f = _m.value;
333
- _k = false;
344
+ for (var _l = true, _m = __asyncValues(meta.files), _o; _o = await _m.next(), _d = _o.done, !_d; _l = true) {
345
+ _f = _o.value;
346
+ _l = false;
334
347
  let f = _f;
335
348
  const findex = fileInfo.findIndex((x) => x.fieldname == f.fieldName);
336
349
  if (f.fieldName != "all" && findex == -1) {
@@ -345,7 +358,7 @@ class AvleonApplication {
345
358
  catch (e_3_1) { e_3 = { error: e_3_1 }; }
346
359
  finally {
347
360
  try {
348
- if (!_k && !_d && (_e = _l.return)) await _e.call(_l);
361
+ if (!_l && !_d && (_e = _m.return)) await _e.call(_m);
349
362
  }
350
363
  finally { if (e_3) throw e_3.error; }
351
364
  }
@@ -402,6 +415,9 @@ class AvleonApplication {
402
415
  if ((0, container_1.isApiController)(controller)) {
403
416
  this.buildController(controller);
404
417
  }
418
+ else {
419
+ throw new system_exception_1.SystemUseError("Not a api controller.");
420
+ }
405
421
  }
406
422
  }
407
423
  }
@@ -555,16 +571,23 @@ class AvleonApplication {
555
571
  await this.app.listen({ port });
556
572
  console.log(`Application running on http://127.0.0.1:${port}`);
557
573
  }
558
- async getTestApp(buildOptions) {
574
+ getTestApp(buildOptions) {
559
575
  try {
560
576
  if (buildOptions && buildOptions.addDataSource) {
561
- const typeorm = await Promise.resolve().then(() => __importStar(require("typeorm")));
577
+ const typeorm = Promise.resolve().then(() => __importStar(require("typeorm")));
562
578
  if (!typeorm) {
563
579
  throw new system_exception_1.SystemUseError("TypeOrm not installed");
564
580
  }
565
- const datasource = new typeorm.DataSource(buildOptions.addDataSource);
566
- typedi_1.default.set("idatasource", datasource);
567
- await datasource.initialize();
581
+ typeorm.then(async (t) => {
582
+ try {
583
+ const datasource = new t.DataSource(buildOptions.addDataSource);
584
+ typedi_1.default.set("idatasource", datasource);
585
+ await datasource.initialize();
586
+ }
587
+ catch (error) {
588
+ console.error("Database can't initialized.", error);
589
+ }
590
+ });
568
591
  }
569
592
  this._mapControllers();
570
593
  this.rMap.forEach((value, key) => {
@@ -591,7 +614,15 @@ class AvleonApplication {
591
614
  }
592
615
  return res.status(handledErr.code).send(handledErr);
593
616
  });
594
- return this.app;
617
+ // return this.app as any;
618
+ return {
619
+ get: (url, options) => this.app.inject(Object.assign({ method: "GET", url }, options)),
620
+ post: (url, options) => this.app.inject(Object.assign({ method: "POST", url }, options)),
621
+ put: (url, options) => this.app.inject(Object.assign({ method: "PUT", url }, options)),
622
+ patch: (url, options) => this.app.inject(Object.assign({ method: "PATCH", url }, options)),
623
+ delete: (url, options) => this.app.inject(Object.assign({ method: "DELETE", url }, options)),
624
+ options: (url, options) => this.app.inject(Object.assign({ method: "OPTIONS", url }, options)),
625
+ };
595
626
  }
596
627
  catch (error) {
597
628
  throw new system_exception_1.SystemUseError("Can't get test appliction");
@@ -613,12 +644,12 @@ class TestBuilder {
613
644
  getService(service) {
614
645
  return typedi_1.default.get(service);
615
646
  }
616
- async getTestApplication(options) {
647
+ getTestApplication(options) {
617
648
  const app = AvleonApplication.getInternalApp({
618
649
  dataSourceOptions: this.dataSourceOptions,
619
650
  });
620
651
  app.mapControllers([...options.controllers]);
621
- const fa = await app.getTestApp();
652
+ const fa = app.getTestApp();
622
653
  return fa;
623
654
  }
624
655
  build(app) {
@@ -636,22 +667,12 @@ class Builder {
636
667
  this.testBuilder = false;
637
668
  this.appConfig = new config_1.AppConfig();
638
669
  }
639
- getTestApplication() {
640
- throw new Error("Method not implemented.");
641
- }
642
670
  static createAppBuilder() {
643
671
  if (!Builder.instance) {
644
672
  Builder.instance = new Builder();
645
673
  }
646
674
  return Builder.instance;
647
675
  }
648
- static creatTestAppBuilder() {
649
- if (!Builder.instance) {
650
- Builder.instance = new Builder();
651
- Builder.instance.testBuilder = true;
652
- }
653
- return Builder.instance;
654
- }
655
676
  async registerPlugin(plugin, options) {
656
677
  container_1.default.set(plugin, plugin.prototype);
657
678
  }
@@ -665,28 +686,6 @@ class Builder {
665
686
  this.dataSourceOptions = openApiConfig;
666
687
  }
667
688
  }
668
- createTestApplication(buildOptions) {
669
- return {
670
- addDataSource: (dataSourceOptions) => (this.dataSourceOptions = dataSourceOptions),
671
- getApp: async (options) => {
672
- const app = AvleonApplication.getInternalApp({
673
- database: this.database,
674
- dataSourceOptions: buildOptions.datSource,
675
- });
676
- app.mapControllers([...options.controllers]);
677
- const _tapp = await app.getTestApp();
678
- return {
679
- async get(url, options) {
680
- const res = await _tapp.inject(Object.assign({ url, method: "GET" }, options));
681
- return res;
682
- },
683
- };
684
- },
685
- getController(controller) {
686
- return typedi_1.default.get(controller);
687
- },
688
- };
689
- }
690
689
  build() {
691
690
  if (this.alreadyBuilt) {
692
691
  throw new Error("Already built");
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * @email xtrinsic96@gmail.com
5
5
  * @url https://github.com/xtareq
6
6
  */
7
+ import * as sw from "./swagger-schema";
7
8
  export * from "./icore";
8
9
  export { inject, validateRequestBody } from "./helpers";
9
10
  export * from "./decorators";
@@ -21,4 +22,6 @@ export * from "./queue";
21
22
  export * from "./security";
22
23
  export * from "./multipart";
23
24
  export * from "./file-storage";
25
+ export * from "./logger";
26
+ export declare const GetSchema: typeof sw.generateSwaggerSchema;
24
27
  export { default as Container } from "./container";
package/dist/index.js CHANGED
@@ -1,10 +1,4 @@
1
1
  "use strict";
2
- /**
3
- * @copyright 2024
4
- * @author Tareq Hossain
5
- * @email xtrinsic96@gmail.com
6
- * @url https://github.com/xtareq
7
- */
8
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
3
  if (k2 === undefined) k2 = k;
10
4
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -16,6 +10,28 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
16
10
  if (k2 === undefined) k2 = k;
17
11
  o[k2] = m[k];
18
12
  }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
19
35
  var __exportStar = (this && this.__exportStar) || function(m, exports) {
20
36
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
21
37
  };
@@ -23,7 +39,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
23
39
  return (mod && mod.__esModule) ? mod : { "default": mod };
24
40
  };
25
41
  Object.defineProperty(exports, "__esModule", { value: true });
26
- exports.Container = exports.validateRequestBody = exports.inject = void 0;
42
+ exports.Container = exports.GetSchema = exports.validateRequestBody = exports.inject = 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"));
27
50
  __exportStar(require("./icore"), exports);
28
51
  var helpers_1 = require("./helpers");
29
52
  Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return helpers_1.inject; } });
@@ -43,5 +66,7 @@ __exportStar(require("./queue"), exports);
43
66
  __exportStar(require("./security"), exports);
44
67
  __exportStar(require("./multipart"), exports);
45
68
  __exportStar(require("./file-storage"), exports);
69
+ __exportStar(require("./logger"), exports);
70
+ exports.GetSchema = sw.generateSwaggerSchema;
46
71
  var container_1 = require("./container");
47
72
  Object.defineProperty(exports, "Container", { enumerable: true, get: function () { return __importDefault(container_1).default; } });
@@ -0,0 +1,12 @@
1
+ import pino from "pino";
2
+ export declare class LoggerService {
3
+ private logger;
4
+ constructor();
5
+ getLogger(): pino.Logger;
6
+ info(message: string, obj?: any): void;
7
+ error(message: string, obj?: any): void;
8
+ warn(message: string, obj?: any): void;
9
+ debug(message: string, obj?: any): void;
10
+ fatal(message: string, obj?: any): void;
11
+ trace(message: string, obj?: any): void;
12
+ }
package/dist/logger.js ADDED
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.LoggerService = void 0;
16
+ const pino_1 = __importDefault(require("pino"));
17
+ const decorators_1 = require("./decorators");
18
+ let LoggerService = class LoggerService {
19
+ constructor() {
20
+ this.logger = (0, pino_1.default)({
21
+ level: process.env.LOG_LEVEL || "info",
22
+ transport: {
23
+ target: "pino-pretty",
24
+ options: {
25
+ translateTime: "SYS:standard",
26
+ ignore: "pid,hostname",
27
+ },
28
+ },
29
+ });
30
+ }
31
+ getLogger() {
32
+ return this.logger;
33
+ }
34
+ info(message, obj) {
35
+ if (obj) {
36
+ this.logger.info(obj, message);
37
+ }
38
+ else {
39
+ this.logger.info(message);
40
+ }
41
+ }
42
+ error(message, obj) {
43
+ if (obj) {
44
+ this.logger.error(obj, message);
45
+ }
46
+ else {
47
+ this.logger.error(message);
48
+ }
49
+ }
50
+ warn(message, obj) {
51
+ if (obj) {
52
+ this.logger.warn(obj, message);
53
+ }
54
+ else {
55
+ this.logger.warn(message);
56
+ }
57
+ }
58
+ debug(message, obj) {
59
+ if (obj) {
60
+ this.logger.debug(obj, message);
61
+ }
62
+ else {
63
+ this.logger.debug(message);
64
+ }
65
+ }
66
+ fatal(message, obj) {
67
+ if (obj) {
68
+ this.logger.fatal(obj, message);
69
+ }
70
+ else {
71
+ this.logger.fatal(message);
72
+ }
73
+ }
74
+ trace(message, obj) {
75
+ if (obj) {
76
+ this.logger.trace(obj, message);
77
+ }
78
+ else {
79
+ this.logger.trace(message);
80
+ }
81
+ }
82
+ };
83
+ exports.LoggerService = LoggerService;
84
+ exports.LoggerService = LoggerService = __decorate([
85
+ decorators_1.AppService,
86
+ __metadata("design:paramtypes", [])
87
+ ], LoggerService);
package/dist/params.js CHANGED
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.AuthUser = exports.Header = exports.Body = exports.Query = exports.Param = void 0;
10
10
  const container_1 = require("./container");
11
11
  const helpers_1 = require("./helpers");
12
+ const swagger_schema_1 = require("./swagger-schema");
12
13
  function createParamDecorator(type) {
13
14
  return function (key, options = {}) {
14
15
  return function (target, propertyKey, parameterIndex) {
@@ -27,6 +28,9 @@ function createParamDecorator(type) {
27
28
  validate: options.validate || true,
28
29
  dataType: (0, helpers_1.getDataType)(paramDataType),
29
30
  validatorClass: (0, helpers_1.isClassValidatorClass)(paramDataType),
31
+ schema: (0, helpers_1.isClassValidatorClass)(paramDataType)
32
+ ? (0, swagger_schema_1.generateSwaggerSchema)(paramDataType)
33
+ : null,
30
34
  type,
31
35
  });
32
36
  switch (type) {
@@ -4,7 +4,6 @@
4
4
  * @email xtrinsic96@gmail.com
5
5
  * @url https://github.com/xtareq
6
6
  */
7
- import "reflect-metadata";
8
7
  import { ClassConstructor } from "class-transformer";
9
8
  export interface IHttpResponse<T extends any> {
10
9
  message: string;
@@ -14,6 +13,8 @@ export declare class HttpResponse {
14
13
  static Ok<T>(obj: any, s?: ClassConstructor<T>): IHttpResponse<T>;
15
14
  static Created<T>(obj: any, s?: ClassConstructor<T>): IHttpResponse<T>;
16
15
  static NoContent(): IHttpResponse<null>;
16
+ }
17
+ export declare class HttpExceptions {
17
18
  static BadRequest(message: string, data?: any): IHttpResponse<any>;
18
19
  static Unauthorized(message: string, data?: any): IHttpResponse<any>;
19
20
  static Forbidden(message: string, data?: any): IHttpResponse<any>;
package/dist/response.js CHANGED
@@ -1,13 +1,12 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HttpExceptions = exports.HttpResponse = void 0;
2
4
  /**
3
5
  * @copyright 2024
4
6
  * @author Tareq Hossain
5
7
  * @email xtrinsic96@gmail.com
6
8
  * @url https://github.com/xtareq
7
9
  */
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.HttpResponse = void 0;
10
- require("reflect-metadata");
11
10
  const class_transformer_1 = require("class-transformer");
12
11
  function isClassTransformerClass(target) {
13
12
  const prototype = target.prototype;
@@ -49,6 +48,9 @@ class HttpResponse {
49
48
  static NoContent() {
50
49
  return { message: "no content", data: null };
51
50
  }
51
+ }
52
+ exports.HttpResponse = HttpResponse;
53
+ class HttpExceptions {
52
54
  static BadRequest(message, data = null) {
53
55
  return { message: message, data: data };
54
56
  }
@@ -74,4 +76,4 @@ class HttpResponse {
74
76
  return { message: message, data: data };
75
77
  }
76
78
  }
77
- exports.HttpResponse = HttpResponse;
79
+ exports.HttpExceptions = HttpExceptions;
@@ -1,7 +1 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
1
  export declare function generateSwaggerSchema(classType: any): any;
@@ -7,22 +7,28 @@ exports.generateSwaggerSchema = generateSwaggerSchema;
7
7
  * @email xtrinsic96@gmail.com
8
8
  * @url https://github.com/xtareq
9
9
  */
10
+ const class_validator_1 = require("class-validator");
10
11
  function generateSwaggerSchema(classType) {
11
- const { getMetadataStorage } = require("class-validator");
12
- const { plainToInstance } = require("class-transformer");
13
- //const { isArray } = require("lodash"); // Add lodash for array check
14
- const metadataStorage = getMetadataStorage();
15
- const validationMetadata = metadataStorage.getTargetValidationMetadatas(classType, "", true);
12
+ const metadataStorage = (0, class_validator_1.getMetadataStorage)();
13
+ const validationMetadata = metadataStorage.getTargetValidationMetadatas(classType, "", true, false);
16
14
  const schema = {
17
15
  type: "object",
18
16
  properties: {},
19
17
  required: [],
20
18
  };
21
- validationMetadata.forEach((meta) => {
22
- var _a, _b;
23
- const propertyName = meta.propertyName;
24
- // Infer the type dynamically using Reflect metadata
25
- const propertyType = Reflect.getMetadata("design:type", classType.prototype, propertyName);
19
+ const prototype = classType.prototype;
20
+ const propertyKeys = new Set([
21
+ ...Object.getOwnPropertyNames(prototype),
22
+ ...validationMetadata.map((m) => m.propertyName),
23
+ ]);
24
+ propertyKeys.forEach((propertyName) => {
25
+ var _a;
26
+ if (!propertyName || propertyName === "constructor")
27
+ return;
28
+ const openApiMeta = Reflect.getMetadata("property:openapi", prototype, propertyName);
29
+ if (openApiMeta === null || openApiMeta === void 0 ? void 0 : openApiMeta.exclude)
30
+ return;
31
+ const propertyType = Reflect.getMetadata("design:type", prototype, propertyName);
26
32
  let swaggerProperty = {};
27
33
  switch (propertyType) {
28
34
  case String:
@@ -39,85 +45,101 @@ function generateSwaggerSchema(classType) {
39
45
  swaggerProperty.format = "date-time";
40
46
  break;
41
47
  case Array:
42
- // Attempt to infer array item type
43
- const arrayItemType = Reflect.getMetadata("design:type", classType.prototype, propertyName + "[0]" // Attempt to get array item type. Very fragile.
44
- );
45
- if (arrayItemType) {
46
- swaggerProperty.type = "array";
47
- swaggerProperty.items = {
48
- type: arrayItemType.name.toLowerCase(), // basic type inference
49
- };
50
- if (arrayItemType === Object) {
51
- //try to infer the Object type within array
52
- const nestedSchema = generateSwaggerSchema(Reflect.getMetadata("design:type", classType.prototype, propertyName + "[0]"));
53
- swaggerProperty.items = nestedSchema;
54
- }
55
- }
56
- else {
57
- swaggerProperty.type = "array";
58
- swaggerProperty.items = {}; // Array of unknown type
59
- }
48
+ swaggerProperty.type = "array";
49
+ swaggerProperty.items = { type: "string" }; // fallback
60
50
  break;
61
51
  case Object:
62
- //Nested object
63
- const nestedSchema = generateSwaggerSchema(Reflect.getMetadata("design:type", classType.prototype, propertyName));
64
- swaggerProperty = nestedSchema;
52
+ swaggerProperty = generateSwaggerSchema(propertyType);
65
53
  break;
66
54
  default:
67
- swaggerProperty.type = ((_a = propertyType === null || propertyType === void 0 ? void 0 : propertyType.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || "string"; // Default to string if type cannot be inferred
55
+ swaggerProperty.type = ((_a = propertyType === null || propertyType === void 0 ? void 0 : propertyType.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || "string";
56
+ }
57
+ // Apply OpenApi metadata if present
58
+ if (openApiMeta) {
59
+ swaggerProperty = Object.assign(Object.assign({}, swaggerProperty), extractOpenApiFields(openApiMeta));
68
60
  }
69
61
  schema.properties[propertyName] = swaggerProperty;
70
- (_b = meta.constraints) === null || _b === void 0 ? void 0 : _b.forEach((constraint) => {
71
- switch (constraint.name) {
72
- case "isNotEmpty":
73
- if (!schema.required.includes(propertyName)) {
74
- schema.required.push(propertyName);
75
- }
76
- break;
77
- case "minLength":
78
- schema.properties[propertyName].minLength = constraint.constraints[0];
79
- break;
80
- case "maxLength":
81
- schema.properties[propertyName].maxLength = constraint.constraints[0];
82
- break;
83
- case "min":
84
- schema.properties[propertyName].minimum = constraint.constraints[0];
85
- break;
86
- case "max":
87
- schema.properties[propertyName].maximum = constraint.constraints[0];
88
- break;
89
- case "isEmail":
90
- schema.properties[propertyName].format = "email";
91
- break;
92
- case "isDate":
93
- schema.properties[propertyName].format = "date-time";
94
- break;
95
- case "isIn":
96
- schema.properties[propertyName].enum = constraint.constraints[0];
97
- break;
98
- case "isNumber":
99
- schema.properties[propertyName].type = "number";
100
- break;
101
- case "isInt":
102
- schema.properties[propertyName].type = "integer";
103
- break;
104
- case "isBoolean":
105
- schema.properties[propertyName].type = "boolean";
106
- break;
107
- case "isString":
108
- schema.properties[propertyName].type = "string";
109
- break;
110
- case "isOptional":
111
- if (schema.required.includes(propertyName)) {
112
- schema.required = schema.required.filter((item) => item !== propertyName);
113
- }
114
- break;
115
- // Add more cases for other validators as needed
116
- }
117
- });
62
+ });
63
+ // Handle validation rules
64
+ validationMetadata.forEach((meta) => {
65
+ const propertyName = meta.propertyName;
66
+ switch (meta.name) {
67
+ case "isNotEmpty":
68
+ if (!schema.required.includes(propertyName)) {
69
+ schema.required.push(propertyName);
70
+ }
71
+ break;
72
+ case "isDefined":
73
+ if (!schema.required.includes(propertyName)) {
74
+ schema.required.push(propertyName);
75
+ }
76
+ break;
77
+ case "isOptional":
78
+ schema.required = schema.required.filter((item) => item !== propertyName);
79
+ break;
80
+ case "minLength":
81
+ schema.properties[propertyName].minLength = meta.constraints[0];
82
+ break;
83
+ case "maxLength":
84
+ schema.properties[propertyName].maxLength = meta.constraints[0];
85
+ break;
86
+ case "min":
87
+ schema.properties[propertyName].minimum = meta.constraints[0];
88
+ break;
89
+ case "max":
90
+ schema.properties[propertyName].maximum = meta.constraints[0];
91
+ break;
92
+ case "isEmail":
93
+ schema.properties[propertyName].format = "email";
94
+ break;
95
+ case "isDate":
96
+ schema.properties[propertyName].format = "date-time";
97
+ break;
98
+ case "isIn":
99
+ schema.properties[propertyName].enum = meta.constraints[0];
100
+ break;
101
+ case "isNumber":
102
+ schema.properties[propertyName].type = "number";
103
+ break;
104
+ case "isInt":
105
+ schema.properties[propertyName].type = "integer";
106
+ break;
107
+ case "isBoolean":
108
+ schema.properties[propertyName].type = "boolean";
109
+ break;
110
+ case "isString":
111
+ schema.properties[propertyName].type = "string";
112
+ break;
113
+ }
118
114
  });
119
115
  return schema;
120
116
  }
117
+ function extractOpenApiFields(meta) {
118
+ const result = {};
119
+ const fields = [
120
+ "description",
121
+ "summary",
122
+ "deprecated",
123
+ "example",
124
+ "enum",
125
+ "format",
126
+ "default",
127
+ "minimum",
128
+ "maximum",
129
+ "minLength",
130
+ "maxLength",
131
+ "pattern",
132
+ "oneOf",
133
+ "allOf",
134
+ "anyOf",
135
+ ];
136
+ fields.forEach((field) => {
137
+ if (meta[field] !== undefined) {
138
+ result[field] = meta[field];
139
+ }
140
+ });
141
+ return result;
142
+ }
121
143
  // export function generateSwaggerSchema(classType: any) {
122
144
  // const { getMetadataStorage } = require("class-validator");
123
145
  // const { plainToInstance } = require("class-transformer");
package/package.json CHANGED
@@ -1,52 +1,54 @@
1
- {
2
- "name": "@avleon/core",
3
- "version": "0.0.13",
4
- "main": "./dist/index.js",
5
- "scripts": {
6
- "build": "rimraf dist && tsc",
7
- "watch": "tsc-watch",
8
- "test": "jest",
9
- "test:watch": "jest --watch"
10
- },
11
- "keywords": [],
12
- "author": "Tareq Hossain",
13
- "license": "ISC",
14
- "devDependencies": {
15
- "@types/jest": "^29.5.14",
16
- "class-transformer": "^0.5.1",
17
- "class-validator": "^0.14.1",
18
- "jest": "^29.7.0",
19
- "nodemon": "^3.1.7",
20
- "sharp": "^0.33.5",
21
- "ts-jest": "^29.2.5",
22
- "ts-node": "^10.9.2",
23
- "tsc-watch": "^6.2.1",
24
- "typeorm": "^0.3.20",
25
- "typescript": "^5.7.2"
26
- },
27
- "dependencies": {
28
- "@fastify/cors": "^11.0.0",
29
- "@fastify/multipart": "^9.0.3",
30
- "@fastify/static": "^8.1.1",
31
- "@fastify/swagger": "^9.4.0",
32
- "@fastify/swagger-ui": "^5.1.0",
33
- "bcryptjs": "^3.0.2",
34
- "dotenv": "^16.4.7",
35
- "fastify": "^5.1.0",
36
- "reflect-metadata": "^0.2.2",
37
- "typedi": "^0.10.0"
38
- },
39
- "peerDependencies": {
40
- "typeorm": "^0.3.20",
41
- "class-transformer": "^0.5.1",
42
- "class-validator": "^0.14.1"
43
- },
44
- "directories": {
45
- "test": "tests"
46
- },
47
- "description": "avleon core",
48
- "repository": {
49
- "type": "git",
50
- "url": "git+https://github.com/avleonjs/avleon-core"
51
- }
1
+ {
2
+ "name": "@avleon/core",
3
+ "version": "0.0.14",
4
+ "main": "./dist/index.js",
5
+ "scripts": {
6
+ "build": "rimraf dist && tsc",
7
+ "watch": "tsc-watch",
8
+ "test": "jest",
9
+ "test:watch": "jest --watch"
10
+ },
11
+ "keywords": [],
12
+ "author": "Tareq Hossain",
13
+ "license": "ISC",
14
+ "devDependencies": {
15
+ "@types/jest": "^29.5.14",
16
+ "class-transformer": "^0.5.1",
17
+ "class-validator": "^0.14.1",
18
+ "jest": "^29.7.0",
19
+ "nodemon": "^3.1.7",
20
+ "sharp": "^0.33.5",
21
+ "ts-jest": "^29.2.5",
22
+ "ts-node": "^10.9.2",
23
+ "tsc-watch": "^6.2.1",
24
+ "typeorm": "^0.3.20",
25
+ "typescript": "^5.7.2"
26
+ },
27
+ "dependencies": {
28
+ "@fastify/cors": "^11.0.0",
29
+ "@fastify/multipart": "^9.0.3",
30
+ "@fastify/static": "^8.1.1",
31
+ "@fastify/swagger": "^9.4.0",
32
+ "@fastify/swagger-ui": "^5.1.0",
33
+ "bcryptjs": "^3.0.2",
34
+ "dotenv": "^16.4.7",
35
+ "fastify": "^5.1.0",
36
+ "pino": "^9.6.0",
37
+ "pino-pretty": "^13.0.0",
38
+ "reflect-metadata": "^0.2.2",
39
+ "typedi": "^0.10.0"
40
+ },
41
+ "peerDependencies": {
42
+ "class-transformer": "^0.5.1",
43
+ "class-validator": "^0.14.1",
44
+ "typeorm": "^0.3.20"
45
+ },
46
+ "directories": {
47
+ "test": "tests"
48
+ },
49
+ "description": "avleon core",
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/avleonjs/avleon-core"
53
+ }
52
54
  }