@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.
- package/README.md +601 -561
- package/package.json +38 -6
- package/src/application.ts +104 -125
- package/src/authentication.ts +16 -16
- package/src/cache.ts +91 -91
- package/src/collection.test.ts +71 -0
- package/src/collection.ts +344 -254
- package/src/config.test.ts +35 -0
- package/src/config.ts +85 -42
- package/src/constants.ts +1 -1
- package/src/container.ts +54 -54
- package/src/controller.ts +125 -127
- package/src/decorators.ts +27 -27
- package/src/environment-variables.ts +53 -46
- package/src/exceptions/http-exceptions.ts +86 -86
- package/src/exceptions/index.ts +1 -1
- package/src/exceptions/system-exception.ts +35 -34
- package/src/file-storage.ts +206 -206
- package/src/helpers.ts +324 -328
- package/src/icore.ts +66 -90
- package/src/index.ts +30 -30
- package/src/interfaces/avleon-application.ts +32 -40
- package/src/logger.ts +72 -72
- package/src/map-types.ts +159 -159
- package/src/middleware.ts +119 -98
- package/src/multipart.ts +116 -116
- package/src/openapi.ts +372 -372
- package/src/params.ts +111 -111
- package/src/queue.ts +126 -126
- package/src/response.ts +74 -74
- package/src/results.ts +30 -30
- package/src/route-methods.ts +186 -186
- package/src/swagger-schema.ts +213 -213
- package/src/testing.ts +220 -220
- package/src/types/app-builder.interface.ts +18 -19
- package/src/types/application.interface.ts +7 -9
- package/src/utils/hash.ts +8 -5
- package/src/utils/index.ts +2 -2
- package/src/utils/optional-require.ts +50 -50
- package/src/validation.ts +160 -156
- 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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
* @
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
2
|
-
export const hashPasswordSync = (password: string) =>
|
|
3
|
-
|
|
4
|
-
export const
|
|
5
|
-
|
|
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);
|
package/src/utils/index.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
1
|
+
export * from "./hash";
|
|
2
|
+
export * from "./optional-require";
|
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
+
}
|