@avleon/core 0.0.24 → 0.0.26
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/dist/application.d.ts +21 -0
- package/dist/cache.d.ts +12 -0
- package/dist/cache.js +78 -0
- package/dist/exceptions/http-exceptions.d.ts +9 -1
- package/dist/exceptions/http-exceptions.js +9 -9
- package/dist/icore.d.ts +32 -78
- package/dist/icore.js +118 -117
- package/dist/interfaces/avleon-application.d.ts +27 -0
- package/dist/interfaces/avleon-application.js +1 -0
- package/dist/middleware.d.ts +1 -1
- package/dist/response.d.ts +0 -10
- package/dist/response.js +1 -28
- package/dist/testing.js +1 -1
- package/package.json +21 -12
- package/src/application.ts +29 -0
- package/src/cache.ts +91 -0
- package/src/config.ts +3 -0
- package/src/controller.ts +1 -2
- package/src/exceptions/http-exceptions.ts +10 -10
- package/src/icore.ts +178 -158
- package/src/interfaces/avleon-application.ts +40 -0
- package/src/middleware.ts +1 -1
- package/src/response.ts +0 -43
- package/src/testing.ts +1 -1
package/src/controller.ts
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* @url https://github.com/xtareq
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
9
8
|
import Container, { Service } from "typedi";
|
|
10
9
|
import container, {
|
|
11
10
|
API_CONTROLLER_METADATA_KEY,
|
|
@@ -100,7 +99,7 @@ export function ApiController(
|
|
|
100
99
|
options?: ControllerOptions,
|
|
101
100
|
): ClassDecorator;
|
|
102
101
|
export function ApiController(
|
|
103
|
-
pathOrOptions: Function |string | ControllerOptions = "/",
|
|
102
|
+
pathOrOptions: Function | string | ControllerOptions = "/",
|
|
104
103
|
mayBeOptions?: ControllerOptions,
|
|
105
104
|
): any {
|
|
106
105
|
if (typeof pathOrOptions == 'function') {
|
|
@@ -11,7 +11,7 @@ export abstract class BaseHttpException extends Error {
|
|
|
11
11
|
super(JSON.stringify(message));
|
|
12
12
|
}
|
|
13
13
|
isCustomException() {
|
|
14
|
-
return true;
|
|
14
|
+
return true;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -61,7 +61,7 @@ export class ForbiddenException extends BaseHttpException {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
export type
|
|
64
|
+
export type HttpExceptionTypes =
|
|
65
65
|
| NotFoundException
|
|
66
66
|
| BadRequestException
|
|
67
67
|
| UnauthorizedException
|
|
@@ -76,11 +76,11 @@ export type HttpException =
|
|
|
76
76
|
// Forbidden: (message: any) => ForbiddenException,
|
|
77
77
|
// InternalError: (message: any) => InternalErrorException
|
|
78
78
|
// }
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
export const HttpExceptions = {
|
|
80
|
+
notFound:(message:any="")=>new NotFoundException(message),
|
|
81
|
+
validationError:(message:any="")=>new ValidationErrorException(message),
|
|
82
|
+
badRequest:(message:any="")=>new BadRequestException(message),
|
|
83
|
+
unauthorized:(message:any="")=>new UnauthorizedException(message),
|
|
84
|
+
forbidden:(message:any="")=>new ForbiddenException(message),
|
|
85
|
+
internalError: (message:any="")=> new InternalErrorException(message)
|
|
86
|
+
}
|
package/src/icore.ts
CHANGED
|
@@ -159,23 +159,29 @@ type AvleonApp = FastifyInstance;
|
|
|
159
159
|
|
|
160
160
|
export type TestAppOptions = {
|
|
161
161
|
controllers: Constructor[];
|
|
162
|
+
dataSource?: DataSource
|
|
162
163
|
};
|
|
163
164
|
|
|
164
165
|
export interface AvleonTestAppliction {
|
|
165
166
|
addDataSource: (dataSourceOptions: DataSourceOptions) => void;
|
|
166
167
|
getApp: (options?: TestAppOptions) => any;
|
|
167
|
-
getController: <T>(controller: Constructor<T
|
|
168
|
+
getController: <T>(controller: Constructor<T>, deps: any[]) => T;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export type AutoControllerOptions = {
|
|
172
|
+
auto: true,
|
|
173
|
+
path?: string
|
|
168
174
|
}
|
|
169
175
|
export interface IAvleonApplication {
|
|
170
176
|
isDevelopment(): boolean;
|
|
171
177
|
useCors(corsOptions?: FastifyCorsOptions): void;
|
|
172
178
|
useDataSource<
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
>(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
): void;
|
|
179
|
+
T extends IConfig<R>,
|
|
180
|
+
R = ReturnType<InstanceType<Constructable<T>>["config"]>,
|
|
181
|
+
>(
|
|
182
|
+
ConfigClass: Constructable<T>,
|
|
183
|
+
modifyConfig?: (config: R) => R,
|
|
184
|
+
): void;
|
|
179
185
|
useOpenApi<
|
|
180
186
|
T extends IConfig<R>,
|
|
181
187
|
R = ReturnType<InstanceType<Constructable<T>>["config"]>,
|
|
@@ -183,8 +189,9 @@ export interface IAvleonApplication {
|
|
|
183
189
|
ConfigClass: Constructable<T>,
|
|
184
190
|
modifyConfig?: (config: R) => R,
|
|
185
191
|
): void;
|
|
186
|
-
|
|
192
|
+
|
|
187
193
|
useMultipart(options: MultipartOptions): void;
|
|
194
|
+
useCache(options: any): void
|
|
188
195
|
|
|
189
196
|
useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]): void;
|
|
190
197
|
useAuthoriztion<T extends any>(middleware: Constructor<T>): void;
|
|
@@ -194,16 +201,21 @@ export interface IAvleonApplication {
|
|
|
194
201
|
fn: T,
|
|
195
202
|
): Promise<void>;
|
|
196
203
|
mapGet<T extends (...args: any[]) => any>(path: string, fn: T): any;
|
|
197
|
-
|
|
198
204
|
mapPost<T extends (...args: any[]) => any>(path: string, fn: T): any;
|
|
199
205
|
mapPut<T extends (...args: any[]) => any>(path: string, fn: T): any;
|
|
200
206
|
mapDelete<T extends (...args: any[]) => any>(path: string, fn: T): any;
|
|
201
|
-
|
|
207
|
+
useControllers(controllers: any[]): any;
|
|
208
|
+
useControllers(controllersOptions: AutoControllerOptions): any;
|
|
209
|
+
useControllers(controllersOrOptions: any[] | AutoControllerOptions): any;
|
|
202
210
|
useStaticFiles(options?: StaticFileOptions): void;
|
|
203
211
|
run(port?: number): Promise<void>;
|
|
204
212
|
getTestApp(): TestApplication;
|
|
205
213
|
}
|
|
214
|
+
type OpenApiConfigClass<T = any> = Constructable<IConfig<T>>;
|
|
215
|
+
type OpenApiConfigInput<T = any> = OpenApiConfigClass<T> | T;
|
|
206
216
|
|
|
217
|
+
type ConfigClass<T = any> = Constructable<IConfig<T>>;
|
|
218
|
+
type ConfigInput<T = any> = ConfigClass<T> | T;
|
|
207
219
|
// InternalApplication
|
|
208
220
|
export class AvleonApplication {
|
|
209
221
|
private static instance: AvleonApplication;
|
|
@@ -222,6 +234,8 @@ export class AvleonApplication {
|
|
|
222
234
|
private appConfig: AppConfig;
|
|
223
235
|
private dataSource?: DataSource = undefined;
|
|
224
236
|
private isMapFeatures = false;
|
|
237
|
+
private registerControllerAuto = false;
|
|
238
|
+
private registerControllerPath = './src';
|
|
225
239
|
|
|
226
240
|
private metaCache = new Map<string, MethodParamMeta>();
|
|
227
241
|
private multipartOptions: FastifyMultipartOptions | undefined;
|
|
@@ -230,7 +244,6 @@ export class AvleonApplication {
|
|
|
230
244
|
this.appConfig = new AppConfig();
|
|
231
245
|
}
|
|
232
246
|
|
|
233
|
-
private isTest() { }
|
|
234
247
|
|
|
235
248
|
static getApp(): AvleonApplication {
|
|
236
249
|
let isTestEnv = process.env.NODE_ENV == "test";
|
|
@@ -311,94 +324,89 @@ export class AvleonApplication {
|
|
|
311
324
|
});
|
|
312
325
|
}
|
|
313
326
|
}
|
|
314
|
-
|
|
315
|
-
|
|
327
|
+
|
|
328
|
+
private _isConfigClass<T>(input: any): input is ConfigClass<T> {
|
|
329
|
+
return (
|
|
330
|
+
typeof input === 'function' &&
|
|
331
|
+
typeof input.prototype === 'object' &&
|
|
332
|
+
input.prototype?.constructor === input
|
|
333
|
+
);
|
|
316
334
|
}
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
335
|
+
useCors<T = FastifyCorsOptions>(corsOptions?: ConfigInput<T>) {
|
|
336
|
+
let coptions: any = {};
|
|
337
|
+
if (corsOptions) {
|
|
338
|
+
if (this._isConfigClass<T>(corsOptions)) {
|
|
339
|
+
coptions = this.appConfig.get(corsOptions) as T;
|
|
340
|
+
} else {
|
|
341
|
+
coptions = corsOptions as T;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
this.app.register(cors, coptions);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
useOpenApi<T = OpenApiUiOptions>(
|
|
348
|
+
configOrClass: OpenApiConfigInput<T>
|
|
349
|
+
) {
|
|
350
|
+
let openApiConfig: T;
|
|
351
|
+
if (this._isConfigClass(configOrClass)) {
|
|
352
|
+
openApiConfig = this.appConfig.get(configOrClass);
|
|
325
353
|
} else {
|
|
326
|
-
|
|
354
|
+
openApiConfig = configOrClass as T;
|
|
327
355
|
}
|
|
356
|
+
this.globalSwaggerOptions = openApiConfig;
|
|
328
357
|
this.hasSwagger = true;
|
|
329
358
|
}
|
|
330
359
|
|
|
360
|
+
useMultipart<T extends MultipartOptions>(options: ConfigInput<T>) {
|
|
361
|
+
let multipartOptions: T;
|
|
362
|
+
if (this._isConfigClass(options)) {
|
|
363
|
+
multipartOptions = this.appConfig.get(options);
|
|
364
|
+
} else {
|
|
365
|
+
multipartOptions = options as T;
|
|
366
|
+
}
|
|
367
|
+
if (multipartOptions) {
|
|
368
|
+
this.multipartOptions = multipartOptions;
|
|
369
|
+
this.app.register(fastifyMultipart, {
|
|
370
|
+
...this.multipartOptions,
|
|
371
|
+
attachFieldsToBody: true,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
}
|
|
331
375
|
|
|
332
376
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
this.
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
377
|
+
useDataSource<T extends DataSourceOptions>(options: ConfigInput<T>) {
|
|
378
|
+
|
|
379
|
+
let dataSourceOptions: T;
|
|
380
|
+
if (this._isConfigClass(options)) {
|
|
381
|
+
dataSourceOptions = this.appConfig.get(options);
|
|
382
|
+
} else {
|
|
383
|
+
dataSourceOptions = options as T;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
if (!dataSourceOptions) throw new SystemUseError("Invlaid datasource options.")
|
|
387
|
+
|
|
388
|
+
this.dataSourceOptions = dataSourceOptions;
|
|
389
|
+
const typeorm = require("typeorm");
|
|
390
|
+
const datasource = new typeorm.DataSource(
|
|
391
|
+
dataSourceOptions,
|
|
392
|
+
) as DataSource;
|
|
393
|
+
|
|
394
|
+
this.dataSource = datasource;
|
|
395
|
+
|
|
396
|
+
Container.set<DataSource>("idatasource",
|
|
397
|
+
datasource,
|
|
398
|
+
);
|
|
349
399
|
|
|
350
400
|
|
|
351
|
-
/**
|
|
352
|
-
* Configures and initializes a TypeORM DataSource based on the provided configuration class.
|
|
353
|
-
* It retrieves the configuration from the application's configuration service and allows for optional modification.
|
|
354
|
-
* The initialized DataSource is then stored and registered within a dependency injection container.
|
|
355
|
-
*
|
|
356
|
-
* @template T - A generic type extending the `IConfig` interface, representing the configuration class.
|
|
357
|
-
* @template R - A generic type representing the return type of the configuration method of the `ConfigClass`.
|
|
358
|
-
* @param {Constructable<T>} ConfigClass - The constructor of the configuration class to be used for creating the DataSource.
|
|
359
|
-
* @param {(config: R) => R} [modifyConfig] - An optional function that takes the initial configuration and returns a modified configuration.
|
|
360
|
-
* @returns {void}
|
|
361
|
-
* @property {DataSourceOptions} this.dataSourceOptions - Stores the final DataSource options after potential modification.
|
|
362
|
-
* @property {DataSource} this.dataSource - Stores the initialized TypeORM DataSource instance.
|
|
363
|
-
* @see {@link https://typeorm.io/} for more information about TypeORM.
|
|
364
|
-
*/
|
|
365
|
-
useDataSource<
|
|
366
|
-
T extends IConfig<R>,
|
|
367
|
-
R = ReturnType<InstanceType<Constructable<T>>["config"]>,
|
|
368
|
-
>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R) {
|
|
369
|
-
const dsConfig: R = this.appConfig.get(ConfigClass);
|
|
370
|
-
if (modifyConfig) {
|
|
371
|
-
const modifiedConfig: R = modifyConfig(dsConfig);
|
|
372
|
-
this.dataSourceOptions = modifiedConfig as unknown as DataSourceOptions;
|
|
373
|
-
} else {
|
|
374
|
-
this.dataSourceOptions = dsConfig as unknown as DataSourceOptions;
|
|
375
401
|
}
|
|
376
402
|
|
|
377
|
-
|
|
378
|
-
const datasource = new typeorm.DataSource(
|
|
379
|
-
dsConfig,
|
|
380
|
-
) as DataSource;
|
|
403
|
+
private _useCache(options: any) {
|
|
381
404
|
|
|
382
|
-
|
|
405
|
+
}
|
|
383
406
|
|
|
384
|
-
Container.set<DataSource>("idatasource",
|
|
385
|
-
datasource,
|
|
386
|
-
);
|
|
387
|
-
}
|
|
388
407
|
|
|
389
408
|
|
|
390
|
-
|
|
391
|
-
* Registers an array of middleware classes to be executed before request handlers.
|
|
392
|
-
* It retrieves instances of the middleware classes from the dependency injection container
|
|
393
|
-
* and adds them as 'preHandler' hooks to the Fastify application.
|
|
394
|
-
*
|
|
395
|
-
* @template T - A generic type extending the `AppMiddleware` interface, representing the middleware class.
|
|
396
|
-
* @param {Constructor<T>[]} mclasses - An array of middleware class constructors to be registered.
|
|
397
|
-
* @returns {void}
|
|
398
|
-
* @property {Map<string, T>} this.middlewares - Stores the registered middleware instances, keyed by their class names.
|
|
399
|
-
* @see {@link https://www.fastify.io/docs/latest/Reference/Hooks/#prehandler} for more information about Fastify preHandler hooks.
|
|
400
|
-
*/
|
|
401
|
-
useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
409
|
+
useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
402
410
|
for (const mclass of mclasses) {
|
|
403
411
|
const cls = Container.get<T>(mclass);
|
|
404
412
|
this.middlewares.set(mclass.name, cls);
|
|
@@ -407,31 +415,11 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
407
415
|
}
|
|
408
416
|
|
|
409
417
|
|
|
410
|
-
/**
|
|
411
|
-
* Registers a middleware constructor to be used for authorization purposes.
|
|
412
|
-
* The specific implementation and usage of this middleware will depend on the application's authorization logic.
|
|
413
|
-
*
|
|
414
|
-
* @template T - A generic type representing the constructor of the authorization middleware.
|
|
415
|
-
* @param {Constructor<T>} middleware - The constructor of the middleware to be used for authorization.
|
|
416
|
-
* @returns {void}
|
|
417
|
-
* @property {any} this.authorizeMiddleware - Stores the constructor of the authorization middleware.
|
|
418
|
-
*/
|
|
419
418
|
useAuthoriztion<T extends any>(middleware: Constructor<T>) {
|
|
420
419
|
this.authorizeMiddleware = middleware as any;
|
|
421
420
|
}
|
|
422
421
|
|
|
423
422
|
|
|
424
|
-
|
|
425
|
-
/**
|
|
426
|
-
* Registers the `@fastify/static` plugin to serve static files.
|
|
427
|
-
* It configures the root directory and URL prefix for serving static assets.
|
|
428
|
-
*
|
|
429
|
-
* @param {StaticFileOptions} [options={ path: undefined, prefix: undefined }] - Optional configuration for serving static files.
|
|
430
|
-
* @param {string} [options.path] - The absolute path to the static files directory. Defaults to 'process.cwd()/public'.
|
|
431
|
-
* @param {string} [options.prefix] - The URL prefix for serving static files. Defaults to '/static/'.
|
|
432
|
-
* @returns {void}
|
|
433
|
-
* @see {@link https://github.com/fastify/fastify-static} for more details on available options.
|
|
434
|
-
*/
|
|
435
423
|
useStaticFiles(
|
|
436
424
|
options: StaticFileOptions = { path: undefined, prefix: undefined },
|
|
437
425
|
) {
|
|
@@ -441,10 +429,6 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
441
429
|
});
|
|
442
430
|
}
|
|
443
431
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
432
|
private handleMiddlewares<T extends AppMiddleware>(
|
|
449
433
|
mclasses: Constructor<T>[],
|
|
450
434
|
) {
|
|
@@ -535,7 +519,7 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
535
519
|
handler: async (req, res) => {
|
|
536
520
|
let reqClone = req as IRequest;
|
|
537
521
|
|
|
538
|
-
|
|
522
|
+
|
|
539
523
|
// class level authrization
|
|
540
524
|
if (authClsMeata.authorize && this.authorizeMiddleware) {
|
|
541
525
|
const cls = container.get(this.authorizeMiddleware) as any;
|
|
@@ -714,37 +698,74 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
714
698
|
return meta;
|
|
715
699
|
}
|
|
716
700
|
|
|
717
|
-
|
|
718
|
-
const
|
|
719
|
-
|
|
701
|
+
private _resolveControllerDir(dir?: string) {
|
|
702
|
+
const isTsNode =
|
|
703
|
+
process.env.TS_NODE_DEV ||
|
|
704
|
+
process.env.TS_NODE_PROJECT ||
|
|
705
|
+
(process as any)[Symbol.for("ts-node.register.instance")];
|
|
706
|
+
const controllerDir = path.join(
|
|
707
|
+
process.cwd(),
|
|
708
|
+
this.registerControllerPath
|
|
709
|
+
);
|
|
710
|
+
|
|
711
|
+
return isTsNode ? controllerDir : controllerDir.replace('src', 'dist')
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
private async autoControllers(controllersPath?: string) {
|
|
715
|
+
const conDir = this._resolveControllerDir(controllersPath);
|
|
716
|
+
|
|
717
|
+
const files = await fs.readdir(conDir, { recursive: true });
|
|
720
718
|
for (const file of files) {
|
|
719
|
+
const isTestFile = /\.(test|spec|e2e-spec)\.ts$/.test(file);
|
|
720
|
+
if (isTestFile) continue;
|
|
721
721
|
if (isTsNode ? file.endsWith(".ts") : file.endsWith(".js")) {
|
|
722
|
-
const filePath = path.join(
|
|
722
|
+
const filePath = path.join(conDir, file);
|
|
723
723
|
const module = await import(filePath);
|
|
724
724
|
for (const exported of Object.values(module)) {
|
|
725
725
|
if (typeof exported === "function" && isApiController(exported)) {
|
|
726
|
-
|
|
726
|
+
console.log('adding', exported.name)
|
|
727
|
+
if (!this.controllers.some(con => exported.name == con.name)) {
|
|
728
|
+
this.controllers.push(exported)
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
//this.buildController(exported);
|
|
727
732
|
}
|
|
728
733
|
}
|
|
729
734
|
}
|
|
730
735
|
}
|
|
731
736
|
}
|
|
732
737
|
|
|
733
|
-
|
|
734
|
-
|
|
738
|
+
useControllers(controllers: Constructor[] | AutoControllerOptions) {
|
|
739
|
+
|
|
740
|
+
if (Array.isArray(controllers)) {
|
|
741
|
+
this.controllers = controllers;
|
|
742
|
+
|
|
743
|
+
controllers.forEach(controller => {
|
|
744
|
+
if (!this.controllers.includes(controller)) {
|
|
745
|
+
this.controllers.push(controller)
|
|
746
|
+
}
|
|
747
|
+
})
|
|
748
|
+
} else {
|
|
749
|
+
this.registerControllerAuto = true;
|
|
750
|
+
if (controllers.path) {
|
|
751
|
+
this.registerControllerPath = controllers.path;
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
|
|
735
755
|
}
|
|
736
756
|
|
|
737
757
|
// addFeature(feature:{controllers:Function[]}){
|
|
738
758
|
// feature.controllers.forEach(c=> this.controllers.push(c))
|
|
739
759
|
// }
|
|
740
760
|
|
|
741
|
-
mapFeature(){
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
}
|
|
761
|
+
// mapFeature(){
|
|
762
|
+
// if(!this.isMapFeatures){
|
|
763
|
+
// this.isMapFeatures = true;
|
|
764
|
+
// }
|
|
765
|
+
// }
|
|
746
766
|
|
|
747
767
|
private async _mapControllers() {
|
|
768
|
+
|
|
748
769
|
if (this.controllers.length > 0) {
|
|
749
770
|
for (let controller of this.controllers) {
|
|
750
771
|
if (isApiController(controller)) {
|
|
@@ -756,14 +777,11 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
756
777
|
}
|
|
757
778
|
}
|
|
758
779
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
}
|
|
764
|
-
}
|
|
780
|
+
// useControllersAuto(controllerPath?:string) {
|
|
781
|
+
// this.registerControllerAuto = true;
|
|
782
|
+
// //this.autoControllers();
|
|
783
|
+
// }
|
|
765
784
|
|
|
766
|
-
async handleRoute(args: any) { }
|
|
767
785
|
|
|
768
786
|
private async mapFn(fn: Function) {
|
|
769
787
|
const original = fn;
|
|
@@ -827,8 +845,7 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
827
845
|
middlewares: [],
|
|
828
846
|
schema: {},
|
|
829
847
|
});
|
|
830
|
-
|
|
831
|
-
this.mapFn(fn);
|
|
848
|
+
// this.mapFn(fn);
|
|
832
849
|
|
|
833
850
|
const route = {
|
|
834
851
|
useMiddleware: <M extends AppMiddleware>(
|
|
@@ -878,7 +895,7 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
878
895
|
}
|
|
879
896
|
|
|
880
897
|
|
|
881
|
-
private _mapFeatures(){
|
|
898
|
+
private _mapFeatures() {
|
|
882
899
|
const features = Container.get('features');
|
|
883
900
|
console.log('Features', features);
|
|
884
901
|
}
|
|
@@ -889,7 +906,7 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
889
906
|
}
|
|
890
907
|
}
|
|
891
908
|
|
|
892
|
-
async run(port: number = 4000, fn?:CallableFunction): Promise<void> {
|
|
909
|
+
async run(port: number = 4000, fn?: CallableFunction): Promise<void> {
|
|
893
910
|
if (this.alreadyRun) throw new SystemUseError("App already running");
|
|
894
911
|
this.alreadyRun = true;
|
|
895
912
|
|
|
@@ -897,9 +914,13 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
897
914
|
await this.initSwagger(this.globalSwaggerOptions);
|
|
898
915
|
}
|
|
899
916
|
await this.initializeDatabase();
|
|
900
|
-
if(this.isMapFeatures){
|
|
917
|
+
if (this.isMapFeatures) {
|
|
901
918
|
this._mapFeatures();
|
|
902
919
|
}
|
|
920
|
+
|
|
921
|
+
if (this.registerControllerAuto) {
|
|
922
|
+
await this.autoControllers();
|
|
923
|
+
}
|
|
903
924
|
await this._mapControllers();
|
|
904
925
|
|
|
905
926
|
this.rMap.forEach((value, key) => {
|
|
@@ -975,8 +996,15 @@ useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]) {
|
|
|
975
996
|
this.app.inject({ method: "DELETE", url, ...options }),
|
|
976
997
|
options: async (url: string, options?: InjectOptions) =>
|
|
977
998
|
this.app.inject({ method: "OPTIONS", url, ...options }),
|
|
978
|
-
getController: <T>(controller: Constructor<T
|
|
979
|
-
|
|
999
|
+
getController: <T>(controller: Constructor<T>, deps: any[] = []) => {
|
|
1000
|
+
const paramTypes = Reflect.getMetadata('design:paramtypes', controller) || [];
|
|
1001
|
+
|
|
1002
|
+
deps.forEach((dep, i) => {
|
|
1003
|
+
Container.set(paramTypes[i], dep);
|
|
1004
|
+
});
|
|
1005
|
+
|
|
1006
|
+
return Container.get(controller);
|
|
1007
|
+
|
|
980
1008
|
},
|
|
981
1009
|
};
|
|
982
1010
|
} catch (error) {
|
|
@@ -1009,26 +1037,17 @@ export interface IAppBuilder {
|
|
|
1009
1037
|
build<T extends IAvleonApplication>(): T;
|
|
1010
1038
|
}
|
|
1011
1039
|
|
|
1012
|
-
export class
|
|
1013
|
-
private static instance: TestBuilder;
|
|
1014
|
-
private app: any;
|
|
1015
|
-
private dataSourceOptions?: DataSourceOptions | undefined;
|
|
1040
|
+
export class AvleonTest {
|
|
1016
1041
|
private constructor() {
|
|
1017
1042
|
process.env.NODE_ENV = "test";
|
|
1018
1043
|
}
|
|
1044
|
+
static getController<T>(controller: Constructor<T>, deps: any[] = []) {
|
|
1045
|
+
const paramTypes = Reflect.getMetadata('design:paramtypes', controller) || [];
|
|
1019
1046
|
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
}
|
|
1024
|
-
return TestBuilder.instance;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
addDatasource(options: DataSourceOptions) {
|
|
1028
|
-
this.dataSourceOptions = options;
|
|
1029
|
-
}
|
|
1047
|
+
deps.forEach((dep, i) => {
|
|
1048
|
+
Container.set(paramTypes[i], dep);
|
|
1049
|
+
});
|
|
1030
1050
|
|
|
1031
|
-
private getController<T>(controller: Constructor<T>) {
|
|
1032
1051
|
return Container.get(controller);
|
|
1033
1052
|
}
|
|
1034
1053
|
|
|
@@ -1036,27 +1055,28 @@ export class TestBuilder {
|
|
|
1036
1055
|
return Container.get(service);
|
|
1037
1056
|
}
|
|
1038
1057
|
|
|
1039
|
-
|
|
1058
|
+
|
|
1059
|
+
static createTestApplication(options: TestAppOptions) {
|
|
1040
1060
|
const app = AvleonApplication.getInternalApp({
|
|
1041
|
-
dataSourceOptions:
|
|
1061
|
+
dataSourceOptions: options.dataSource ? options.dataSource : null,
|
|
1042
1062
|
});
|
|
1043
|
-
app.
|
|
1063
|
+
app.useControllers([...options.controllers]);
|
|
1044
1064
|
return app.getTestApp();
|
|
1045
1065
|
}
|
|
1046
1066
|
|
|
1047
|
-
|
|
1067
|
+
static from(app: AvleonApplication) {
|
|
1048
1068
|
return app.getTestApp();
|
|
1049
1069
|
}
|
|
1050
1070
|
|
|
1051
|
-
|
|
1052
|
-
|
|
1071
|
+
static clean() {
|
|
1072
|
+
Container.reset();
|
|
1053
1073
|
}
|
|
1054
1074
|
}
|
|
1055
1075
|
|
|
1056
|
-
export class
|
|
1076
|
+
export class Avleon {
|
|
1057
1077
|
|
|
1058
|
-
static createApplication(){
|
|
1059
|
-
const app =
|
|
1078
|
+
static createApplication() {
|
|
1079
|
+
const app = AvleonApplication.getApp();
|
|
1060
1080
|
return app
|
|
1061
1081
|
}
|
|
1062
1082
|
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
|
package/src/middleware.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { Service } from "typedi";
|
|
8
8
|
import { IRequest, IResponse } from "./icore";
|
|
9
|
-
import { HttpException, UnauthorizedException } from "./exceptions";
|
|
9
|
+
import { HttpExceptionTypes as HttpException, UnauthorizedException } from "./exceptions";
|
|
10
10
|
import Container, { AUTHORIZATION_META_KEY } from "./container";
|
|
11
11
|
|
|
12
12
|
export abstract class AppMiddleware {
|
package/src/response.ts
CHANGED
|
@@ -72,46 +72,3 @@ export class HttpResponse {
|
|
|
72
72
|
return { message: "no content", data: null };
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
-
|
|
76
|
-
export class HttpExceptions {
|
|
77
|
-
static BadRequest(message: string, data: any = null): IHttpResponse<any> {
|
|
78
|
-
return { message: message, data: data };
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
static Unauthorized(message: string, data: any = null): IHttpResponse<any> {
|
|
82
|
-
return { message: message, data: data };
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
static Forbidden(message: string, data: any = null): IHttpResponse<any> {
|
|
86
|
-
return { message: message, data: data };
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
static NotFound(message: string, data: any = null): IHttpResponse<any> {
|
|
90
|
-
return { message: message, data: data };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
static InternalServerError(
|
|
94
|
-
message: string = "Internal server error",
|
|
95
|
-
data: any = null
|
|
96
|
-
): IHttpResponse<any> {
|
|
97
|
-
return { message: message, data: data };
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
static Conflict(message: string, data: any = null): IHttpResponse<any> {
|
|
101
|
-
return { message: message, data: data };
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
static UnprocessableEntity(
|
|
105
|
-
message: string,
|
|
106
|
-
data: any = null
|
|
107
|
-
): IHttpResponse<any> {
|
|
108
|
-
return { message: message, data: data };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
static TooManyRequests(
|
|
112
|
-
message: string,
|
|
113
|
-
data: any = null
|
|
114
|
-
): IHttpResponse<any> {
|
|
115
|
-
return { message: message, data: data };
|
|
116
|
-
}
|
|
117
|
-
}
|