@avleon/core 0.0.27 → 0.0.29

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 (77) hide show
  1. package/README.md +601 -561
  2. package/dist/application.js +1 -1
  3. package/dist/cache.d.ts +1 -1
  4. package/dist/cache.js +2 -2
  5. package/dist/collection.d.ts +25 -32
  6. package/dist/collection.js +50 -6
  7. package/dist/collection.test.d.ts +1 -0
  8. package/dist/collection.test.js +59 -0
  9. package/dist/config.d.ts +2 -0
  10. package/dist/config.js +30 -5
  11. package/dist/config.test.d.ts +1 -0
  12. package/dist/config.test.js +40 -0
  13. package/dist/controller.js +2 -2
  14. package/dist/environment-variables.js +42 -5
  15. package/dist/event-dispatcher.d.ts +23 -0
  16. package/dist/event-dispatcher.js +102 -0
  17. package/dist/event-subscriber.d.ts +15 -0
  18. package/dist/event-subscriber.js +96 -0
  19. package/dist/exceptions/http-exceptions.js +1 -1
  20. package/dist/exceptions/index.d.ts +1 -1
  21. package/dist/exceptions/system-exception.js +3 -1
  22. package/dist/file-storage.js +1 -1
  23. package/dist/helpers.js +1 -1
  24. package/dist/icore.d.ts +5 -0
  25. package/dist/icore.js +53 -18
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.js +6 -1
  28. package/dist/utils/index.d.ts +2 -2
  29. package/dist/utils/optional-require.js +2 -2
  30. package/dist/validation.d.ts +1 -1
  31. package/dist/websocket.d.ts +7 -0
  32. package/dist/websocket.js +20 -0
  33. package/dist/websocket.test.d.ts +0 -0
  34. package/dist/websocket.test.js +1 -0
  35. package/package.json +37 -6
  36. package/src/application.ts +104 -125
  37. package/src/authentication.ts +16 -16
  38. package/src/cache.ts +91 -91
  39. package/src/collection.test.ts +71 -0
  40. package/src/collection.ts +344 -254
  41. package/src/config.test.ts +35 -0
  42. package/src/config.ts +85 -42
  43. package/src/constants.ts +1 -1
  44. package/src/container.ts +54 -54
  45. package/src/controller.ts +125 -127
  46. package/src/decorators.ts +27 -27
  47. package/src/environment-variables.ts +53 -46
  48. package/src/event-dispatcher.ts +100 -0
  49. package/src/event-subscriber.ts +79 -0
  50. package/src/exceptions/http-exceptions.ts +86 -86
  51. package/src/exceptions/index.ts +1 -1
  52. package/src/exceptions/system-exception.ts +35 -34
  53. package/src/file-storage.ts +206 -206
  54. package/src/helpers.ts +324 -328
  55. package/src/icore.ts +1106 -1084
  56. package/src/index.ts +32 -30
  57. package/src/interfaces/avleon-application.ts +32 -40
  58. package/src/logger.ts +72 -72
  59. package/src/map-types.ts +159 -159
  60. package/src/middleware.ts +121 -98
  61. package/src/multipart.ts +116 -116
  62. package/src/openapi.ts +372 -372
  63. package/src/params.ts +111 -111
  64. package/src/queue.ts +126 -126
  65. package/src/response.ts +74 -74
  66. package/src/results.ts +30 -30
  67. package/src/route-methods.ts +186 -186
  68. package/src/swagger-schema.ts +213 -213
  69. package/src/testing.ts +220 -220
  70. package/src/types/app-builder.interface.ts +18 -19
  71. package/src/types/application.interface.ts +7 -9
  72. package/src/utils/hash.ts +8 -5
  73. package/src/utils/index.ts +2 -2
  74. package/src/utils/optional-require.ts +50 -50
  75. package/src/validation.ts +160 -156
  76. package/src/validator-extend.ts +25 -25
  77. package/src/websocket.ts +47 -0
package/src/middleware.ts CHANGED
@@ -1,98 +1,121 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
- import { Service } from "typedi";
8
- import { IRequest, IResponse } from "./icore";
9
- import { HttpExceptionTypes as HttpException, UnauthorizedException } from "./exceptions";
10
- import Container, { AUTHORIZATION_META_KEY } from "./container";
11
-
12
- export abstract class AppMiddleware {
13
- abstract invoke(req: IRequest, res?: IResponse): Promise<IRequest|HttpException>;
14
- }
15
- export type AuthHandler = (req: IRequest, roles?: string[]) => Promise<IRequest | HttpException>;
16
-
17
-
18
-
19
- export type Constructor<T> = { new(...args: any[]): T };
20
-
21
- export abstract class AuthorizeMiddleware {
22
- abstract authorize(roles: string[]): (req: IRequest, res?: IResponse) => IRequest | Promise<IRequest>;
23
-
24
- }
25
-
26
-
27
- export type AuthReturnTypes = IRequest | Promise<IRequest>
28
-
29
- interface AuthorizeClass {
30
- authorize(req: IRequest, options?:any): AuthReturnTypes;
31
- }
32
-
33
- export function Authorize(target: { new (...args: any[]): AuthorizeClass }) {
34
- if (typeof target.prototype.authorize !== "function") {
35
- throw new Error(
36
- `Class "${target.name}" must implement an "authorize" method.`,
37
- );
38
- }
39
- Service()(target);
40
- }
41
-
42
-
43
- // export function Authorized(target: Function): void;
44
- export function Authorized(): ClassDecorator & MethodDecorator;
45
- export function Authorized(options?: any): ClassDecorator & MethodDecorator;
46
- export function Authorized(options: any = {}): MethodDecorator | ClassDecorator {
47
- return function (target: any, propertyKey?: string | symbol, descriptor?: PropertyDescriptor) {
48
- if (propertyKey && descriptor) {
49
- Reflect.defineMetadata(AUTHORIZATION_META_KEY, { authorize: true, options}, target.constructor, propertyKey);
50
- } else {
51
- Reflect.defineMetadata(AUTHORIZATION_META_KEY, { authorize: true, options}, target);
52
- }
53
- };
54
- }
55
-
56
-
57
- export function Middleware(target: Constructor<AppMiddleware>) {
58
- if (typeof target.prototype.invoke !== "function") {
59
- throw new Error(
60
- `Class "${target.name}" must implement an "invoke" method.`,
61
- );
62
- }
63
-
64
- Service()(target);
65
- }
66
-
67
-
68
- export function UseMiddleware<T extends AppMiddleware | (new (...args: any[]) => AppMiddleware)>(
69
- options: T | T[],
70
- ): MethodDecorator & ClassDecorator {
71
- return function (
72
- target: Object | Function,
73
- propertyKey?: string | symbol,
74
- descriptor?: PropertyDescriptor,
75
- ) {
76
- const normalizeMiddleware = (middleware: any) =>
77
- typeof middleware === "function" ? new middleware() : middleware;
78
- const middlewareList = (Array.isArray(options) ? options : [options]).map(normalizeMiddleware);
79
- if (typeof target === "function" && !propertyKey) {
80
- const existingMiddlewares =
81
- Reflect.getMetadata("controller:middleware", target) || [];
82
- Reflect.defineMetadata(
83
- "controller:middleware",
84
- [...existingMiddlewares, ...middlewareList],
85
- target
86
- );
87
- } else if (descriptor) {
88
- const existingMiddlewares =
89
- Reflect.getMetadata("route:middleware", target, propertyKey!) || [];
90
- Reflect.defineMetadata(
91
- "route:middleware",
92
- [...existingMiddlewares, ...middlewareList],
93
- target,
94
- propertyKey!
95
- );
96
- }
97
- };
98
- }
1
+ /**
2
+ * @copyright 2024
3
+ * @author Tareq Hossain
4
+ * @email xtrinsic96@gmail.com
5
+ * @url https://github.com/xtareq
6
+ */
7
+ import { Service } from "typedi";
8
+ import { IRequest, IResponse } from "./icore";
9
+ import {
10
+ HttpExceptionTypes as HttpException,
11
+ UnauthorizedException,
12
+ } from "./exceptions";
13
+ import Container, { AUTHORIZATION_META_KEY } from "./container";
14
+
15
+ export abstract class AvleonMiddleware {
16
+ abstract invoke(
17
+ req: IRequest,
18
+ res?: IResponse,
19
+ ): Promise<IRequest | HttpException>;
20
+ }
21
+ export type AuthHandler = (
22
+ req: IRequest,
23
+ roles?: string[],
24
+ ) => Promise<IRequest | HttpException>;
25
+
26
+ export type Constructor<T> = { new (...args: any[]): T };
27
+
28
+ export abstract class AuthorizeMiddleware {
29
+ abstract authorize(
30
+ roles: string[],
31
+ ): (req: IRequest, res?: IResponse) => IRequest | Promise<IRequest>;
32
+ }
33
+
34
+ export type AuthReturnTypes = IRequest | Promise<IRequest>;
35
+
36
+ interface AuthorizeClass {
37
+ authorize(req: IRequest, options?: any): AuthReturnTypes;
38
+ }
39
+
40
+ export function AppAuthorization(target: {
41
+ new (...args: any[]): AuthorizeClass;
42
+ }) {
43
+ if (typeof target.prototype.authorize !== "function") {
44
+ throw new Error(
45
+ `Class "${target.name}" must implement an "authorize" method.`,
46
+ );
47
+ }
48
+ Service()(target);
49
+ }
50
+
51
+ // export function Authorized(target: Function): void;
52
+ export function Authorized(): ClassDecorator & MethodDecorator;
53
+ export function Authorized(options?: any): ClassDecorator & MethodDecorator;
54
+ export function Authorized(
55
+ options: any = {},
56
+ ): MethodDecorator | ClassDecorator {
57
+ return function (
58
+ target: any,
59
+ propertyKey?: string | symbol,
60
+ descriptor?: PropertyDescriptor,
61
+ ) {
62
+ if (propertyKey && descriptor) {
63
+ Reflect.defineMetadata(
64
+ AUTHORIZATION_META_KEY,
65
+ { authorize: true, options },
66
+ target.constructor,
67
+ propertyKey,
68
+ );
69
+ } else {
70
+ Reflect.defineMetadata(
71
+ AUTHORIZATION_META_KEY,
72
+ { authorize: true, options },
73
+ target,
74
+ );
75
+ }
76
+ };
77
+ }
78
+
79
+ export function AppMiddleware(target: Constructor<AvleonMiddleware>) {
80
+ if (typeof target.prototype.invoke !== "function") {
81
+ throw new Error(
82
+ `Class "${target.name}" must implement an "invoke" method.`,
83
+ );
84
+ }
85
+
86
+ Service()(target);
87
+ }
88
+
89
+ export function UseMiddleware<
90
+ T extends AvleonMiddleware | (new (...args: any[]) => AvleonMiddleware),
91
+ >(options: T | T[]): MethodDecorator & ClassDecorator {
92
+ return function (
93
+ target: Object | Function,
94
+ propertyKey?: string | symbol,
95
+ descriptor?: PropertyDescriptor,
96
+ ) {
97
+ const normalizeMiddleware = (middleware: any) =>
98
+ typeof middleware === "function" ? new middleware() : middleware;
99
+ const middlewareList = (Array.isArray(options) ? options : [options]).map(
100
+ normalizeMiddleware,
101
+ );
102
+ if (typeof target === "function" && !propertyKey) {
103
+ const existingMiddlewares =
104
+ Reflect.getMetadata("controller:middleware", target) || [];
105
+ Reflect.defineMetadata(
106
+ "controller:middleware",
107
+ [...existingMiddlewares, ...middlewareList],
108
+ target,
109
+ );
110
+ } else if (descriptor) {
111
+ const existingMiddlewares =
112
+ Reflect.getMetadata("route:middleware", target, propertyKey!) || [];
113
+ Reflect.defineMetadata(
114
+ "route:middleware",
115
+ [...existingMiddlewares, ...middlewareList],
116
+ target,
117
+ propertyKey!,
118
+ );
119
+ }
120
+ };
121
+ }
package/src/multipart.ts CHANGED
@@ -1,116 +1,116 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
-
8
- import {
9
- MultipartFile as FsM,
10
- MultipartValue,
11
- SavedMultipartFile,
12
- } from "@fastify/multipart";
13
- import { IRequest } from "./icore";
14
- import fs from "fs";
15
- import path from "path";
16
- import { pipeline } from "stream/promises";
17
- import { InternalErrorException } from "./exceptions";
18
- import { REQUEST_BODY_FILE_KEY, REQUEST_BODY_FILES_KEY } from "./container";
19
-
20
- export function UploadFile(fieldName: string) {
21
- return function (
22
- target: any,
23
- propertyKey: string | symbol,
24
- parameterIndex: number
25
- ) {
26
- if (!Reflect.hasMetadata(REQUEST_BODY_FILE_KEY, target, propertyKey)) {
27
- Reflect.defineMetadata(REQUEST_BODY_FILE_KEY, [], target, propertyKey);
28
- }
29
- const existingMetadata = Reflect.getMetadata(
30
- REQUEST_BODY_FILE_KEY,
31
- target,
32
- propertyKey
33
- ) as {
34
- fieldName: string;
35
- index: number;
36
- }[];
37
- existingMetadata.push({ fieldName, index: parameterIndex });
38
- Reflect.defineMetadata(
39
- REQUEST_BODY_FILE_KEY,
40
- existingMetadata,
41
- target,
42
- propertyKey
43
- );
44
- };
45
- }
46
-
47
- export function UploadFiles(fieldName?: string) {
48
- return function (
49
- target: any,
50
- propertyKey: string | symbol,
51
- parameterIndex: number
52
- ) {
53
- if (!Reflect.hasMetadata(REQUEST_BODY_FILES_KEY, target, propertyKey)) {
54
- Reflect.defineMetadata(REQUEST_BODY_FILES_KEY, [], target, propertyKey);
55
- }
56
- const existingMetadata = Reflect.getMetadata(
57
- REQUEST_BODY_FILES_KEY,
58
- target,
59
- propertyKey
60
- ) as {
61
- fieldName: string;
62
- index: number;
63
- }[];
64
- existingMetadata.push({
65
- fieldName: fieldName ? fieldName : "all",
66
- index: parameterIndex,
67
- });
68
- Reflect.defineMetadata(
69
- REQUEST_BODY_FILES_KEY,
70
- existingMetadata,
71
- target,
72
- propertyKey
73
- );
74
- };
75
- }
76
-
77
- type Foptions = {
78
- saveAs?: string;
79
- dest?: true;
80
- };
81
-
82
- export type MultipartFile = FsM | SavedMultipartFile;
83
- export function UploadFileFromRequest(req: IRequest, options?: Foptions) {
84
- return Promise.resolve(
85
- req.file().then(async (f) => {
86
- if (f && f.file) {
87
- let fname = f.filename;
88
- if (options) {
89
- if (options.dest) {
90
- fname = options.saveAs
91
- ? options.dest + "/" + options.saveAs
92
- : options.dest + "/" + f.filename;
93
- } else {
94
- fname = path.join(
95
- process.cwd(),
96
- `public/${options.saveAs ? options.saveAs : f.filename}`
97
- );
98
- }
99
- } else {
100
- fname = path.join(process.cwd(), `public/${f.filename}`);
101
- }
102
-
103
- if (fs.existsSync(fname)) {
104
- throw new InternalErrorException("File already exists.");
105
- }
106
-
107
- await pipeline(f.file!, fs.createWriteStream(fname));
108
-
109
- return {
110
- ...f,
111
- filename: options?.saveAs ? options.saveAs : f.filename,
112
- } as MultipartFile;
113
- }
114
- })
115
- );
116
- }
1
+ /**
2
+ * @copyright 2024
3
+ * @author Tareq Hossain
4
+ * @email xtrinsic96@gmail.com
5
+ * @url https://github.com/xtareq
6
+ */
7
+
8
+ import {
9
+ MultipartFile as FsM,
10
+ MultipartValue,
11
+ SavedMultipartFile,
12
+ } from "@fastify/multipart";
13
+ import { IRequest } from "./icore";
14
+ import fs from "fs";
15
+ import path from "path";
16
+ import { pipeline } from "stream/promises";
17
+ import { InternalErrorException } from "./exceptions";
18
+ import { REQUEST_BODY_FILE_KEY, REQUEST_BODY_FILES_KEY } from "./container";
19
+
20
+ export function UploadFile(fieldName: string) {
21
+ return function (
22
+ target: any,
23
+ propertyKey: string | symbol,
24
+ parameterIndex: number,
25
+ ) {
26
+ if (!Reflect.hasMetadata(REQUEST_BODY_FILE_KEY, target, propertyKey)) {
27
+ Reflect.defineMetadata(REQUEST_BODY_FILE_KEY, [], target, propertyKey);
28
+ }
29
+ const existingMetadata = Reflect.getMetadata(
30
+ REQUEST_BODY_FILE_KEY,
31
+ target,
32
+ propertyKey,
33
+ ) as {
34
+ fieldName: string;
35
+ index: number;
36
+ }[];
37
+ existingMetadata.push({ fieldName, index: parameterIndex });
38
+ Reflect.defineMetadata(
39
+ REQUEST_BODY_FILE_KEY,
40
+ existingMetadata,
41
+ target,
42
+ propertyKey,
43
+ );
44
+ };
45
+ }
46
+
47
+ export function UploadFiles(fieldName?: string) {
48
+ return function (
49
+ target: any,
50
+ propertyKey: string | symbol,
51
+ parameterIndex: number,
52
+ ) {
53
+ if (!Reflect.hasMetadata(REQUEST_BODY_FILES_KEY, target, propertyKey)) {
54
+ Reflect.defineMetadata(REQUEST_BODY_FILES_KEY, [], target, propertyKey);
55
+ }
56
+ const existingMetadata = Reflect.getMetadata(
57
+ REQUEST_BODY_FILES_KEY,
58
+ target,
59
+ propertyKey,
60
+ ) as {
61
+ fieldName: string;
62
+ index: number;
63
+ }[];
64
+ existingMetadata.push({
65
+ fieldName: fieldName ? fieldName : "all",
66
+ index: parameterIndex,
67
+ });
68
+ Reflect.defineMetadata(
69
+ REQUEST_BODY_FILES_KEY,
70
+ existingMetadata,
71
+ target,
72
+ propertyKey,
73
+ );
74
+ };
75
+ }
76
+
77
+ type Foptions = {
78
+ saveAs?: string;
79
+ dest?: true;
80
+ };
81
+
82
+ export type MultipartFile = FsM | SavedMultipartFile;
83
+ export function UploadFileFromRequest(req: IRequest, options?: Foptions) {
84
+ return Promise.resolve(
85
+ req.file().then(async (f) => {
86
+ if (f && f.file) {
87
+ let fname = f.filename;
88
+ if (options) {
89
+ if (options.dest) {
90
+ fname = options.saveAs
91
+ ? options.dest + "/" + options.saveAs
92
+ : options.dest + "/" + f.filename;
93
+ } else {
94
+ fname = path.join(
95
+ process.cwd(),
96
+ `public/${options.saveAs ? options.saveAs : f.filename}`,
97
+ );
98
+ }
99
+ } else {
100
+ fname = path.join(process.cwd(), `public/${f.filename}`);
101
+ }
102
+
103
+ if (fs.existsSync(fname)) {
104
+ throw new InternalErrorException("File already exists.");
105
+ }
106
+
107
+ await pipeline(f.file!, fs.createWriteStream(fname));
108
+
109
+ return {
110
+ ...f,
111
+ filename: options?.saveAs ? options.saveAs : f.filename,
112
+ } as MultipartFile;
113
+ }
114
+ }),
115
+ );
116
+ }