@avleon/core 0.0.26 → 0.0.28

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 (41) hide show
  1. package/README.md +601 -561
  2. package/package.json +38 -6
  3. package/src/application.ts +104 -125
  4. package/src/authentication.ts +16 -16
  5. package/src/cache.ts +91 -91
  6. package/src/collection.test.ts +71 -0
  7. package/src/collection.ts +344 -254
  8. package/src/config.test.ts +35 -0
  9. package/src/config.ts +85 -42
  10. package/src/constants.ts +1 -1
  11. package/src/container.ts +54 -54
  12. package/src/controller.ts +125 -127
  13. package/src/decorators.ts +27 -27
  14. package/src/environment-variables.ts +53 -46
  15. package/src/exceptions/http-exceptions.ts +86 -86
  16. package/src/exceptions/index.ts +1 -1
  17. package/src/exceptions/system-exception.ts +35 -34
  18. package/src/file-storage.ts +206 -206
  19. package/src/helpers.ts +324 -328
  20. package/src/icore.ts +66 -90
  21. package/src/index.ts +30 -30
  22. package/src/interfaces/avleon-application.ts +32 -40
  23. package/src/logger.ts +72 -72
  24. package/src/map-types.ts +159 -159
  25. package/src/middleware.ts +119 -98
  26. package/src/multipart.ts +116 -116
  27. package/src/openapi.ts +372 -372
  28. package/src/params.ts +111 -111
  29. package/src/queue.ts +126 -126
  30. package/src/response.ts +74 -74
  31. package/src/results.ts +30 -30
  32. package/src/route-methods.ts +186 -186
  33. package/src/swagger-schema.ts +213 -213
  34. package/src/testing.ts +220 -220
  35. package/src/types/app-builder.interface.ts +18 -19
  36. package/src/types/application.interface.ts +7 -9
  37. package/src/utils/hash.ts +8 -5
  38. package/src/utils/index.ts +2 -2
  39. package/src/utils/optional-require.ts +50 -50
  40. package/src/validation.ts +160 -156
  41. package/src/validator-extend.ts +25 -25
package/src/icore.ts CHANGED
@@ -57,7 +57,6 @@ import { MultipartFile } from "./multipart";
57
57
  import { validateOrThrow } from "./validation";
58
58
  import { optionalRequire } from "./utils";
59
59
 
60
-
61
60
  export type FuncRoute = {
62
61
  handler: any;
63
62
  middlewares?: any[];
@@ -73,11 +72,9 @@ export interface IRequest extends FastifyRequest {
73
72
  user?: any;
74
73
  }
75
74
 
76
-
77
-
78
- export interface DoneFunction extends HookHandlerDoneFunction { }
75
+ export interface DoneFunction extends HookHandlerDoneFunction {}
79
76
  // IResponse
80
- export interface IResponse extends FastifyReply { }
77
+ export interface IResponse extends FastifyReply {}
81
78
 
82
79
  export type TestResponseType = LightMyRequestResponse;
83
80
  export type TestResponse = TestResponseType | Promise<TestResponseType>;
@@ -103,13 +100,13 @@ export interface ParamMetaOptions {
103
100
  validatorClass: boolean;
104
101
  schema?: any;
105
102
  type:
106
- | "route:param"
107
- | "route:query"
108
- | "route:body"
109
- | "route:header"
110
- | "route:user"
111
- | "route:file"
112
- | "route:files";
103
+ | "route:param"
104
+ | "route:query"
105
+ | "route:body"
106
+ | "route:header"
107
+ | "route:user"
108
+ | "route:file"
109
+ | "route:files";
113
110
  }
114
111
 
115
112
  export interface ParamMetaFilesOptions {
@@ -159,7 +156,7 @@ type AvleonApp = FastifyInstance;
159
156
 
160
157
  export type TestAppOptions = {
161
158
  controllers: Constructor[];
162
- dataSource?: DataSource
159
+ dataSource?: DataSource;
163
160
  };
164
161
 
165
162
  export interface AvleonTestAppliction {
@@ -169,9 +166,9 @@ export interface AvleonTestAppliction {
169
166
  }
170
167
 
171
168
  export type AutoControllerOptions = {
172
- auto: true,
173
- path?: string
174
- }
169
+ auto: true;
170
+ path?: string;
171
+ };
175
172
  export interface IAvleonApplication {
176
173
  isDevelopment(): boolean;
177
174
  useCors(corsOptions?: FastifyCorsOptions): void;
@@ -191,7 +188,7 @@ export interface IAvleonApplication {
191
188
  ): void;
192
189
 
193
190
  useMultipart(options: MultipartOptions): void;
194
- useCache(options: any): void
191
+ useCache(options: any): void;
195
192
 
196
193
  useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]): void;
197
194
  useAuthoriztion<T extends any>(middleware: Constructor<T>): void;
@@ -235,7 +232,7 @@ export class AvleonApplication {
235
232
  private dataSource?: DataSource = undefined;
236
233
  private isMapFeatures = false;
237
234
  private registerControllerAuto = false;
238
- private registerControllerPath = './src';
235
+ private registerControllerPath = "./src";
239
236
 
240
237
  private metaCache = new Map<string, MethodParamMeta>();
241
238
  private multipartOptions: FastifyMultipartOptions | undefined;
@@ -244,7 +241,6 @@ export class AvleonApplication {
244
241
  this.appConfig = new AppConfig();
245
242
  }
246
243
 
247
-
248
244
  static getApp(): AvleonApplication {
249
245
  let isTestEnv = process.env.NODE_ENV == "test";
250
246
  if (!AvleonApplication.instance) {
@@ -267,9 +263,7 @@ export class AvleonApplication {
267
263
  buildOptions.dataSourceOptions,
268
264
  ) as DataSource;
269
265
 
270
- Container.set<DataSource>("idatasource",
271
- datasource,
272
- );
266
+ Container.set<DataSource>("idatasource", datasource);
273
267
  AvleonApplication.instance.dataSource = datasource;
274
268
  }
275
269
  return AvleonApplication.instance;
@@ -280,7 +274,6 @@ export class AvleonApplication {
280
274
  return env.get("NODE_ENV") == "development";
281
275
  }
282
276
 
283
-
284
277
  private async initSwagger(options: OpenApiUiOptions) {
285
278
  const { routePrefix, logo, ui, theme, configuration, ...restOptions } =
286
279
  options;
@@ -296,26 +289,27 @@ export class AvleonApplication {
296
289
  if (options.ui && options.ui == "scalar") {
297
290
  const scalarPlugin = optionalRequire("@scalar/fastify-api-reference", {
298
291
  failOnMissing: true,
299
- customMessage: 'Install "@scalar/fastify-api-reference" to enable API docs.\n\n npm install @scalar/fastify-api-reference',
292
+ customMessage:
293
+ "Install \"@scalar/fastify-api-reference\" to enable API docs.\n\n npm install @scalar/fastify-api-reference",
300
294
  });
301
295
  await this.app.register(scalarPlugin, {
302
296
  routePrefix: rPrefix as any,
303
297
  configuration: configuration
304
298
  ? configuration
305
299
  : {
306
- metaData: {
307
- title: "Avleon Api",
308
- ogTitle: "Avleon",
300
+ metaData: {
301
+ title: "Avleon Api",
302
+ ogTitle: "Avleon",
303
+ },
304
+ theme: options.theme ? options.theme : "kepler",
305
+ favicon: "/static/favicon.png",
309
306
  },
310
- theme: options.theme ? options.theme : "kepler",
311
- favicon: "/static/favicon.png",
312
- },
313
307
  });
314
308
  } else {
315
-
316
309
  const fastifySwaggerUi = optionalRequire("@fastify/swagger-ui", {
317
310
  failOnMissing: true,
318
- customMessage: 'Install "@fastify/swagger-ui" to enable API docs.\n\n npm install @fastify/swagger-ui',
311
+ customMessage:
312
+ "Install \"@fastify/swagger-ui\" to enable API docs.\n\n npm install @fastify/swagger-ui",
319
313
  });
320
314
  await this.app.register(fastifySwaggerUi, {
321
315
  logo: logo ? logo : null,
@@ -327,8 +321,8 @@ export class AvleonApplication {
327
321
 
328
322
  private _isConfigClass<T>(input: any): input is ConfigClass<T> {
329
323
  return (
330
- typeof input === 'function' &&
331
- typeof input.prototype === 'object' &&
324
+ typeof input === "function" &&
325
+ typeof input.prototype === "object" &&
332
326
  input.prototype?.constructor === input
333
327
  );
334
328
  }
@@ -344,9 +338,7 @@ export class AvleonApplication {
344
338
  this.app.register(cors, coptions);
345
339
  }
346
340
 
347
- useOpenApi<T = OpenApiUiOptions>(
348
- configOrClass: OpenApiConfigInput<T>
349
- ) {
341
+ useOpenApi<T = OpenApiUiOptions>(configOrClass: OpenApiConfigInput<T>) {
350
342
  let openApiConfig: T;
351
343
  if (this._isConfigClass(configOrClass)) {
352
344
  openApiConfig = this.appConfig.get(configOrClass);
@@ -373,9 +365,7 @@ export class AvleonApplication {
373
365
  }
374
366
  }
375
367
 
376
-
377
368
  useDataSource<T extends DataSourceOptions>(options: ConfigInput<T>) {
378
-
379
369
  let dataSourceOptions: T;
380
370
  if (this._isConfigClass(options)) {
381
371
  dataSourceOptions = this.appConfig.get(options);
@@ -383,28 +373,19 @@ export class AvleonApplication {
383
373
  dataSourceOptions = options as T;
384
374
  }
385
375
 
386
- if (!dataSourceOptions) throw new SystemUseError("Invlaid datasource options.")
376
+ if (!dataSourceOptions)
377
+ throw new SystemUseError("Invlaid datasource options.");
387
378
 
388
379
  this.dataSourceOptions = dataSourceOptions;
389
380
  const typeorm = require("typeorm");
390
- const datasource = new typeorm.DataSource(
391
- dataSourceOptions,
392
- ) as DataSource;
381
+ const datasource = new typeorm.DataSource(dataSourceOptions) as DataSource;
393
382
 
394
383
  this.dataSource = datasource;
395
384
 
396
- Container.set<DataSource>("idatasource",
397
- datasource,
398
- );
399
-
400
-
385
+ Container.set<DataSource>("idatasource", datasource);
401
386
  }
402
387
 
403
- private _useCache(options: any) {
404
-
405
- }
406
-
407
-
388
+ private _useCache(options: any) {}
408
389
 
409
390
  useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
410
391
  for (const mclass of mclasses) {
@@ -414,12 +395,10 @@ export class AvleonApplication {
414
395
  }
415
396
  }
416
397
 
417
-
418
398
  useAuthoriztion<T extends any>(middleware: Constructor<T>) {
419
399
  this.authorizeMiddleware = middleware as any;
420
400
  }
421
401
 
422
-
423
402
  useStaticFiles(
424
403
  options: StaticFileOptions = { path: undefined, prefix: undefined },
425
404
  ) {
@@ -519,7 +498,6 @@ export class AvleonApplication {
519
498
  handler: async (req, res) => {
520
499
  let reqClone = req as IRequest;
521
500
 
522
-
523
501
  // class level authrization
524
502
  if (authClsMeata.authorize && this.authorizeMiddleware) {
525
503
  const cls = container.get(this.authorizeMiddleware) as any;
@@ -544,7 +522,11 @@ export class AvleonApplication {
544
522
 
545
523
  for (let paramMeta of allMeta.params) {
546
524
  if (paramMeta.required) {
547
- validateOrThrow({ [paramMeta.key]: args[paramMeta.index] }, { [paramMeta.key]: { type: paramMeta.dataType } }, { location: 'param' })
525
+ validateOrThrow(
526
+ { [paramMeta.key]: args[paramMeta.index] },
527
+ { [paramMeta.key]: { type: paramMeta.dataType } },
528
+ { location: "param" },
529
+ );
548
530
  }
549
531
  }
550
532
 
@@ -564,7 +546,11 @@ export class AvleonApplication {
564
546
  }
565
547
  }
566
548
  if (queryMeta.required) {
567
- validateOrThrow({ [queryMeta.key]: args[queryMeta.index] }, { [queryMeta.key]: { type: queryMeta.dataType } }, { location: 'queryparam' })
549
+ validateOrThrow(
550
+ { [queryMeta.key]: args[queryMeta.index] },
551
+ { [queryMeta.key]: { type: queryMeta.dataType } },
552
+ { location: "queryparam" },
553
+ );
568
554
  }
569
555
  }
570
556
 
@@ -622,8 +608,8 @@ export class AvleonApplication {
622
608
  meta.currentUser.forEach((user) => (args[user.index] = req.user));
623
609
  meta.headers.forEach(
624
610
  (header) =>
625
- (args[header.index] =
626
- header.key === "all" ? req.headers : req.headers[header.key]),
611
+ (args[header.index] =
612
+ header.key === "all" ? req.headers : req.headers[header.key]),
627
613
  );
628
614
 
629
615
  if (meta.file) {
@@ -703,12 +689,9 @@ export class AvleonApplication {
703
689
  process.env.TS_NODE_DEV ||
704
690
  process.env.TS_NODE_PROJECT ||
705
691
  (process as any)[Symbol.for("ts-node.register.instance")];
706
- const controllerDir = path.join(
707
- process.cwd(),
708
- this.registerControllerPath
709
- );
692
+ const controllerDir = path.join(process.cwd(), this.registerControllerPath);
710
693
 
711
- return isTsNode ? controllerDir : controllerDir.replace('src', 'dist')
694
+ return isTsNode ? controllerDir : controllerDir.replace("src", "dist");
712
695
  }
713
696
 
714
697
  private async autoControllers(controllersPath?: string) {
@@ -723,9 +706,9 @@ export class AvleonApplication {
723
706
  const module = await import(filePath);
724
707
  for (const exported of Object.values(module)) {
725
708
  if (typeof exported === "function" && isApiController(exported)) {
726
- console.log('adding', exported.name)
727
- if (!this.controllers.some(con => exported.name == con.name)) {
728
- this.controllers.push(exported)
709
+ console.log("adding", exported.name);
710
+ if (!this.controllers.some((con) => exported.name == con.name)) {
711
+ this.controllers.push(exported);
729
712
  }
730
713
 
731
714
  //this.buildController(exported);
@@ -736,22 +719,20 @@ export class AvleonApplication {
736
719
  }
737
720
 
738
721
  useControllers(controllers: Constructor[] | AutoControllerOptions) {
739
-
740
722
  if (Array.isArray(controllers)) {
741
723
  this.controllers = controllers;
742
724
 
743
- controllers.forEach(controller => {
725
+ controllers.forEach((controller) => {
744
726
  if (!this.controllers.includes(controller)) {
745
- this.controllers.push(controller)
727
+ this.controllers.push(controller);
746
728
  }
747
- })
729
+ });
748
730
  } else {
749
731
  this.registerControllerAuto = true;
750
732
  if (controllers.path) {
751
733
  this.registerControllerPath = controllers.path;
752
734
  }
753
735
  }
754
-
755
736
  }
756
737
 
757
738
  // addFeature(feature:{controllers:Function[]}){
@@ -765,7 +746,6 @@ export class AvleonApplication {
765
746
  // }
766
747
 
767
748
  private async _mapControllers() {
768
-
769
749
  if (this.controllers.length > 0) {
770
750
  for (let controller of this.controllers) {
771
751
  if (isApiController(controller)) {
@@ -782,14 +762,12 @@ export class AvleonApplication {
782
762
  // //this.autoControllers();
783
763
  // }
784
764
 
785
-
786
765
  private async mapFn(fn: Function) {
787
766
  const original = fn;
788
- fn = function () { };
767
+ fn = function () {};
789
768
  return fn;
790
769
  }
791
770
 
792
-
793
771
  private _handleError(error: any): {
794
772
  code: number;
795
773
  error: string;
@@ -877,7 +855,6 @@ export class AvleonApplication {
877
855
  return route;
878
856
  }
879
857
 
880
-
881
858
  mapGet<T extends (...args: any[]) => any>(path: string = "", fn: T) {
882
859
  return this._routeHandler(path, "GET", fn);
883
860
  }
@@ -894,10 +871,9 @@ export class AvleonApplication {
894
871
  return this._routeHandler(path, "DELETE", fn);
895
872
  }
896
873
 
897
-
898
874
  private _mapFeatures() {
899
- const features = Container.get('features');
900
- console.log('Features', features);
875
+ const features = Container.get("features");
876
+ console.log("Features", features);
901
877
  }
902
878
 
903
879
  async initializeDatabase() {
@@ -938,7 +914,10 @@ export class AvleonApplication {
938
914
  });
939
915
  this.app.setErrorHandler(async (error, req, res) => {
940
916
  const handledErr = this._handleError(error);
941
- if (error instanceof ValidationErrorException || error instanceof BadRequestException) {
917
+ if (
918
+ error instanceof ValidationErrorException ||
919
+ error instanceof BadRequestException
920
+ ) {
942
921
  return res.status(handledErr.code).send({
943
922
  code: handledErr.code,
944
923
  error: handledErr.error,
@@ -997,14 +976,14 @@ export class AvleonApplication {
997
976
  options: async (url: string, options?: InjectOptions) =>
998
977
  this.app.inject({ method: "OPTIONS", url, ...options }),
999
978
  getController: <T>(controller: Constructor<T>, deps: any[] = []) => {
1000
- const paramTypes = Reflect.getMetadata('design:paramtypes', controller) || [];
979
+ const paramTypes =
980
+ Reflect.getMetadata("design:paramtypes", controller) || [];
1001
981
 
1002
982
  deps.forEach((dep, i) => {
1003
983
  Container.set(paramTypes[i], dep);
1004
984
  });
1005
985
 
1006
986
  return Container.get(controller);
1007
-
1008
987
  },
1009
988
  };
1010
989
  } catch (error) {
@@ -1042,7 +1021,8 @@ export class AvleonTest {
1042
1021
  process.env.NODE_ENV = "test";
1043
1022
  }
1044
1023
  static getController<T>(controller: Constructor<T>, deps: any[] = []) {
1045
- const paramTypes = Reflect.getMetadata('design:paramtypes', controller) || [];
1024
+ const paramTypes =
1025
+ Reflect.getMetadata("design:paramtypes", controller) || [];
1046
1026
 
1047
1027
  deps.forEach((dep, i) => {
1048
1028
  Container.set(paramTypes[i], dep);
@@ -1055,7 +1035,6 @@ export class AvleonTest {
1055
1035
  return Container.get(service);
1056
1036
  }
1057
1037
 
1058
-
1059
1038
  static createTestApplication(options: TestAppOptions) {
1060
1039
  const app = AvleonApplication.getInternalApp({
1061
1040
  dataSourceOptions: options.dataSource ? options.dataSource : null,
@@ -1074,11 +1053,8 @@ export class AvleonTest {
1074
1053
  }
1075
1054
 
1076
1055
  export class Avleon {
1077
-
1078
1056
  static createApplication() {
1079
1057
  const app = AvleonApplication.getApp();
1080
- return app
1058
+ return app;
1081
1059
  }
1082
-
1083
-
1084
1060
  }
package/src/index.ts CHANGED
@@ -1,30 +1,30 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
- import * as sw from "./swagger-schema";
8
- export * from "./icore";
9
- export * from "./testing";
10
- export { inject, validateRequestBody,pick, exclude } from "./helpers";
11
- export * from "./decorators";
12
- export * from "./middleware";
13
- export * from "./config";
14
- export * from "./openapi";
15
- export * from "./map-types";
16
- export * from "./response";
17
- export * from "./exceptions";
18
- export * from "./validator-extend";
19
- export * from "./validation";
20
- export * from "./environment-variables";
21
- export * from "./collection";
22
- export * from "./queue";
23
- export * from "./utils/hash";
24
- export * from "./multipart";
25
- export * from "./file-storage";
26
- export * from "./logger";
27
-
28
- export const GetSchema = sw.generateSwaggerSchema;
29
-
30
- export { default as Container } from "./container";
1
+ /**
2
+ * @copyright 2024
3
+ * @author Tareq Hossain
4
+ * @email xtrinsic96@gmail.com
5
+ * @url https://github.com/xtareq
6
+ */
7
+ import * as sw from "./swagger-schema";
8
+ export * from "./icore";
9
+ export * from "./testing";
10
+ export { inject, validateRequestBody, pick, exclude } from "./helpers";
11
+ export * from "./decorators";
12
+ export * from "./middleware";
13
+ export * from "./config";
14
+ export * from "./openapi";
15
+ export * from "./map-types";
16
+ export * from "./response";
17
+ export * from "./exceptions";
18
+ export * from "./validator-extend";
19
+ export * from "./validation";
20
+ export * from "./environment-variables";
21
+ export * from "./collection";
22
+ export * from "./queue";
23
+ export * from "./utils/hash";
24
+ export * from "./multipart";
25
+ export * from "./file-storage";
26
+ export * from "./logger";
27
+
28
+ export const GetSchema = sw.generateSwaggerSchema;
29
+
30
+ export { default as Container } from "./container";
@@ -1,40 +1,32 @@
1
-
2
-
3
- interface AvleonApplication {
4
-
5
- // all use
6
- useCors: () => void;
7
- /**
8
- * function for register database
9
- * @param options datasource options. options can be plain object or avleon config class
10
- * */
11
- useDatasource: () => void;
12
- useMultipart: () => void;
13
- useOpenApi: () => void;
14
- useMiddlewares: () => void;
15
- useAuthorization: () => void;
16
- useSerialization: () => void;
17
- useControllers: () => void;
18
- useStaticFiles: () => void;
19
- /**
20
- * @experimental
21
- * use https as defalut http protocol
22
- * */
23
- useHttps: () => void;
24
-
25
-
26
- // all map
27
- mapGet: () => void;
28
- mapPost: () => void;
29
- mapPut: () => void;
30
- mapPatch: () => void;
31
- mapOptions: () => void;
32
- mapGroup: () => void;
33
- // all others
34
- // run
35
- run: () => void;
36
- }
37
-
38
-
39
-
40
-
1
+ interface AvleonApplication {
2
+ // all use
3
+ useCors: () => void;
4
+ /**
5
+ * function for register database
6
+ * @param options datasource options. options can be plain object or avleon config class
7
+ * */
8
+ useDatasource: () => void;
9
+ useMultipart: () => void;
10
+ useOpenApi: () => void;
11
+ useMiddlewares: () => void;
12
+ useAuthorization: () => void;
13
+ useSerialization: () => void;
14
+ useControllers: () => void;
15
+ useStaticFiles: () => void;
16
+ /**
17
+ * @experimental
18
+ * use https as defalut http protocol
19
+ * */
20
+ useHttps: () => void;
21
+
22
+ // all map
23
+ mapGet: () => void;
24
+ mapPost: () => void;
25
+ mapPut: () => void;
26
+ mapPatch: () => void;
27
+ mapOptions: () => void;
28
+ mapGroup: () => void;
29
+ // all others
30
+ // run
31
+ run: () => void;
32
+ }