@avleon/core 0.0.29 → 0.0.31

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 (43) hide show
  1. package/package.json +2 -4
  2. package/src/application.ts +0 -104
  3. package/src/authentication.ts +0 -16
  4. package/src/cache.ts +0 -91
  5. package/src/collection.test.ts +0 -71
  6. package/src/collection.ts +0 -344
  7. package/src/config.test.ts +0 -35
  8. package/src/config.ts +0 -85
  9. package/src/constants.ts +0 -1
  10. package/src/container.ts +0 -54
  11. package/src/controller.ts +0 -125
  12. package/src/decorators.ts +0 -27
  13. package/src/environment-variables.ts +0 -53
  14. package/src/event-dispatcher.ts +0 -100
  15. package/src/event-subscriber.ts +0 -79
  16. package/src/exceptions/http-exceptions.ts +0 -86
  17. package/src/exceptions/index.ts +0 -1
  18. package/src/exceptions/system-exception.ts +0 -35
  19. package/src/file-storage.ts +0 -206
  20. package/src/helpers.ts +0 -324
  21. package/src/icore.ts +0 -1106
  22. package/src/index.ts +0 -32
  23. package/src/interfaces/avleon-application.ts +0 -32
  24. package/src/logger.ts +0 -72
  25. package/src/map-types.ts +0 -159
  26. package/src/middleware.ts +0 -121
  27. package/src/multipart.ts +0 -116
  28. package/src/openapi.ts +0 -372
  29. package/src/params.ts +0 -111
  30. package/src/queue.ts +0 -126
  31. package/src/response.ts +0 -74
  32. package/src/results.ts +0 -30
  33. package/src/route-methods.ts +0 -186
  34. package/src/swagger-schema.ts +0 -213
  35. package/src/testing.ts +0 -220
  36. package/src/types/app-builder.interface.ts +0 -18
  37. package/src/types/application.interface.ts +0 -7
  38. package/src/utils/hash.ts +0 -8
  39. package/src/utils/index.ts +0 -2
  40. package/src/utils/optional-require.ts +0 -50
  41. package/src/validation.ts +0 -160
  42. package/src/validator-extend.ts +0 -25
  43. package/src/websocket.ts +0 -47
@@ -1,186 +0,0 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
-
8
- import { CONTROLLER_META_KEY, ROUTE_META_KEY } from "./container";
9
- import { OpenApiOptions } from "./openapi";
10
- import { HttpResponse } from "./response";
11
- import { Results } from "./results";
12
- export type RouteMethods =
13
- | "GET"
14
- | "POST"
15
- | "PUT"
16
- | "PATCH"
17
- | "DELETE"
18
- | "OPTIONS"
19
- | "ALL";
20
-
21
- const schema: OpenApiOptions = {
22
- tags: ["hello"],
23
- };
24
-
25
- /**
26
- * Options for defining a route's method and metadata.
27
- */
28
- export type RouteMethodOptions = {
29
- /**
30
- * HTTP method for the route (e.g., GET, POST, PUT, DELETE).
31
- */
32
- method?: RouteMethods;
33
-
34
- /**
35
- * The path or endpoint for the route (e.g., "/users/:id").
36
- */
37
- path?: string;
38
-
39
- /**
40
- * OpenAPI metadata for the route, including summary and description.
41
- */
42
- openapi?: OpenApiOptions;
43
-
44
- /**
45
- * Name of the route.
46
- *
47
- * @description If Swagger is enabled in the project, this will appear as a tag in the generated documentation.
48
- */
49
- name?: string;
50
- };
51
-
52
- // Overloads
53
-
54
- // Implementation
55
- export function createRouteDecorator(
56
- method: RouteMethods = "GET",
57
- ): (
58
- pathOrOptions: string | RouteMethodOptions,
59
- maybeOptions?: RouteMethodOptions,
60
- ) => MethodDecorator {
61
- return function (
62
- pathOrOptions: string | RouteMethodOptions,
63
- maybeOptions?: RouteMethodOptions,
64
- ): MethodDecorator {
65
- return function (
66
- target,
67
- propertyKey: string | symbol,
68
- descriptor: PropertyDescriptor,
69
- ) {
70
- let path = "/";
71
- let options: RouteMethodOptions = {};
72
-
73
- if (typeof pathOrOptions === "string") {
74
- path = pathOrOptions;
75
- options = maybeOptions || {};
76
- } else if (typeof pathOrOptions === "object") {
77
- options = pathOrOptions;
78
- path = options.name || "/";
79
- }
80
-
81
- // Define metadata
82
- Reflect.defineMetadata("route:path", path, target, propertyKey);
83
- Reflect.defineMetadata(
84
- "route:method",
85
- method || "GET",
86
- target,
87
- propertyKey,
88
- );
89
- Reflect.getMetadata(CONTROLLER_META_KEY, target.constructor);
90
- Reflect.defineMetadata(
91
- ROUTE_META_KEY,
92
- { ...options, method, path, controller: target.constructor.name },
93
- target,
94
- propertyKey,
95
- );
96
-
97
- if (options) {
98
- Reflect.defineMetadata("route:options", options, target, propertyKey);
99
- }
100
- };
101
- };
102
- }
103
-
104
- // Usage Example
105
- /**
106
- * @description HTTP Get method
107
- * @param {string} path
108
- */
109
- export function Get(path?: string): MethodDecorator;
110
- export function Get(path: string | RouteMethodOptions): MethodDecorator;
111
- /**
112
- * @description HTTP Get method
113
- * @param {string} path
114
- * @param {RouteMethodOptions} options
115
- */
116
- export function Get(path: string, options: RouteMethodOptions): MethodDecorator;
117
- export function Get(
118
- path?: string | RouteMethodOptions,
119
- options?: RouteMethodOptions,
120
- ) {
121
- const parsedPath =
122
- !path && !options ? "/" : (path as string | RouteMethodOptions);
123
- if (options) {
124
- return createRouteDecorator("GET")(parsedPath, options);
125
- } else {
126
- return createRouteDecorator("GET")(parsedPath);
127
- }
128
- }
129
-
130
- export function Post(path?: string): MethodDecorator;
131
- export function Post(path: string | RouteMethodOptions): MethodDecorator;
132
- export function Post(
133
- path: string,
134
- options: RouteMethodOptions,
135
- ): MethodDecorator;
136
- export function Post(
137
- path?: string | RouteMethodOptions,
138
- options?: RouteMethodOptions,
139
- ) {
140
- const parsedPath =
141
- !path && !options ? "/" : (path as string | RouteMethodOptions);
142
- if (options) {
143
- return createRouteDecorator("POST")(parsedPath, options);
144
- } else {
145
- return createRouteDecorator("POST")(parsedPath);
146
- }
147
- }
148
-
149
- export function Put(path?: string): MethodDecorator;
150
- export function Put(path: string | RouteMethodOptions): MethodDecorator;
151
- export function Put(path: string, options: RouteMethodOptions): MethodDecorator;
152
- export function Put(
153
- path?: string | RouteMethodOptions,
154
- options?: RouteMethodOptions,
155
- ) {
156
- const parsedPath =
157
- !path && !options ? "/" : (path as string | RouteMethodOptions);
158
- if (options) {
159
- return createRouteDecorator("PUT")(parsedPath, options);
160
- } else {
161
- return createRouteDecorator("PUT")(parsedPath);
162
- }
163
- }
164
-
165
- export function Delete(path?: string): MethodDecorator;
166
- export function Delete(path: string | RouteMethodOptions): MethodDecorator;
167
- export function Delete(
168
- path: string,
169
- options: RouteMethodOptions,
170
- ): MethodDecorator;
171
- export function Delete(
172
- path?: string | RouteMethodOptions,
173
- options?: RouteMethodOptions,
174
- ) {
175
- const parsedPath =
176
- !path && !options ? "/" : (path as string | RouteMethodOptions);
177
- if (options) {
178
- return createRouteDecorator("DELETE")(parsedPath, options);
179
- } else {
180
- return createRouteDecorator("DELETE")(parsedPath);
181
- }
182
- }
183
-
184
- export const Patch = createRouteDecorator("PATCH");
185
- export const Options = createRouteDecorator("OPTIONS");
186
- export const All = createRouteDecorator("ALL");
@@ -1,213 +0,0 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
- import { getMetadataStorage } from "class-validator";
8
-
9
- export function generateSwaggerSchema(classType: any): any {
10
- const metadataStorage = getMetadataStorage();
11
- const validationMetadata = metadataStorage.getTargetValidationMetadatas(
12
- classType,
13
- "",
14
- true,
15
- false,
16
- );
17
-
18
- const schema: any = {
19
- type: "object",
20
- properties: {},
21
- required: [],
22
- };
23
-
24
- const prototype = classType.prototype;
25
-
26
- const propertyKeys = new Set([
27
- ...Object.getOwnPropertyNames(prototype),
28
- ...validationMetadata.map((m: any) => m.propertyName),
29
- ]);
30
-
31
- propertyKeys.forEach((propertyName) => {
32
- if (!propertyName || propertyName === "constructor") return;
33
-
34
- const openApiMeta: any = Reflect.getMetadata(
35
- "property:openapi",
36
- prototype,
37
- propertyName,
38
- );
39
-
40
- if (openApiMeta?.exclude) return;
41
-
42
- const propertyType = Reflect.getMetadata(
43
- "design:type",
44
- prototype,
45
- propertyName,
46
- );
47
-
48
- let swaggerProperty: any = {};
49
-
50
- switch (propertyType) {
51
- case String:
52
- swaggerProperty.type = "string";
53
- break;
54
- case Number:
55
- swaggerProperty.type = "number";
56
- break;
57
- case Boolean:
58
- swaggerProperty.type = "boolean";
59
- break;
60
- case Date:
61
- swaggerProperty.type = "string";
62
- swaggerProperty.format = "date-time";
63
- break;
64
- case Array:
65
- swaggerProperty.type = "array";
66
- swaggerProperty.items = { type: "string" }; // fallback
67
- break;
68
- case Object:
69
- swaggerProperty = generateSwaggerSchema(propertyType);
70
- break;
71
- default:
72
- swaggerProperty.type = propertyType?.name?.toLowerCase() || "string";
73
- }
74
-
75
- // Apply OpenApi metadata if present
76
- if (openApiMeta) {
77
- swaggerProperty = {
78
- ...swaggerProperty,
79
- ...extractOpenApiFields(openApiMeta),
80
- };
81
- }
82
-
83
- schema.properties[propertyName] = swaggerProperty;
84
- });
85
-
86
- // Handle validation rules
87
- validationMetadata.forEach((meta: any) => {
88
- const propertyName = meta.propertyName;
89
- switch (meta.name) {
90
- case "isNotEmpty":
91
- if (!schema.required.includes(propertyName)) {
92
- schema.required.push(propertyName);
93
- }
94
- break;
95
- case "isDefined":
96
- if (!schema.required.includes(propertyName)) {
97
- schema.required.push(propertyName);
98
- }
99
- break;
100
- case "isOptional":
101
- schema.required = schema.required.filter(
102
- (item: any) => item !== propertyName,
103
- );
104
- break;
105
- case "minLength":
106
- schema.properties[propertyName].minLength = meta.constraints[0];
107
- break;
108
- case "maxLength":
109
- schema.properties[propertyName].maxLength = meta.constraints[0];
110
- break;
111
- case "min":
112
- schema.properties[propertyName].minimum = meta.constraints[0];
113
- break;
114
- case "max":
115
- schema.properties[propertyName].maximum = meta.constraints[0];
116
- break;
117
- case "isEmail":
118
- schema.properties[propertyName].format = "email";
119
- break;
120
- case "isDate":
121
- schema.properties[propertyName].format = "date-time";
122
- break;
123
- case "isIn":
124
- schema.properties[propertyName].enum = meta.constraints[0];
125
- break;
126
- case "isNumber":
127
- schema.properties[propertyName].type = "number";
128
- break;
129
- case "isInt":
130
- schema.properties[propertyName].type = "integer";
131
- break;
132
- case "isBoolean":
133
- schema.properties[propertyName].type = "boolean";
134
- break;
135
- case "isString":
136
- schema.properties[propertyName].type = "string";
137
- break;
138
- }
139
- });
140
- return schema;
141
- }
142
-
143
- function extractOpenApiFields(meta: any): any {
144
- const result: any = {};
145
- const fields = [
146
- "description",
147
- "summary",
148
- "deprecated",
149
- "example",
150
- "enum",
151
- "format",
152
- "default",
153
- "minimum",
154
- "maximum",
155
- "minLength",
156
- "maxLength",
157
- "pattern",
158
- "oneOf",
159
- "allOf",
160
- "anyOf",
161
- ];
162
-
163
- fields.forEach((field) => {
164
- if (meta[field] !== undefined) {
165
- result[field] = meta[field];
166
- }
167
- });
168
-
169
- return result;
170
- }
171
-
172
- // export function generateSwaggerSchema(classType: any) {
173
- // const { getMetadataStorage } = require("class-validator");
174
- // const { plainToInstance } = require("class-transformer");
175
-
176
- // const metadataStorage = getMetadataStorage();
177
- // const validationMetadata = metadataStorage.getTargetValidationMetadatas(
178
- // classType,
179
- // "",
180
- // true,
181
- // );
182
-
183
- // const schema: any = {
184
- // type: "object",
185
- // properties: {},
186
- // required: [],
187
- // };
188
-
189
- // validationMetadata.forEach((meta: any) => {
190
- // const propertyName = meta.propertyName;
191
-
192
- // // Infer the type dynamically using Reflect metadata
193
- // const propertyType = Reflect.getMetadata(
194
- // "design:type",
195
- // classType.prototype,
196
- // propertyName,
197
- // );
198
-
199
- // schema.properties[propertyName] = {
200
- // type: propertyType?.name.toLowerCase() || "string", // Default to string if type cannot be inferred
201
- // };
202
-
203
- // if (meta.name === "isNotEmpty") {
204
- // schema.required.push(propertyName);
205
- // }
206
-
207
- // if (meta.name === "minLength") {
208
- // schema.properties[propertyName].minLength = meta.constraints[0];
209
- // }
210
- // });
211
-
212
- // return schema;
213
- // }
package/src/testing.ts DELETED
@@ -1,220 +0,0 @@
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,18 +0,0 @@
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,7 +0,0 @@
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 DELETED
@@ -1,8 +0,0 @@
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 +0,0 @@
1
- export * from "./hash";
2
- export * from "./optional-require";
@@ -1,50 +0,0 @@
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
- }