@avleon/core 0.0.13 → 0.0.16
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/classToOpenapi.d.ts +0 -0
- package/dist/classToOpenapi.js +1 -0
- package/dist/exceptions/http-exceptions.d.ts +0 -9
- package/dist/exceptions/http-exceptions.js +17 -9
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.js +23 -17
- package/dist/icore.d.ts +21 -14
- package/dist/icore.js +82 -66
- package/dist/index.d.ts +3 -0
- package/dist/index.js +32 -7
- package/dist/logger.d.ts +12 -0
- package/dist/logger.js +87 -0
- package/dist/openapi.d.ts +2 -0
- package/dist/params.js +4 -0
- package/dist/response.d.ts +2 -1
- package/dist/response.js +6 -4
- package/dist/swagger-schema.d.ts +0 -6
- package/dist/swagger-schema.js +102 -80
- package/package.json +57 -51
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -39,12 +39,3 @@ export declare class ForbiddenException extends BaseHttpException {
|
|
|
39
39
|
constructor(message: any);
|
|
40
40
|
}
|
|
41
41
|
export type HttpException = NotFoundException | BadRequestException | UnauthorizedException | InternalErrorException | ForbiddenException;
|
|
42
|
-
export type HttpExceptions = {
|
|
43
|
-
NotFound: (message: any) => NotFoundException;
|
|
44
|
-
ValidationError: (message: any) => ValidationErrorException;
|
|
45
|
-
BadRequest: (message: any) => BadRequestException;
|
|
46
|
-
Unauthorized: (message: any) => UnauthorizedException;
|
|
47
|
-
Forbidden: (message: any) => ForbiddenException;
|
|
48
|
-
InternalError: (message: any) => InternalErrorException;
|
|
49
|
-
};
|
|
50
|
-
export declare const httpExcepitoins: HttpExceptions;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ForbiddenException = exports.UnauthorizedException = exports.NotFoundException = exports.InternalErrorException = exports.ValidationErrorException = exports.BadRequestException = exports.BaseHttpException = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* @copyright 2024
|
|
6
6
|
* @author Tareq Hossain
|
|
@@ -65,11 +65,19 @@ class ForbiddenException extends BaseHttpException {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
exports.ForbiddenException = ForbiddenException;
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
68
|
+
// export type HttpExceptions = {
|
|
69
|
+
// NotFound: (message: any) => NotFoundException,
|
|
70
|
+
// ValidationError: (message: any) =>ValidationErrorException,
|
|
71
|
+
// BadRequest: (message: any) => BadRequestException,
|
|
72
|
+
// Unauthorized: (message: any) => UnauthorizedException,
|
|
73
|
+
// Forbidden: (message: any) => ForbiddenException,
|
|
74
|
+
// InternalError: (message: any) => InternalErrorException
|
|
75
|
+
// }
|
|
76
|
+
// export const httpExcepitoins: HttpExceptions = {
|
|
77
|
+
// NotFound:(message:any)=>new NotFoundException(message),
|
|
78
|
+
// ValidationError:(message:any)=>new ValidationErrorException(message),
|
|
79
|
+
// BadRequest:(message:any)=>new BadRequestException(message),
|
|
80
|
+
// Unauthorized:(message:any)=>new UnauthorizedException(message),
|
|
81
|
+
// Forbidden:(message:any)=>new ForbiddenException(message),
|
|
82
|
+
// InternalError: (message:any)=> new InternalErrorException(message)
|
|
83
|
+
// }
|
package/dist/helpers.d.ts
CHANGED
|
@@ -23,10 +23,10 @@ export declare function jsonToJs(value: string): any;
|
|
|
23
23
|
export declare function jsonToInstance(value: string, instance: Constructor): any;
|
|
24
24
|
export declare function transformObjectByInstanceToObject(instance: Constructor, value: object): Record<string, any>;
|
|
25
25
|
export declare const isClassValidatorClass: (target: Constructor) => boolean;
|
|
26
|
-
export declare function validateObjectByInstance(target: Constructor, value?: object, options?:
|
|
26
|
+
export declare function validateObjectByInstance(target: Constructor, value?: object, options?: "object" | "array"): Promise<any>;
|
|
27
27
|
type ValidationError = {
|
|
28
28
|
count: number;
|
|
29
29
|
errors: any;
|
|
30
30
|
};
|
|
31
|
-
export declare function validateRequestBody(target: Constructor, value: object, options?:
|
|
31
|
+
export declare function validateRequestBody(target: Constructor, value: object, options?: "object" | "array"): ValidationError;
|
|
32
32
|
export {};
|
package/dist/helpers.js
CHANGED
|
@@ -43,7 +43,7 @@ function inject(cls) {
|
|
|
43
43
|
}
|
|
44
44
|
function isConstructor(func) {
|
|
45
45
|
// Check if the func is a function
|
|
46
|
-
if (typeof func !==
|
|
46
|
+
if (typeof func !== "function") {
|
|
47
47
|
return false;
|
|
48
48
|
}
|
|
49
49
|
// Check if it's an arrow function or a built-in JavaScript function
|
|
@@ -51,13 +51,13 @@ function isConstructor(func) {
|
|
|
51
51
|
return false;
|
|
52
52
|
}
|
|
53
53
|
// Check if it has a `prototype` property
|
|
54
|
-
if (func.prototype && typeof func.prototype ===
|
|
54
|
+
if (func.prototype && typeof func.prototype === "object") {
|
|
55
55
|
return true;
|
|
56
56
|
}
|
|
57
57
|
// If it's not a constructor, check if it can be called with the new keyword
|
|
58
58
|
try {
|
|
59
59
|
const instance = new func();
|
|
60
|
-
return typeof instance ===
|
|
60
|
+
return typeof instance === "object";
|
|
61
61
|
}
|
|
62
62
|
catch (e) {
|
|
63
63
|
return false;
|
|
@@ -83,8 +83,7 @@ function parsedPath(ipath) {
|
|
|
83
83
|
const isClassValidator = (target) => {
|
|
84
84
|
try {
|
|
85
85
|
const clsval = require("class-validator");
|
|
86
|
-
const result = (0, class_validator_1.getMetadataStorage)()
|
|
87
|
-
.getTargetValidationMetadatas(target, '', false, false);
|
|
86
|
+
const result = (0, class_validator_1.getMetadataStorage)().getTargetValidationMetadatas(target, "", false, false);
|
|
88
87
|
return result.length > 0;
|
|
89
88
|
}
|
|
90
89
|
catch (err) {
|
|
@@ -216,7 +215,7 @@ const isClassValidatorClass = (target) => {
|
|
|
216
215
|
}
|
|
217
216
|
};
|
|
218
217
|
exports.isClassValidatorClass = isClassValidatorClass;
|
|
219
|
-
async function validateObjectByInstance(target, value = {}, options =
|
|
218
|
+
async function validateObjectByInstance(target, value = {}, options = "array") {
|
|
220
219
|
try {
|
|
221
220
|
const { validateOrReject } = require("class-validator");
|
|
222
221
|
const { plainToInstance } = require("class-transformer");
|
|
@@ -224,11 +223,16 @@ async function validateObjectByInstance(target, value = {}, options = 'array') {
|
|
|
224
223
|
}
|
|
225
224
|
catch (error) {
|
|
226
225
|
if (typeof error == "object" && Array.isArray(error)) {
|
|
227
|
-
const errors = options ==
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
226
|
+
const errors = options == "object"
|
|
227
|
+
? error.reduce((acc, x) => {
|
|
228
|
+
//acc[x.property] = Object.values(x.constraints);
|
|
229
|
+
acc[x.property] = x.constraints;
|
|
230
|
+
return acc;
|
|
231
|
+
}, {})
|
|
232
|
+
: error.map((x) => ({
|
|
233
|
+
path: x.property,
|
|
234
|
+
constraints: x.constraints,
|
|
235
|
+
}));
|
|
232
236
|
return errors;
|
|
233
237
|
}
|
|
234
238
|
else {
|
|
@@ -236,14 +240,16 @@ async function validateObjectByInstance(target, value = {}, options = 'array') {
|
|
|
236
240
|
}
|
|
237
241
|
}
|
|
238
242
|
}
|
|
239
|
-
function validateRequestBody(target, value, options =
|
|
243
|
+
function validateRequestBody(target, value, options = "array") {
|
|
240
244
|
if (!(0, exports.isClassValidatorClass)(target))
|
|
241
245
|
return { count: 0, errors: {} };
|
|
242
246
|
const error = (0, class_validator_1.validateSync)((0, class_transformer_1.plainToInstance)(target, value ? value : {}));
|
|
243
|
-
const errors = options ==
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
247
|
+
const errors = options == "object"
|
|
248
|
+
? error.reduce((acc, x) => {
|
|
249
|
+
//acc[x.property] = Object.values(x.constraints);
|
|
250
|
+
acc[x.property] = x.constraints;
|
|
251
|
+
return acc;
|
|
252
|
+
}, {})
|
|
253
|
+
: error.map((x) => ({ path: x.property, constraints: x.constraints }));
|
|
248
254
|
return { count: error.length, errors };
|
|
249
255
|
}
|
package/dist/icore.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* @email xtrinsic96@gmail.com
|
|
5
5
|
* @url https://github.com/xtareq
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { FastifyReply, FastifyRequest, HookHandlerDoneFunction, InjectOptions, LightMyRequestResponse } from "fastify";
|
|
8
8
|
import { Constructable } from "typedi";
|
|
9
9
|
import { Constructor } from "./helpers";
|
|
10
10
|
import { PathLike } from "fs";
|
|
@@ -27,9 +27,19 @@ export interface IRequest extends FastifyRequest {
|
|
|
27
27
|
headers: any;
|
|
28
28
|
user?: any;
|
|
29
29
|
}
|
|
30
|
+
export interface DoneFunction extends HookHandlerDoneFunction {
|
|
31
|
+
}
|
|
30
32
|
export interface IResponse extends FastifyReply {
|
|
31
33
|
}
|
|
32
|
-
export
|
|
34
|
+
export type TestResponseType = LightMyRequestResponse;
|
|
35
|
+
export type TestResponse = TestResponseType | Promise<TestResponseType>;
|
|
36
|
+
export interface TestApplication {
|
|
37
|
+
get: (url: string, options?: InjectOptions) => TestResponse;
|
|
38
|
+
post: (url: string, options?: InjectOptions) => TestResponse;
|
|
39
|
+
put: (url: string, options?: InjectOptions) => TestResponse;
|
|
40
|
+
patch: (url: string, options?: InjectOptions) => TestResponse;
|
|
41
|
+
delete: (url: string, options?: InjectOptions) => TestResponse;
|
|
42
|
+
options: (url: string, options?: InjectOptions) => TestResponse;
|
|
33
43
|
}
|
|
34
44
|
export interface ParamMetaOptions {
|
|
35
45
|
index: number;
|
|
@@ -39,6 +49,7 @@ export interface ParamMetaOptions {
|
|
|
39
49
|
validate: boolean;
|
|
40
50
|
dataType: any;
|
|
41
51
|
validatorClass: boolean;
|
|
52
|
+
schema?: any;
|
|
42
53
|
type: "route:param" | "route:query" | "route:body" | "route:header" | "route:user" | "route:file" | "route:files";
|
|
43
54
|
}
|
|
44
55
|
export interface ParamMetaFilesOptions {
|
|
@@ -64,7 +75,6 @@ type StaticFileOptions = {
|
|
|
64
75
|
type MultipartOptions = {
|
|
65
76
|
destination: PathLike;
|
|
66
77
|
} & FastifyMultipartOptions;
|
|
67
|
-
type AvleonApp = FastifyInstance;
|
|
68
78
|
export type TestAppOptions = {
|
|
69
79
|
controllers: Constructor[];
|
|
70
80
|
};
|
|
@@ -78,7 +88,7 @@ export interface IAvleonApplication {
|
|
|
78
88
|
useCors(corsOptions?: FastifyCorsOptions): void;
|
|
79
89
|
useOpenApi<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
|
|
80
90
|
useSwagger(options: OpenApiUiOptions): Promise<void>;
|
|
81
|
-
useMultipart(options: MultipartOptions):
|
|
91
|
+
useMultipart(options: MultipartOptions): void;
|
|
82
92
|
useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]): void;
|
|
83
93
|
useAuthoriztion<T extends any>(middleware: Constructor<T>): void;
|
|
84
94
|
mapRoute<T extends (...args: any[]) => any>(method: "get" | "post" | "put" | "delete", path: string, fn: T): Promise<void>;
|
|
@@ -89,7 +99,7 @@ export interface IAvleonApplication {
|
|
|
89
99
|
mapControllers(controllers: any[]): any;
|
|
90
100
|
useStaticFiles(options?: StaticFileOptions): void;
|
|
91
101
|
run(port?: number): Promise<void>;
|
|
92
|
-
getTestApp():
|
|
102
|
+
getTestApp(): TestApplication;
|
|
93
103
|
}
|
|
94
104
|
declare class AvleonApplication implements IAvleonApplication {
|
|
95
105
|
private static instance;
|
|
@@ -120,7 +130,7 @@ declare class AvleonApplication implements IAvleonApplication {
|
|
|
120
130
|
* Will remove in next major version
|
|
121
131
|
*/
|
|
122
132
|
useSwagger(options: OpenApiUiOptions): Promise<void>;
|
|
123
|
-
useMultipart(options: MultipartOptions):
|
|
133
|
+
useMultipart(options: MultipartOptions): void;
|
|
124
134
|
private handleMiddlewares;
|
|
125
135
|
private executeMiddlewares;
|
|
126
136
|
/**
|
|
@@ -173,7 +183,7 @@ declare class AvleonApplication implements IAvleonApplication {
|
|
|
173
183
|
useStaticFiles(options?: StaticFileOptions): void;
|
|
174
184
|
initializeDatabase(): Promise<void>;
|
|
175
185
|
run(port?: number): Promise<void>;
|
|
176
|
-
getTestApp(buildOptions?: any):
|
|
186
|
+
getTestApp(buildOptions?: any): TestApplication;
|
|
177
187
|
}
|
|
178
188
|
export type Application = typeof AvleonApplication;
|
|
179
189
|
export interface ITestBuilder {
|
|
@@ -193,11 +203,11 @@ export declare class TestBuilder {
|
|
|
193
203
|
static createBuilder(): TestBuilder;
|
|
194
204
|
getController<T>(controller: Constructor<T>): T;
|
|
195
205
|
getService<T>(service: Constructor<T>): T;
|
|
196
|
-
getTestApplication(options: TestAppOptions):
|
|
197
|
-
build(app: IAvleonApplication):
|
|
198
|
-
fromApplication(app: IAvleonApplication):
|
|
206
|
+
getTestApplication(options: TestAppOptions): TestApplication;
|
|
207
|
+
build(app: IAvleonApplication): TestApplication;
|
|
208
|
+
fromApplication(app: IAvleonApplication): TestApplication;
|
|
199
209
|
}
|
|
200
|
-
export declare class Builder implements
|
|
210
|
+
export declare class Builder implements IAppBuilder {
|
|
201
211
|
private static instance;
|
|
202
212
|
private alreadyBuilt;
|
|
203
213
|
private database;
|
|
@@ -207,12 +217,9 @@ export declare class Builder implements ITestBuilder, IAppBuilder {
|
|
|
207
217
|
private testBuilder;
|
|
208
218
|
private appConfig;
|
|
209
219
|
private constructor();
|
|
210
|
-
getTestApplication(): AvleonTestAppliction;
|
|
211
220
|
static createAppBuilder(): Builder;
|
|
212
|
-
static creatTestAppBuilder(): ITestBuilder;
|
|
213
221
|
registerPlugin<T extends Function, S extends {}>(plugin: T, options: S): Promise<void>;
|
|
214
222
|
addDataSource<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>["config"]>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
|
|
215
|
-
createTestApplication<T extends AvleonTestAppliction>(buildOptions?: any): any;
|
|
216
223
|
build<T extends IAvleonApplication>(): T;
|
|
217
224
|
}
|
|
218
225
|
export {};
|
package/dist/icore.js
CHANGED
|
@@ -94,7 +94,9 @@ class AvleonApplication {
|
|
|
94
94
|
this.authorizeMiddleware = undefined;
|
|
95
95
|
this.dataSource = undefined;
|
|
96
96
|
this.metaCache = new Map();
|
|
97
|
-
this.app = (0, fastify_1.default)(
|
|
97
|
+
this.app = (0, fastify_1.default)({
|
|
98
|
+
frameworkErrors: (error, req, res) => { },
|
|
99
|
+
});
|
|
98
100
|
this.appConfig = new config_1.AppConfig();
|
|
99
101
|
// this.app.setValidatorCompiler(() => () => true);
|
|
100
102
|
}
|
|
@@ -120,24 +122,41 @@ class AvleonApplication {
|
|
|
120
122
|
return env.get("NODE_ENV") == "development";
|
|
121
123
|
}
|
|
122
124
|
async initSwagger(options) {
|
|
123
|
-
const { routePrefix, logo, theme } = options, restOptions = __rest(options, ["routePrefix", "logo", "theme"]);
|
|
125
|
+
const { routePrefix, logo, ui, theme, configuration } = options, restOptions = __rest(options, ["routePrefix", "logo", "ui", "theme", "configuration"]);
|
|
124
126
|
this.app.register(swagger_1.default, {
|
|
125
127
|
openapi: Object.assign({ openapi: "3.0.0" }, restOptions),
|
|
126
128
|
});
|
|
127
129
|
const rPrefix = routePrefix ? routePrefix : "/docs";
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
130
|
+
if (options.ui && options.ui == "scalar") {
|
|
131
|
+
await this.app.register(require("@scalar/fastify-api-reference"), {
|
|
132
|
+
routePrefix: rPrefix,
|
|
133
|
+
configuration: configuration
|
|
134
|
+
? configuration
|
|
135
|
+
: {
|
|
136
|
+
metaData: {
|
|
137
|
+
title: "Avleon Api",
|
|
138
|
+
ogTitle: "Avleon",
|
|
139
|
+
},
|
|
140
|
+
theme: options.theme ? options.theme : "kepler",
|
|
141
|
+
favicon: "/static/favicon.png",
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
await this.app.register(require("@fastify/swagger-ui"), {
|
|
147
|
+
logo: logo ? logo : null,
|
|
148
|
+
theme: theme ? theme : {},
|
|
149
|
+
routePrefix: rPrefix,
|
|
150
|
+
configuration: {
|
|
151
|
+
metaData: {
|
|
152
|
+
title: "Avleon Api",
|
|
153
|
+
ogTitle: "Avleon",
|
|
154
|
+
},
|
|
155
|
+
theme: "kepler",
|
|
156
|
+
favicon: "/static/favicon.png",
|
|
136
157
|
},
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
},
|
|
140
|
-
});
|
|
158
|
+
});
|
|
159
|
+
}
|
|
141
160
|
}
|
|
142
161
|
useCors(corsOptions = {}) {
|
|
143
162
|
this.app.register(cors_1.default, corsOptions);
|
|
@@ -163,8 +182,7 @@ class AvleonApplication {
|
|
|
163
182
|
}
|
|
164
183
|
useMultipart(options) {
|
|
165
184
|
this.multipartOptions = options;
|
|
166
|
-
this.app.register(multipart_1.default,
|
|
167
|
-
return this;
|
|
185
|
+
this.app.register(multipart_1.default, Object.assign(Object.assign({}, this.multipartOptions), { attachFieldsToBody: true }));
|
|
168
186
|
}
|
|
169
187
|
handleMiddlewares(mclasses) {
|
|
170
188
|
for (const mclass of mclasses) {
|
|
@@ -222,11 +240,21 @@ class AvleonApplication {
|
|
|
222
240
|
const swaggerMeta = Reflect.getMetadata("route:openapi", prototype, method) || {};
|
|
223
241
|
const authClsMethodMeata = Reflect.getMetadata(container_1.AUTHORIZATION_META_KEY, ctrl.constructor, method) || { authorize: false, options: undefined };
|
|
224
242
|
const allMeta = this._processMeta(prototype, method);
|
|
243
|
+
let bodySchema = null;
|
|
244
|
+
allMeta.body.forEach((r) => {
|
|
245
|
+
if (r.schema) {
|
|
246
|
+
bodySchema = Object.assign({}, r.schema);
|
|
247
|
+
}
|
|
248
|
+
});
|
|
225
249
|
const routePath = methodmetaOptions.path == "" ? "/" : methodmetaOptions.path;
|
|
250
|
+
let schema = Object.assign(Object.assign(Object.assign({}, swaggerControllerMeta), swaggerMeta), { tags: [tag] });
|
|
251
|
+
if (!swaggerMeta.body && bodySchema) {
|
|
252
|
+
schema = Object.assign(Object.assign({}, schema), { body: bodySchema });
|
|
253
|
+
}
|
|
226
254
|
this.app.route({
|
|
227
255
|
url: routePath,
|
|
228
256
|
method: methodmetaOptions.method.toUpperCase(),
|
|
229
|
-
schema: Object.assign(
|
|
257
|
+
schema: Object.assign({}, schema),
|
|
230
258
|
handler: async (req, res) => {
|
|
231
259
|
let reqClone = req;
|
|
232
260
|
if (authClsMethodMeata.authorize && this.authorizeMiddleware) {
|
|
@@ -279,6 +307,7 @@ class AvleonApplication {
|
|
|
279
307
|
*/
|
|
280
308
|
async _mapArgs(req, meta) {
|
|
281
309
|
var _a, e_2, _b, _c, _d, e_3, _e, _f;
|
|
310
|
+
var _g;
|
|
282
311
|
if (!req.hasOwnProperty("_argsCache")) {
|
|
283
312
|
Object.defineProperty(req, "_argsCache", {
|
|
284
313
|
value: new Map(),
|
|
@@ -298,9 +327,9 @@ class AvleonApplication {
|
|
|
298
327
|
header.key === "all" ? req.headers : req.headers[header.key]));
|
|
299
328
|
if (meta.file) {
|
|
300
329
|
try {
|
|
301
|
-
for (var
|
|
302
|
-
_c =
|
|
303
|
-
|
|
330
|
+
for (var _h = true, _j = __asyncValues(meta.file), _k; _k = await _j.next(), _a = _k.done, !_a; _h = true) {
|
|
331
|
+
_c = _k.value;
|
|
332
|
+
_h = false;
|
|
304
333
|
let f = _c;
|
|
305
334
|
args[f.index] = await req.file();
|
|
306
335
|
}
|
|
@@ -308,12 +337,13 @@ class AvleonApplication {
|
|
|
308
337
|
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
309
338
|
finally {
|
|
310
339
|
try {
|
|
311
|
-
if (!
|
|
340
|
+
if (!_h && !_a && (_b = _j.return)) await _b.call(_j);
|
|
312
341
|
}
|
|
313
342
|
finally { if (e_2) throw e_2.error; }
|
|
314
343
|
}
|
|
315
344
|
}
|
|
316
|
-
if (meta.files
|
|
345
|
+
if (meta.files &&
|
|
346
|
+
((_g = req.headers["content-type"]) === null || _g === void 0 ? void 0 : _g.startsWith("multipart/form-data")) === true) {
|
|
317
347
|
const files = await req.saveRequestFiles();
|
|
318
348
|
if (!files || files.length === 0) {
|
|
319
349
|
throw new exceptions_1.BadRequestException({ error: "No files uploaded" });
|
|
@@ -328,9 +358,9 @@ class AvleonApplication {
|
|
|
328
358
|
fields: file.fields,
|
|
329
359
|
}));
|
|
330
360
|
try {
|
|
331
|
-
for (var
|
|
332
|
-
_f =
|
|
333
|
-
|
|
361
|
+
for (var _l = true, _m = __asyncValues(meta.files), _o; _o = await _m.next(), _d = _o.done, !_d; _l = true) {
|
|
362
|
+
_f = _o.value;
|
|
363
|
+
_l = false;
|
|
334
364
|
let f = _f;
|
|
335
365
|
const findex = fileInfo.findIndex((x) => x.fieldname == f.fieldName);
|
|
336
366
|
if (f.fieldName != "all" && findex == -1) {
|
|
@@ -345,7 +375,7 @@ class AvleonApplication {
|
|
|
345
375
|
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
346
376
|
finally {
|
|
347
377
|
try {
|
|
348
|
-
if (!
|
|
378
|
+
if (!_l && !_d && (_e = _m.return)) await _e.call(_m);
|
|
349
379
|
}
|
|
350
380
|
finally { if (e_3) throw e_3.error; }
|
|
351
381
|
}
|
|
@@ -402,6 +432,9 @@ class AvleonApplication {
|
|
|
402
432
|
if ((0, container_1.isApiController)(controller)) {
|
|
403
433
|
this.buildController(controller);
|
|
404
434
|
}
|
|
435
|
+
else {
|
|
436
|
+
throw new system_exception_1.SystemUseError("Not a api controller.");
|
|
437
|
+
}
|
|
405
438
|
}
|
|
406
439
|
}
|
|
407
440
|
}
|
|
@@ -555,16 +588,23 @@ class AvleonApplication {
|
|
|
555
588
|
await this.app.listen({ port });
|
|
556
589
|
console.log(`Application running on http://127.0.0.1:${port}`);
|
|
557
590
|
}
|
|
558
|
-
|
|
591
|
+
getTestApp(buildOptions) {
|
|
559
592
|
try {
|
|
560
593
|
if (buildOptions && buildOptions.addDataSource) {
|
|
561
|
-
const typeorm =
|
|
594
|
+
const typeorm = Promise.resolve().then(() => __importStar(require("typeorm")));
|
|
562
595
|
if (!typeorm) {
|
|
563
596
|
throw new system_exception_1.SystemUseError("TypeOrm not installed");
|
|
564
597
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
598
|
+
typeorm.then(async (t) => {
|
|
599
|
+
try {
|
|
600
|
+
const datasource = new t.DataSource(buildOptions.addDataSource);
|
|
601
|
+
typedi_1.default.set("idatasource", datasource);
|
|
602
|
+
await datasource.initialize();
|
|
603
|
+
}
|
|
604
|
+
catch (error) {
|
|
605
|
+
console.error("Database can't initialized.", error);
|
|
606
|
+
}
|
|
607
|
+
});
|
|
568
608
|
}
|
|
569
609
|
this._mapControllers();
|
|
570
610
|
this.rMap.forEach((value, key) => {
|
|
@@ -591,7 +631,15 @@ class AvleonApplication {
|
|
|
591
631
|
}
|
|
592
632
|
return res.status(handledErr.code).send(handledErr);
|
|
593
633
|
});
|
|
594
|
-
return this.app;
|
|
634
|
+
// return this.app as any;
|
|
635
|
+
return {
|
|
636
|
+
get: (url, options) => this.app.inject(Object.assign({ method: "GET", url }, options)),
|
|
637
|
+
post: (url, options) => this.app.inject(Object.assign({ method: "POST", url }, options)),
|
|
638
|
+
put: (url, options) => this.app.inject(Object.assign({ method: "PUT", url }, options)),
|
|
639
|
+
patch: (url, options) => this.app.inject(Object.assign({ method: "PATCH", url }, options)),
|
|
640
|
+
delete: (url, options) => this.app.inject(Object.assign({ method: "DELETE", url }, options)),
|
|
641
|
+
options: (url, options) => this.app.inject(Object.assign({ method: "OPTIONS", url }, options)),
|
|
642
|
+
};
|
|
595
643
|
}
|
|
596
644
|
catch (error) {
|
|
597
645
|
throw new system_exception_1.SystemUseError("Can't get test appliction");
|
|
@@ -613,12 +661,12 @@ class TestBuilder {
|
|
|
613
661
|
getService(service) {
|
|
614
662
|
return typedi_1.default.get(service);
|
|
615
663
|
}
|
|
616
|
-
|
|
664
|
+
getTestApplication(options) {
|
|
617
665
|
const app = AvleonApplication.getInternalApp({
|
|
618
666
|
dataSourceOptions: this.dataSourceOptions,
|
|
619
667
|
});
|
|
620
668
|
app.mapControllers([...options.controllers]);
|
|
621
|
-
const fa =
|
|
669
|
+
const fa = app.getTestApp();
|
|
622
670
|
return fa;
|
|
623
671
|
}
|
|
624
672
|
build(app) {
|
|
@@ -636,22 +684,12 @@ class Builder {
|
|
|
636
684
|
this.testBuilder = false;
|
|
637
685
|
this.appConfig = new config_1.AppConfig();
|
|
638
686
|
}
|
|
639
|
-
getTestApplication() {
|
|
640
|
-
throw new Error("Method not implemented.");
|
|
641
|
-
}
|
|
642
687
|
static createAppBuilder() {
|
|
643
688
|
if (!Builder.instance) {
|
|
644
689
|
Builder.instance = new Builder();
|
|
645
690
|
}
|
|
646
691
|
return Builder.instance;
|
|
647
692
|
}
|
|
648
|
-
static creatTestAppBuilder() {
|
|
649
|
-
if (!Builder.instance) {
|
|
650
|
-
Builder.instance = new Builder();
|
|
651
|
-
Builder.instance.testBuilder = true;
|
|
652
|
-
}
|
|
653
|
-
return Builder.instance;
|
|
654
|
-
}
|
|
655
693
|
async registerPlugin(plugin, options) {
|
|
656
694
|
container_1.default.set(plugin, plugin.prototype);
|
|
657
695
|
}
|
|
@@ -665,28 +703,6 @@ class Builder {
|
|
|
665
703
|
this.dataSourceOptions = openApiConfig;
|
|
666
704
|
}
|
|
667
705
|
}
|
|
668
|
-
createTestApplication(buildOptions) {
|
|
669
|
-
return {
|
|
670
|
-
addDataSource: (dataSourceOptions) => (this.dataSourceOptions = dataSourceOptions),
|
|
671
|
-
getApp: async (options) => {
|
|
672
|
-
const app = AvleonApplication.getInternalApp({
|
|
673
|
-
database: this.database,
|
|
674
|
-
dataSourceOptions: buildOptions.datSource,
|
|
675
|
-
});
|
|
676
|
-
app.mapControllers([...options.controllers]);
|
|
677
|
-
const _tapp = await app.getTestApp();
|
|
678
|
-
return {
|
|
679
|
-
async get(url, options) {
|
|
680
|
-
const res = await _tapp.inject(Object.assign({ url, method: "GET" }, options));
|
|
681
|
-
return res;
|
|
682
|
-
},
|
|
683
|
-
};
|
|
684
|
-
},
|
|
685
|
-
getController(controller) {
|
|
686
|
-
return typedi_1.default.get(controller);
|
|
687
|
-
},
|
|
688
|
-
};
|
|
689
|
-
}
|
|
690
706
|
build() {
|
|
691
707
|
if (this.alreadyBuilt) {
|
|
692
708
|
throw new Error("Already built");
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @email xtrinsic96@gmail.com
|
|
5
5
|
* @url https://github.com/xtareq
|
|
6
6
|
*/
|
|
7
|
+
import * as sw from "./swagger-schema";
|
|
7
8
|
export * from "./icore";
|
|
8
9
|
export { inject, validateRequestBody } from "./helpers";
|
|
9
10
|
export * from "./decorators";
|
|
@@ -21,4 +22,6 @@ export * from "./queue";
|
|
|
21
22
|
export * from "./security";
|
|
22
23
|
export * from "./multipart";
|
|
23
24
|
export * from "./file-storage";
|
|
25
|
+
export * from "./logger";
|
|
26
|
+
export declare const GetSchema: typeof sw.generateSwaggerSchema;
|
|
24
27
|
export { default as Container } from "./container";
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* @copyright 2024
|
|
4
|
-
* @author Tareq Hossain
|
|
5
|
-
* @email xtrinsic96@gmail.com
|
|
6
|
-
* @url https://github.com/xtareq
|
|
7
|
-
*/
|
|
8
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
3
|
if (k2 === undefined) k2 = k;
|
|
10
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -16,6 +10,28 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
16
10
|
if (k2 === undefined) k2 = k;
|
|
17
11
|
o[k2] = m[k];
|
|
18
12
|
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
19
35
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
20
36
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
37
|
};
|
|
@@ -23,7 +39,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
23
39
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
24
40
|
};
|
|
25
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.Container = exports.validateRequestBody = exports.inject = void 0;
|
|
42
|
+
exports.Container = exports.GetSchema = exports.validateRequestBody = exports.inject = void 0;
|
|
43
|
+
/**
|
|
44
|
+
* @copyright 2024
|
|
45
|
+
* @author Tareq Hossain
|
|
46
|
+
* @email xtrinsic96@gmail.com
|
|
47
|
+
* @url https://github.com/xtareq
|
|
48
|
+
*/
|
|
49
|
+
const sw = __importStar(require("./swagger-schema"));
|
|
27
50
|
__exportStar(require("./icore"), exports);
|
|
28
51
|
var helpers_1 = require("./helpers");
|
|
29
52
|
Object.defineProperty(exports, "inject", { enumerable: true, get: function () { return helpers_1.inject; } });
|
|
@@ -43,5 +66,7 @@ __exportStar(require("./queue"), exports);
|
|
|
43
66
|
__exportStar(require("./security"), exports);
|
|
44
67
|
__exportStar(require("./multipart"), exports);
|
|
45
68
|
__exportStar(require("./file-storage"), exports);
|
|
69
|
+
__exportStar(require("./logger"), exports);
|
|
70
|
+
exports.GetSchema = sw.generateSwaggerSchema;
|
|
46
71
|
var container_1 = require("./container");
|
|
47
72
|
Object.defineProperty(exports, "Container", { enumerable: true, get: function () { return __importDefault(container_1).default; } });
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import pino from "pino";
|
|
2
|
+
export declare class LoggerService {
|
|
3
|
+
private logger;
|
|
4
|
+
constructor();
|
|
5
|
+
getLogger(): pino.Logger;
|
|
6
|
+
info(message: string, obj?: any): void;
|
|
7
|
+
error(message: string, obj?: any): void;
|
|
8
|
+
warn(message: string, obj?: any): void;
|
|
9
|
+
debug(message: string, obj?: any): void;
|
|
10
|
+
fatal(message: string, obj?: any): void;
|
|
11
|
+
trace(message: string, obj?: any): void;
|
|
12
|
+
}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.LoggerService = void 0;
|
|
16
|
+
const pino_1 = __importDefault(require("pino"));
|
|
17
|
+
const decorators_1 = require("./decorators");
|
|
18
|
+
let LoggerService = class LoggerService {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.logger = (0, pino_1.default)({
|
|
21
|
+
level: process.env.LOG_LEVEL || "info",
|
|
22
|
+
transport: {
|
|
23
|
+
target: "pino-pretty",
|
|
24
|
+
options: {
|
|
25
|
+
translateTime: "SYS:standard",
|
|
26
|
+
ignore: "pid,hostname",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
getLogger() {
|
|
32
|
+
return this.logger;
|
|
33
|
+
}
|
|
34
|
+
info(message, obj) {
|
|
35
|
+
if (obj) {
|
|
36
|
+
this.logger.info(obj, message);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.logger.info(message);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
error(message, obj) {
|
|
43
|
+
if (obj) {
|
|
44
|
+
this.logger.error(obj, message);
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
this.logger.error(message);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
warn(message, obj) {
|
|
51
|
+
if (obj) {
|
|
52
|
+
this.logger.warn(obj, message);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
this.logger.warn(message);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
debug(message, obj) {
|
|
59
|
+
if (obj) {
|
|
60
|
+
this.logger.debug(obj, message);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
this.logger.debug(message);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
fatal(message, obj) {
|
|
67
|
+
if (obj) {
|
|
68
|
+
this.logger.fatal(obj, message);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
this.logger.fatal(message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
trace(message, obj) {
|
|
75
|
+
if (obj) {
|
|
76
|
+
this.logger.trace(obj, message);
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
this.logger.trace(message);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
exports.LoggerService = LoggerService;
|
|
84
|
+
exports.LoggerService = LoggerService = __decorate([
|
|
85
|
+
decorators_1.AppService,
|
|
86
|
+
__metadata("design:paramtypes", [])
|
|
87
|
+
], LoggerService);
|
package/dist/openapi.d.ts
CHANGED
package/dist/params.js
CHANGED
|
@@ -9,6 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.AuthUser = exports.Header = exports.Body = exports.Query = exports.Param = void 0;
|
|
10
10
|
const container_1 = require("./container");
|
|
11
11
|
const helpers_1 = require("./helpers");
|
|
12
|
+
const swagger_schema_1 = require("./swagger-schema");
|
|
12
13
|
function createParamDecorator(type) {
|
|
13
14
|
return function (key, options = {}) {
|
|
14
15
|
return function (target, propertyKey, parameterIndex) {
|
|
@@ -27,6 +28,9 @@ function createParamDecorator(type) {
|
|
|
27
28
|
validate: options.validate || true,
|
|
28
29
|
dataType: (0, helpers_1.getDataType)(paramDataType),
|
|
29
30
|
validatorClass: (0, helpers_1.isClassValidatorClass)(paramDataType),
|
|
31
|
+
schema: (0, helpers_1.isClassValidatorClass)(paramDataType)
|
|
32
|
+
? (0, swagger_schema_1.generateSwaggerSchema)(paramDataType)
|
|
33
|
+
: null,
|
|
30
34
|
type,
|
|
31
35
|
});
|
|
32
36
|
switch (type) {
|
package/dist/response.d.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* @email xtrinsic96@gmail.com
|
|
5
5
|
* @url https://github.com/xtareq
|
|
6
6
|
*/
|
|
7
|
-
import "reflect-metadata";
|
|
8
7
|
import { ClassConstructor } from "class-transformer";
|
|
9
8
|
export interface IHttpResponse<T extends any> {
|
|
10
9
|
message: string;
|
|
@@ -14,6 +13,8 @@ export declare class HttpResponse {
|
|
|
14
13
|
static Ok<T>(obj: any, s?: ClassConstructor<T>): IHttpResponse<T>;
|
|
15
14
|
static Created<T>(obj: any, s?: ClassConstructor<T>): IHttpResponse<T>;
|
|
16
15
|
static NoContent(): IHttpResponse<null>;
|
|
16
|
+
}
|
|
17
|
+
export declare class HttpExceptions {
|
|
17
18
|
static BadRequest(message: string, data?: any): IHttpResponse<any>;
|
|
18
19
|
static Unauthorized(message: string, data?: any): IHttpResponse<any>;
|
|
19
20
|
static Forbidden(message: string, data?: any): IHttpResponse<any>;
|
package/dist/response.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpExceptions = exports.HttpResponse = void 0;
|
|
2
4
|
/**
|
|
3
5
|
* @copyright 2024
|
|
4
6
|
* @author Tareq Hossain
|
|
5
7
|
* @email xtrinsic96@gmail.com
|
|
6
8
|
* @url https://github.com/xtareq
|
|
7
9
|
*/
|
|
8
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.HttpResponse = void 0;
|
|
10
|
-
require("reflect-metadata");
|
|
11
10
|
const class_transformer_1 = require("class-transformer");
|
|
12
11
|
function isClassTransformerClass(target) {
|
|
13
12
|
const prototype = target.prototype;
|
|
@@ -49,6 +48,9 @@ class HttpResponse {
|
|
|
49
48
|
static NoContent() {
|
|
50
49
|
return { message: "no content", data: null };
|
|
51
50
|
}
|
|
51
|
+
}
|
|
52
|
+
exports.HttpResponse = HttpResponse;
|
|
53
|
+
class HttpExceptions {
|
|
52
54
|
static BadRequest(message, data = null) {
|
|
53
55
|
return { message: message, data: data };
|
|
54
56
|
}
|
|
@@ -74,4 +76,4 @@ class HttpResponse {
|
|
|
74
76
|
return { message: message, data: data };
|
|
75
77
|
}
|
|
76
78
|
}
|
|
77
|
-
exports.
|
|
79
|
+
exports.HttpExceptions = HttpExceptions;
|
package/dist/swagger-schema.d.ts
CHANGED
package/dist/swagger-schema.js
CHANGED
|
@@ -7,22 +7,28 @@ exports.generateSwaggerSchema = generateSwaggerSchema;
|
|
|
7
7
|
* @email xtrinsic96@gmail.com
|
|
8
8
|
* @url https://github.com/xtareq
|
|
9
9
|
*/
|
|
10
|
+
const class_validator_1 = require("class-validator");
|
|
10
11
|
function generateSwaggerSchema(classType) {
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
//const { isArray } = require("lodash"); // Add lodash for array check
|
|
14
|
-
const metadataStorage = getMetadataStorage();
|
|
15
|
-
const validationMetadata = metadataStorage.getTargetValidationMetadatas(classType, "", true);
|
|
12
|
+
const metadataStorage = (0, class_validator_1.getMetadataStorage)();
|
|
13
|
+
const validationMetadata = metadataStorage.getTargetValidationMetadatas(classType, "", true, false);
|
|
16
14
|
const schema = {
|
|
17
15
|
type: "object",
|
|
18
16
|
properties: {},
|
|
19
17
|
required: [],
|
|
20
18
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
const prototype = classType.prototype;
|
|
20
|
+
const propertyKeys = new Set([
|
|
21
|
+
...Object.getOwnPropertyNames(prototype),
|
|
22
|
+
...validationMetadata.map((m) => m.propertyName),
|
|
23
|
+
]);
|
|
24
|
+
propertyKeys.forEach((propertyName) => {
|
|
25
|
+
var _a;
|
|
26
|
+
if (!propertyName || propertyName === "constructor")
|
|
27
|
+
return;
|
|
28
|
+
const openApiMeta = Reflect.getMetadata("property:openapi", prototype, propertyName);
|
|
29
|
+
if (openApiMeta === null || openApiMeta === void 0 ? void 0 : openApiMeta.exclude)
|
|
30
|
+
return;
|
|
31
|
+
const propertyType = Reflect.getMetadata("design:type", prototype, propertyName);
|
|
26
32
|
let swaggerProperty = {};
|
|
27
33
|
switch (propertyType) {
|
|
28
34
|
case String:
|
|
@@ -39,85 +45,101 @@ function generateSwaggerSchema(classType) {
|
|
|
39
45
|
swaggerProperty.format = "date-time";
|
|
40
46
|
break;
|
|
41
47
|
case Array:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
);
|
|
45
|
-
if (arrayItemType) {
|
|
46
|
-
swaggerProperty.type = "array";
|
|
47
|
-
swaggerProperty.items = {
|
|
48
|
-
type: arrayItemType.name.toLowerCase(), // basic type inference
|
|
49
|
-
};
|
|
50
|
-
if (arrayItemType === Object) {
|
|
51
|
-
//try to infer the Object type within array
|
|
52
|
-
const nestedSchema = generateSwaggerSchema(Reflect.getMetadata("design:type", classType.prototype, propertyName + "[0]"));
|
|
53
|
-
swaggerProperty.items = nestedSchema;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
swaggerProperty.type = "array";
|
|
58
|
-
swaggerProperty.items = {}; // Array of unknown type
|
|
59
|
-
}
|
|
48
|
+
swaggerProperty.type = "array";
|
|
49
|
+
swaggerProperty.items = { type: "string" }; // fallback
|
|
60
50
|
break;
|
|
61
51
|
case Object:
|
|
62
|
-
|
|
63
|
-
const nestedSchema = generateSwaggerSchema(Reflect.getMetadata("design:type", classType.prototype, propertyName));
|
|
64
|
-
swaggerProperty = nestedSchema;
|
|
52
|
+
swaggerProperty = generateSwaggerSchema(propertyType);
|
|
65
53
|
break;
|
|
66
54
|
default:
|
|
67
|
-
swaggerProperty.type = ((_a = propertyType === null || propertyType === void 0 ? void 0 : propertyType.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || "string";
|
|
55
|
+
swaggerProperty.type = ((_a = propertyType === null || propertyType === void 0 ? void 0 : propertyType.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || "string";
|
|
56
|
+
}
|
|
57
|
+
// Apply OpenApi metadata if present
|
|
58
|
+
if (openApiMeta) {
|
|
59
|
+
swaggerProperty = Object.assign(Object.assign({}, swaggerProperty), extractOpenApiFields(openApiMeta));
|
|
68
60
|
}
|
|
69
61
|
schema.properties[propertyName] = swaggerProperty;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
62
|
+
});
|
|
63
|
+
// Handle validation rules
|
|
64
|
+
validationMetadata.forEach((meta) => {
|
|
65
|
+
const propertyName = meta.propertyName;
|
|
66
|
+
switch (meta.name) {
|
|
67
|
+
case "isNotEmpty":
|
|
68
|
+
if (!schema.required.includes(propertyName)) {
|
|
69
|
+
schema.required.push(propertyName);
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case "isDefined":
|
|
73
|
+
if (!schema.required.includes(propertyName)) {
|
|
74
|
+
schema.required.push(propertyName);
|
|
75
|
+
}
|
|
76
|
+
break;
|
|
77
|
+
case "isOptional":
|
|
78
|
+
schema.required = schema.required.filter((item) => item !== propertyName);
|
|
79
|
+
break;
|
|
80
|
+
case "minLength":
|
|
81
|
+
schema.properties[propertyName].minLength = meta.constraints[0];
|
|
82
|
+
break;
|
|
83
|
+
case "maxLength":
|
|
84
|
+
schema.properties[propertyName].maxLength = meta.constraints[0];
|
|
85
|
+
break;
|
|
86
|
+
case "min":
|
|
87
|
+
schema.properties[propertyName].minimum = meta.constraints[0];
|
|
88
|
+
break;
|
|
89
|
+
case "max":
|
|
90
|
+
schema.properties[propertyName].maximum = meta.constraints[0];
|
|
91
|
+
break;
|
|
92
|
+
case "isEmail":
|
|
93
|
+
schema.properties[propertyName].format = "email";
|
|
94
|
+
break;
|
|
95
|
+
case "isDate":
|
|
96
|
+
schema.properties[propertyName].format = "date-time";
|
|
97
|
+
break;
|
|
98
|
+
case "isIn":
|
|
99
|
+
schema.properties[propertyName].enum = meta.constraints[0];
|
|
100
|
+
break;
|
|
101
|
+
case "isNumber":
|
|
102
|
+
schema.properties[propertyName].type = "number";
|
|
103
|
+
break;
|
|
104
|
+
case "isInt":
|
|
105
|
+
schema.properties[propertyName].type = "integer";
|
|
106
|
+
break;
|
|
107
|
+
case "isBoolean":
|
|
108
|
+
schema.properties[propertyName].type = "boolean";
|
|
109
|
+
break;
|
|
110
|
+
case "isString":
|
|
111
|
+
schema.properties[propertyName].type = "string";
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
118
114
|
});
|
|
119
115
|
return schema;
|
|
120
116
|
}
|
|
117
|
+
function extractOpenApiFields(meta) {
|
|
118
|
+
const result = {};
|
|
119
|
+
const fields = [
|
|
120
|
+
"description",
|
|
121
|
+
"summary",
|
|
122
|
+
"deprecated",
|
|
123
|
+
"example",
|
|
124
|
+
"enum",
|
|
125
|
+
"format",
|
|
126
|
+
"default",
|
|
127
|
+
"minimum",
|
|
128
|
+
"maximum",
|
|
129
|
+
"minLength",
|
|
130
|
+
"maxLength",
|
|
131
|
+
"pattern",
|
|
132
|
+
"oneOf",
|
|
133
|
+
"allOf",
|
|
134
|
+
"anyOf",
|
|
135
|
+
];
|
|
136
|
+
fields.forEach((field) => {
|
|
137
|
+
if (meta[field] !== undefined) {
|
|
138
|
+
result[field] = meta[field];
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
121
143
|
// export function generateSwaggerSchema(classType: any) {
|
|
122
144
|
// const { getMetadataStorage } = require("class-validator");
|
|
123
145
|
// const { plainToInstance } = require("class-transformer");
|
package/package.json
CHANGED
|
@@ -1,52 +1,58 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@avleon/core",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"main": "./dist/index.js",
|
|
5
|
-
"scripts": {
|
|
6
|
-
"build": "rimraf dist && tsc",
|
|
7
|
-
"watch": "tsc-watch",
|
|
8
|
-
"test": "jest",
|
|
9
|
-
"test:watch": "jest --watch"
|
|
10
|
-
},
|
|
11
|
-
"keywords": [],
|
|
12
|
-
"author": "Tareq Hossain",
|
|
13
|
-
"license": "ISC",
|
|
14
|
-
"devDependencies": {
|
|
15
|
-
"@types/jest": "^29.5.14",
|
|
16
|
-
"
|
|
17
|
-
"class-
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"ts-
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"@fastify/
|
|
30
|
-
"@fastify/
|
|
31
|
-
"@fastify/
|
|
32
|
-
"@fastify/swagger
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
"
|
|
46
|
-
},
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@avleon/core",
|
|
3
|
+
"version": "0.0.16",
|
|
4
|
+
"main": "./dist/index.js",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "rimraf dist && tsc",
|
|
7
|
+
"watch": "tsc-watch",
|
|
8
|
+
"test": "jest",
|
|
9
|
+
"test:watch": "jest --watch"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [],
|
|
12
|
+
"author": "Tareq Hossain",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@types/jest": "^29.5.14",
|
|
16
|
+
"@types/node": "^20.17.25",
|
|
17
|
+
"class-transformer": "^0.5.1",
|
|
18
|
+
"class-validator": "^0.14.1",
|
|
19
|
+
"jest": "^29.7.0",
|
|
20
|
+
"nodemon": "^3.1.7",
|
|
21
|
+
"sharp": "^0.33.5",
|
|
22
|
+
"ts-jest": "^29.2.5",
|
|
23
|
+
"ts-node": "^10.9.2",
|
|
24
|
+
"tsc-watch": "^6.2.1",
|
|
25
|
+
"typeorm": "^0.3.20",
|
|
26
|
+
"typescript": "^5.7.2"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@fastify/cors": "^11.0.0",
|
|
30
|
+
"@fastify/multipart": "^9.0.3",
|
|
31
|
+
"@fastify/static": "^8.1.1",
|
|
32
|
+
"@fastify/swagger": "^9.4.0",
|
|
33
|
+
"@fastify/swagger-ui": "^5.1.0",
|
|
34
|
+
"bcryptjs": "^3.0.2",
|
|
35
|
+
"dotenv": "^16.4.7",
|
|
36
|
+
"fastify": "^5.1.0",
|
|
37
|
+
"pino": "^9.6.0",
|
|
38
|
+
"pino-pretty": "^13.0.0",
|
|
39
|
+
"reflect-metadata": "^0.2.2",
|
|
40
|
+
"typedi": "^0.10.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"class-transformer": "^0.5.1",
|
|
44
|
+
"class-validator": "^0.14.1",
|
|
45
|
+
"typeorm": "^0.3.20"
|
|
46
|
+
},
|
|
47
|
+
"optionalDependencies": {
|
|
48
|
+
"@scalar/fastify-api-reference": "^1.25.119"
|
|
49
|
+
},
|
|
50
|
+
"directories": {
|
|
51
|
+
"test": "tests"
|
|
52
|
+
},
|
|
53
|
+
"description": "avleon core",
|
|
54
|
+
"repository": {
|
|
55
|
+
"type": "git",
|
|
56
|
+
"url": "git+https://github.com/avleonjs/avleon-core"
|
|
57
|
+
}
|
|
52
58
|
}
|