@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/testing.ts CHANGED
@@ -1,220 +1,220 @@
1
- import "reflect-metadata";
2
- import { Container } from "typedi";
3
- import { DataSource, DataSourceOptions } from "typeorm";
4
- import { AvleonApplication } from "./icore";
5
-
6
- // Enhanced Test Utilities
7
- export class AvleonTestUtility {
8
- private static testDataSource: DataSource | null = null;
9
- private static testContainer: typeof Container;
10
-
11
- /**
12
- * Initialize test environment
13
- */
14
- static async init(options?: {
15
- dataSourceOptions?: DataSourceOptions;
16
- resetContainer?: boolean;
17
- }) {
18
- // Reset container if specified
19
- if (options?.resetContainer) {
20
- this.testContainer = Container;
21
- this.testContainer.reset();
22
- }
23
-
24
- // Initialize test database if options provided
25
- if (options?.dataSourceOptions) {
26
- this.testDataSource = new DataSource({
27
- ...options.dataSourceOptions,
28
- logging: false, // Disable logging during tests
29
- });
30
-
31
- await this.testDataSource.initialize();
32
- await this.testDataSource.synchronize(true); // Create schema
33
- }
34
-
35
- return this;
36
- }
37
-
38
- /**
39
- * Mock a dependency for testing
40
- * @param token Dependency token
41
- * @param mockImplementation Mock implementation
42
- */
43
- static mockDependency<T>(token: any, mockImplementation: T) {
44
- Container.set(token, mockImplementation);
45
- return mockImplementation;
46
- }
47
-
48
- /**
49
- * Create an isolated test instance of a class
50
- * @param ClassType Class to instantiate
51
- * @param overrides Optional property overrides
52
- */
53
- static createTestInstance<T>(
54
- ClassType: new (...args: any[]) => T,
55
- overrides: Partial<T> = {},
56
- ): T {
57
- const instance = Container.get(ClassType);
58
-
59
- // Apply overrides
60
- Object.keys(overrides).forEach((key) => {
61
- (instance as any)[key] = (overrides as any)[key];
62
- });
63
-
64
- return instance;
65
- }
66
-
67
- /**
68
- * Cleanup test environment
69
- */
70
- static async cleanup() {
71
- if (this.testDataSource) {
72
- await this.testDataSource.dropDatabase();
73
- await this.testDataSource.destroy();
74
- this.testDataSource = null;
75
- }
76
-
77
- // Reset container
78
- Container.reset();
79
- }
80
- }
81
-
82
- // Enhanced Test Builder
83
- export class AvleonTestBuilder {
84
- private controllers: any[] = [];
85
- private testOptions: any = {};
86
- private mocks: Map<any, any> = new Map();
87
-
88
- /**
89
- * Add controllers for testing
90
- * @param controllers Controllers to add
91
- */
92
- addControllers(...controllers: any[]) {
93
- this.controllers.push(...controllers);
94
- return this;
95
- }
96
-
97
- /**
98
- * Mock a dependency
99
- * @param token Dependency token
100
- * @param mockImplementation Mock implementation
101
- */
102
- mockDependency(token: any, mockImplementation: any) {
103
- this.mocks.set(token, mockImplementation);
104
- return this;
105
- }
106
-
107
- /**
108
- * Set test options
109
- * @param options Test configuration options
110
- */
111
- setOptions(options: any) {
112
- this.testOptions = { ...this.testOptions, ...options };
113
- return this;
114
- }
115
-
116
- /**
117
- * Build test application
118
- */
119
- async build() {
120
- // Apply mocks
121
- this.mocks.forEach((mock, token) => {
122
- Container.set(token, mock);
123
- });
124
-
125
- // Initialize test utility
126
- await AvleonTestUtility.init({
127
- dataSourceOptions: this.testOptions.dataSourceOptions,
128
- resetContainer: true,
129
- });
130
-
131
- // Create test application
132
- const app = AvleonApplication.getInternalApp({
133
- dataSourceOptions: this.testOptions.dataSourceOptions,
134
- });
135
-
136
- // Map controllers
137
- app.useControllers(this.controllers);
138
-
139
- // Get test application
140
- return app.getTestApp();
141
- }
142
- }
143
-
144
- // Example Usage Decorator
145
- export function UnitTest() {
146
- return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
147
- const originalMethod = descriptor.value;
148
-
149
- descriptor.value = async function (...args: any[]) {
150
- try {
151
- // Pre-test setup
152
- await AvleonTestUtility.init();
153
-
154
- // Execute test
155
- const result = await originalMethod.apply(this, args);
156
-
157
- // Post-test cleanup
158
- await AvleonTestUtility.cleanup();
159
-
160
- return result;
161
- } catch (error) {
162
- // Ensure cleanup even if test fails
163
- await AvleonTestUtility.cleanup();
164
- throw error;
165
- }
166
- };
167
-
168
- return descriptor;
169
- };
170
- }
171
- //
172
- // // Example of Unit and Integration Test
173
- // class UserServiceTest {
174
- // @UnitTest()
175
- // async testUserCreation() {
176
- // // Mock UserRepository
177
- // const mockRepo = AvleonTestUtility.mockDependency(
178
- // UserRepository,
179
- // { create: jest.fn() }
180
- // );
181
- //
182
- // // Create test instance
183
- // const userService = AvleonTestUtility.createTestInstance(UserService);
184
- //
185
- // // Perform test
186
- // const result = await userService.createUser({
187
- // name: 'Test User',
188
- // email: 'test@example.com'
189
- // });
190
- //
191
- // // Assertions
192
- // expect(mockRepo.create).toHaveBeenCalledWith(expect.any(Object));
193
- // }
194
- // }
195
- //
196
- // // Enhanced E2E Testing Example
197
- // class E2EUserControllerTest {
198
- // async testUserRegistration() {
199
- // // Build test application
200
- // const testApp = await new AvleonTestBuilder()
201
- // .addControllers(UserController)
202
- // .mockDependency(AuthService, mockAuthService)
203
- // .setOptions({
204
- // dataSourceOptions: testDatabaseConfig
205
- // })
206
- // .build();
207
- //
208
- // // Perform HTTP request
209
- // const response = await testApp.post('/users/register', {
210
- // payload: {
211
- // name: 'John Doe',
212
- // email: 'john@example.com'
213
- // }
214
- // });
215
- //
216
- // // Assertions
217
- // expect(response.statusCode).toBe(201);
218
- // expect(response.json()).toHaveProperty('userId');
219
- // }
220
- // }
1
+ import "reflect-metadata";
2
+ import { Container } from "typedi";
3
+ import { DataSource, DataSourceOptions } from "typeorm";
4
+ import { AvleonApplication } from "./icore";
5
+
6
+ // Enhanced Test Utilities
7
+ export class AvleonTestUtility {
8
+ private static testDataSource: DataSource | null = null;
9
+ private static testContainer: typeof Container;
10
+
11
+ /**
12
+ * Initialize test environment
13
+ */
14
+ static async init(options?: {
15
+ dataSourceOptions?: DataSourceOptions;
16
+ resetContainer?: boolean;
17
+ }) {
18
+ // Reset container if specified
19
+ if (options?.resetContainer) {
20
+ this.testContainer = Container;
21
+ this.testContainer.reset();
22
+ }
23
+
24
+ // Initialize test database if options provided
25
+ if (options?.dataSourceOptions) {
26
+ this.testDataSource = new DataSource({
27
+ ...options.dataSourceOptions,
28
+ logging: false, // Disable logging during tests
29
+ });
30
+
31
+ await this.testDataSource.initialize();
32
+ await this.testDataSource.synchronize(true); // Create schema
33
+ }
34
+
35
+ return this;
36
+ }
37
+
38
+ /**
39
+ * Mock a dependency for testing
40
+ * @param token Dependency token
41
+ * @param mockImplementation Mock implementation
42
+ */
43
+ static mockDependency<T>(token: any, mockImplementation: T) {
44
+ Container.set(token, mockImplementation);
45
+ return mockImplementation;
46
+ }
47
+
48
+ /**
49
+ * Create an isolated test instance of a class
50
+ * @param ClassType Class to instantiate
51
+ * @param overrides Optional property overrides
52
+ */
53
+ static createTestInstance<T>(
54
+ ClassType: new (...args: any[]) => T,
55
+ overrides: Partial<T> = {},
56
+ ): T {
57
+ const instance = Container.get(ClassType);
58
+
59
+ // Apply overrides
60
+ Object.keys(overrides).forEach((key) => {
61
+ (instance as any)[key] = (overrides as any)[key];
62
+ });
63
+
64
+ return instance;
65
+ }
66
+
67
+ /**
68
+ * Cleanup test environment
69
+ */
70
+ static async cleanup() {
71
+ if (this.testDataSource) {
72
+ await this.testDataSource.dropDatabase();
73
+ await this.testDataSource.destroy();
74
+ this.testDataSource = null;
75
+ }
76
+
77
+ // Reset container
78
+ Container.reset();
79
+ }
80
+ }
81
+
82
+ // Enhanced Test Builder
83
+ export class AvleonTestBuilder {
84
+ private controllers: any[] = [];
85
+ private testOptions: any = {};
86
+ private mocks: Map<any, any> = new Map();
87
+
88
+ /**
89
+ * Add controllers for testing
90
+ * @param controllers Controllers to add
91
+ */
92
+ addControllers(...controllers: any[]) {
93
+ this.controllers.push(...controllers);
94
+ return this;
95
+ }
96
+
97
+ /**
98
+ * Mock a dependency
99
+ * @param token Dependency token
100
+ * @param mockImplementation Mock implementation
101
+ */
102
+ mockDependency(token: any, mockImplementation: any) {
103
+ this.mocks.set(token, mockImplementation);
104
+ return this;
105
+ }
106
+
107
+ /**
108
+ * Set test options
109
+ * @param options Test configuration options
110
+ */
111
+ setOptions(options: any) {
112
+ this.testOptions = { ...this.testOptions, ...options };
113
+ return this;
114
+ }
115
+
116
+ /**
117
+ * Build test application
118
+ */
119
+ async build() {
120
+ // Apply mocks
121
+ this.mocks.forEach((mock, token) => {
122
+ Container.set(token, mock);
123
+ });
124
+
125
+ // Initialize test utility
126
+ await AvleonTestUtility.init({
127
+ dataSourceOptions: this.testOptions.dataSourceOptions,
128
+ resetContainer: true,
129
+ });
130
+
131
+ // Create test application
132
+ const app = AvleonApplication.getInternalApp({
133
+ dataSourceOptions: this.testOptions.dataSourceOptions,
134
+ });
135
+
136
+ // Map controllers
137
+ app.useControllers(this.controllers);
138
+
139
+ // Get test application
140
+ return app.getTestApp();
141
+ }
142
+ }
143
+
144
+ // Example Usage Decorator
145
+ export function UnitTest() {
146
+ return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
147
+ const originalMethod = descriptor.value;
148
+
149
+ descriptor.value = async function (...args: any[]) {
150
+ try {
151
+ // Pre-test setup
152
+ await AvleonTestUtility.init();
153
+
154
+ // Execute test
155
+ const result = await originalMethod.apply(this, args);
156
+
157
+ // Post-test cleanup
158
+ await AvleonTestUtility.cleanup();
159
+
160
+ return result;
161
+ } catch (error) {
162
+ // Ensure cleanup even if test fails
163
+ await AvleonTestUtility.cleanup();
164
+ throw error;
165
+ }
166
+ };
167
+
168
+ return descriptor;
169
+ };
170
+ }
171
+ //
172
+ // // Example of Unit and Integration Test
173
+ // class UserServiceTest {
174
+ // @UnitTest()
175
+ // async testUserCreation() {
176
+ // // Mock UserRepository
177
+ // const mockRepo = AvleonTestUtility.mockDependency(
178
+ // UserRepository,
179
+ // { create: jest.fn() }
180
+ // );
181
+ //
182
+ // // Create test instance
183
+ // const userService = AvleonTestUtility.createTestInstance(UserService);
184
+ //
185
+ // // Perform test
186
+ // const result = await userService.createUser({
187
+ // name: 'Test User',
188
+ // email: 'test@example.com'
189
+ // });
190
+ //
191
+ // // Assertions
192
+ // expect(mockRepo.create).toHaveBeenCalledWith(expect.any(Object));
193
+ // }
194
+ // }
195
+ //
196
+ // // Enhanced E2E Testing Example
197
+ // class E2EUserControllerTest {
198
+ // async testUserRegistration() {
199
+ // // Build test application
200
+ // const testApp = await new AvleonTestBuilder()
201
+ // .addControllers(UserController)
202
+ // .mockDependency(AuthService, mockAuthService)
203
+ // .setOptions({
204
+ // dataSourceOptions: testDatabaseConfig
205
+ // })
206
+ // .build();
207
+ //
208
+ // // Perform HTTP request
209
+ // const response = await testApp.post('/users/register', {
210
+ // payload: {
211
+ // name: 'John Doe',
212
+ // email: 'john@example.com'
213
+ // }
214
+ // });
215
+ //
216
+ // // Assertions
217
+ // expect(response.statusCode).toBe(201);
218
+ // expect(response.json()).toHaveProperty('userId');
219
+ // }
220
+ // }
@@ -1,19 +1,18 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
-
8
-
9
- import { IApplication } from "./application.interface";
10
-
11
- export interface IAppBuilder {
12
- createBuilder(): IAppBuilder;
13
-
14
- /**
15
- * @description will create a application instace
16
- * @returns IApplication
17
- */
18
- builder: () => IApplication;
19
- }
1
+ /**
2
+ * @copyright 2024
3
+ * @author Tareq Hossain
4
+ * @email xtrinsic96@gmail.com
5
+ * @url https://github.com/xtareq
6
+ */
7
+
8
+ import { IApplication } from "./application.interface";
9
+
10
+ export interface IAppBuilder {
11
+ createBuilder(): IAppBuilder;
12
+
13
+ /**
14
+ * @description will create a application instace
15
+ * @returns IApplication
16
+ */
17
+ builder: () => IApplication;
18
+ }
@@ -1,9 +1,7 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
- export interface IApplication{
8
-
9
- }
1
+ /**
2
+ * @copyright 2024
3
+ * @author Tareq Hossain
4
+ * @email xtrinsic96@gmail.com
5
+ * @url https://github.com/xtareq
6
+ */
7
+ export interface IApplication {}
package/src/utils/hash.ts CHANGED
@@ -1,5 +1,8 @@
1
- import bcrypt from 'bcryptjs';
2
- export const hashPasswordSync = (password: string) => bcrypt.hashSync(password,12);
3
- export const matchPasswordSync = (password: string, hash: string) => bcrypt.compareSync(password, hash);
4
- export const hashPassword = (password: string) => bcrypt.hash(password,12);
5
- export const matchPassword = (password: string, hash: string) => bcrypt.compare(password, hash);
1
+ import bcrypt from "bcryptjs";
2
+ export const hashPasswordSync = (password: string) =>
3
+ bcrypt.hashSync(password, 12);
4
+ export const matchPasswordSync = (password: string, hash: string) =>
5
+ bcrypt.compareSync(password, hash);
6
+ export const hashPassword = (password: string) => bcrypt.hash(password, 12);
7
+ export const matchPassword = (password: string, hash: string) =>
8
+ bcrypt.compare(password, hash);
@@ -1,2 +1,2 @@
1
- export * from './hash';
2
- export * from './optional-require';
1
+ export * from "./hash";
2
+ export * from "./optional-require";
@@ -1,50 +1,50 @@
1
-
2
- export function optionalRequire<T = any>(
3
- moduleName: string,
4
- options: {
5
- failOnMissing?: boolean;
6
- customMessage?: string;
7
- } = {},
8
- ): T | undefined {
9
- try {
10
- // eslint-disable-next-line @typescript-eslint/no-var-requires
11
- return require(moduleName);
12
- } catch (err: any) {
13
- if (err.code === "MODULE_NOT_FOUND" && err.message.includes(moduleName)) {
14
- if (options.failOnMissing) {
15
- throw new Error(
16
- options.customMessage ||
17
- `Optional dependency "${moduleName}" is not installed.\nInstall it with:\n\n npm install ${moduleName}`
18
- );
19
- }
20
- return undefined;
21
- }
22
- throw err;
23
- }
24
- }
25
-
26
- export async function optionalImport<T = any>(
27
- moduleName: string,
28
- options: {
29
- failOnMissing?: boolean;
30
- customMessage?: string;
31
- } = {},
32
- ): Promise<T | undefined> {
33
- try {
34
- const mod = await import(moduleName);
35
- return mod as T;
36
- } catch (err: any) {
37
- if ((err.code === "ERR_MODULE_NOT_FOUND" || err.code === "MODULE_NOT_FOUND") &&
38
- err.message.includes(moduleName)) {
39
- if (options.failOnMissing) {
40
- throw new Error(
41
- options.customMessage ||
42
- `Optional dependency "${moduleName}" is not installed.\nInstall it with:\n\n npm install ${moduleName}`
43
- );
44
- }
45
- return undefined;
46
- }
47
- throw err;
48
- }
49
- }
50
-
1
+ export function optionalRequire<T = any>(
2
+ moduleName: string,
3
+ options: {
4
+ failOnMissing?: boolean;
5
+ customMessage?: string;
6
+ } = {},
7
+ ): T | undefined {
8
+ try {
9
+ return require(moduleName);
10
+ } catch (err: any) {
11
+ if (err.code === "MODULE_NOT_FOUND" && err.message.includes(moduleName)) {
12
+ if (options.failOnMissing) {
13
+ throw new Error(
14
+ options.customMessage ||
15
+ `Optional dependency "${moduleName}" is not installed.\nInstall it with:\n\n npm install ${moduleName}`,
16
+ );
17
+ }
18
+ return undefined;
19
+ }
20
+ throw err;
21
+ }
22
+ }
23
+
24
+ export async function optionalImport<T = any>(
25
+ moduleName: string,
26
+ options: {
27
+ failOnMissing?: boolean;
28
+ customMessage?: string;
29
+ } = {},
30
+ ): Promise<T | undefined> {
31
+ try {
32
+ const mod = await import(moduleName);
33
+ return mod as T;
34
+ } catch (err: any) {
35
+ if (
36
+ (err.code === "ERR_MODULE_NOT_FOUND" ||
37
+ err.code === "MODULE_NOT_FOUND") &&
38
+ err.message.includes(moduleName)
39
+ ) {
40
+ if (options.failOnMissing) {
41
+ throw new Error(
42
+ options.customMessage ||
43
+ `Optional dependency "${moduleName}" is not installed.\nInstall it with:\n\n npm install ${moduleName}`,
44
+ );
45
+ }
46
+ return undefined;
47
+ }
48
+ throw err;
49
+ }
50
+ }