@avleon/core 0.0.5 → 0.0.6
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 +1 -1
- package/dist/authentication.d.ts +3 -5
- package/dist/authentication.js +3 -3
- package/dist/config.d.ts +7 -8
- package/dist/config.js +9 -7
- package/dist/container.d.ts +1 -0
- package/dist/container.js +2 -1
- package/dist/controller.d.ts +2 -1
- package/dist/controller.js +17 -3
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +23 -0
- package/dist/icore.d.ts +11 -1
- package/dist/icore.js +70 -17
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/middleware.d.ts +14 -0
- package/dist/middleware.js +29 -7
- package/dist/validation.d.ts +23 -0
- package/dist/validation.js +98 -0
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/authentication.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export type CurrentUser = {};
|
|
2
|
-
export declare abstract class
|
|
3
|
-
abstract
|
|
4
|
-
abstract
|
|
5
|
-
abstract verifyToken(): boolean;
|
|
6
|
-
abstract currentUser(): CurrentUser;
|
|
2
|
+
export declare abstract class BaseAuthetication {
|
|
3
|
+
abstract authenticate(): Promise<Boolean>;
|
|
4
|
+
abstract authorize(): Promise<Boolean>;
|
|
7
5
|
}
|
|
8
6
|
export declare function Authorized(): void;
|
|
9
7
|
export declare function CurrentUser(): void;
|
package/dist/authentication.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.BaseAuthetication = void 0;
|
|
4
4
|
exports.Authorized = Authorized;
|
|
5
5
|
exports.CurrentUser = CurrentUser;
|
|
6
|
-
class
|
|
6
|
+
class BaseAuthetication {
|
|
7
7
|
}
|
|
8
|
-
exports.
|
|
8
|
+
exports.BaseAuthetication = BaseAuthetication;
|
|
9
9
|
function Authorized() {
|
|
10
10
|
}
|
|
11
11
|
function CurrentUser() { }
|
package/dist/config.d.ts
CHANGED
|
@@ -18,13 +18,12 @@ export interface IAppConfig {
|
|
|
18
18
|
apiKey: string;
|
|
19
19
|
timezone: string;
|
|
20
20
|
}
|
|
21
|
-
interface
|
|
22
|
-
|
|
21
|
+
export interface IConfig {
|
|
22
|
+
config(env: Environment): object;
|
|
23
23
|
}
|
|
24
|
-
export declare function Config(target: {
|
|
25
|
-
new (
|
|
24
|
+
export declare function Config<T extends IConfig>(target: {
|
|
25
|
+
new (): T;
|
|
26
26
|
}): void;
|
|
27
|
-
export declare function GetConfig<T extends
|
|
28
|
-
new (
|
|
29
|
-
}): ReturnType<T["
|
|
30
|
-
export {};
|
|
27
|
+
export declare function GetConfig<T extends IConfig>(ConfigClass: {
|
|
28
|
+
new (): T;
|
|
29
|
+
}): ReturnType<T["config"]>;
|
package/dist/config.js
CHANGED
|
@@ -3,17 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Config = Config;
|
|
4
4
|
exports.GetConfig = GetConfig;
|
|
5
5
|
const CONFIG_METADATA_KEY = Symbol("config");
|
|
6
|
+
const configInstances = new Map();
|
|
6
7
|
function Config(target) {
|
|
7
|
-
if (typeof target.prototype.
|
|
8
|
-
throw new Error(`Class "${target.name}" must implement
|
|
8
|
+
if (typeof target.prototype.config !== "function") {
|
|
9
|
+
throw new Error(`Class "${target.name}" must implement a "config" method.`);
|
|
9
10
|
}
|
|
10
11
|
Reflect.defineMetadata(CONFIG_METADATA_KEY, target, target);
|
|
12
|
+
// Auto-instantiate and store the config instance
|
|
13
|
+
configInstances.set(target.name, new target());
|
|
11
14
|
}
|
|
12
15
|
function GetConfig(ConfigClass) {
|
|
13
|
-
const
|
|
14
|
-
if (!
|
|
15
|
-
throw new Error(`Class "${ConfigClass.name}" is not
|
|
16
|
+
const instance = configInstances.get(ConfigClass.name);
|
|
17
|
+
if (!instance) {
|
|
18
|
+
throw new Error(`Class "${ConfigClass.name}" is not registered as a config.`);
|
|
16
19
|
}
|
|
17
|
-
|
|
18
|
-
return instance.invoke(process.env);
|
|
20
|
+
return instance.config(process.env);
|
|
19
21
|
}
|
package/dist/container.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare const REQUEST_BODY_META_KEY: unique symbol;
|
|
|
7
7
|
export declare const REQUEST_USER_META_KEY: unique symbol;
|
|
8
8
|
export declare const REQUEST_HEADER_META_KEY: unique symbol;
|
|
9
9
|
export declare const DATASOURCE_META_KEY: unique symbol;
|
|
10
|
+
export declare const AUTHORIZATION_META_KEY: unique symbol;
|
|
10
11
|
declare const Container: typeof TypediContainer;
|
|
11
12
|
export declare function registerController(controller: Function): void;
|
|
12
13
|
export declare function registerService(service: Function): void;
|
package/dist/container.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.API_CONTROLLER_METADATA_KEY = exports.DATASOURCE_META_KEY = exports.REQUEST_HEADER_META_KEY = exports.REQUEST_USER_META_KEY = exports.REQUEST_BODY_META_KEY = exports.QUERY_META_KEY = exports.PARAM_META_KEY = exports.CONTROLLER_META_KEY = exports.ROUTE_META_KEY = void 0;
|
|
6
|
+
exports.API_CONTROLLER_METADATA_KEY = exports.AUTHORIZATION_META_KEY = exports.DATASOURCE_META_KEY = exports.REQUEST_HEADER_META_KEY = exports.REQUEST_USER_META_KEY = exports.REQUEST_BODY_META_KEY = exports.QUERY_META_KEY = exports.PARAM_META_KEY = exports.CONTROLLER_META_KEY = exports.ROUTE_META_KEY = void 0;
|
|
7
7
|
exports.registerController = registerController;
|
|
8
8
|
exports.registerService = registerService;
|
|
9
9
|
exports.getRegisteredServices = getRegisteredServices;
|
|
@@ -19,6 +19,7 @@ exports.REQUEST_BODY_META_KEY = Symbol("iparam:options");
|
|
|
19
19
|
exports.REQUEST_USER_META_KEY = Symbol("iparam:options");
|
|
20
20
|
exports.REQUEST_HEADER_META_KEY = Symbol("iheader:options");
|
|
21
21
|
exports.DATASOURCE_META_KEY = Symbol("idatasource:options");
|
|
22
|
+
exports.AUTHORIZATION_META_KEY = Symbol("idatasource:authorization");
|
|
22
23
|
const controllerRegistry = new Set();
|
|
23
24
|
const serviceRegistry = new Set();
|
|
24
25
|
const optionsRegistry = new Map();
|
package/dist/controller.d.ts
CHANGED
|
@@ -35,7 +35,8 @@ export declare function createControllerDecorator(type?: "api" | "web"): (pathOr
|
|
|
35
35
|
* @param path {string} this will used as route prefix
|
|
36
36
|
*
|
|
37
37
|
**/
|
|
38
|
-
export declare function ApiController(
|
|
38
|
+
export declare function ApiController(target: Function): void;
|
|
39
|
+
export declare function ApiController(path: string): ClassDecorator;
|
|
39
40
|
/**
|
|
40
41
|
*@description Api controller's are used for rest . It will populate
|
|
41
42
|
* json on return and all it http methods {get} {post} etc must return
|
package/dist/controller.js
CHANGED
|
@@ -31,8 +31,22 @@ function createControllerDecorator(type = "web") {
|
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
function ApiController(pathOrOptions = "/", mayBeOptions) {
|
|
34
|
-
if (
|
|
35
|
-
|
|
34
|
+
if (typeof pathOrOptions == 'function') {
|
|
35
|
+
Reflect.defineMetadata(container_1.API_CONTROLLER_METADATA_KEY, true, pathOrOptions);
|
|
36
|
+
// Ensure Service is applied as a ClassDecorator
|
|
37
|
+
if (typeof typedi_1.Service === "function") {
|
|
38
|
+
(0, container_1.registerController)(pathOrOptions); // Add to custom registry
|
|
39
|
+
(0, typedi_1.Service)()(pathOrOptions); // Apply DI decorator
|
|
40
|
+
Reflect.defineMetadata(container_1.CONTROLLER_META_KEY, { type: 'api', path: "/", options: {} }, pathOrOptions);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
throw new Error("Service decorator is not a function");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
if (mayBeOptions) {
|
|
48
|
+
return createControllerDecorator("api")(pathOrOptions, mayBeOptions);
|
|
49
|
+
}
|
|
50
|
+
return createControllerDecorator("api")(pathOrOptions);
|
|
36
51
|
}
|
|
37
|
-
return createControllerDecorator("api")(pathOrOptions);
|
|
38
52
|
}
|
package/dist/helpers.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare const uuid: `${string}-${string}-${string}-${string}-${string}`;
|
|
2
2
|
export declare function inject<T>(cls: new (...args: any[]) => T): T;
|
|
3
3
|
export type Constructor<T = any> = new (...args: any[]) => T;
|
|
4
|
+
export declare function isConstructor(func: any): boolean;
|
|
4
5
|
export declare function formatUrl(path: string): string;
|
|
5
6
|
export declare function parsedPath(ipath: string): string;
|
|
6
7
|
export declare const isClassValidator: (target: Constructor) => boolean;
|
package/dist/helpers.js
CHANGED
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.isClassValidatorClass = exports.getLineNumber = exports.isClassValidator = exports.uuid = void 0;
|
|
7
7
|
exports.inject = inject;
|
|
8
|
+
exports.isConstructor = isConstructor;
|
|
8
9
|
exports.formatUrl = formatUrl;
|
|
9
10
|
exports.parsedPath = parsedPath;
|
|
10
11
|
exports.normalizePath = normalizePath;
|
|
@@ -34,6 +35,28 @@ function inject(cls) {
|
|
|
34
35
|
throw new system_exception_1.SystemUseError(`Not a project class. Maybe you wanna register it first.`);
|
|
35
36
|
}
|
|
36
37
|
}
|
|
38
|
+
function isConstructor(func) {
|
|
39
|
+
// Check if the func is a function
|
|
40
|
+
if (typeof func !== 'function') {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
// Check if it's an arrow function or a built-in JavaScript function
|
|
44
|
+
if (func === Function.prototype.bind || func instanceof RegExp) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
// Check if it has a `prototype` property
|
|
48
|
+
if (func.prototype && typeof func.prototype === 'object') {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
// If it's not a constructor, check if it can be called with the new keyword
|
|
52
|
+
try {
|
|
53
|
+
const instance = new func();
|
|
54
|
+
return typeof instance === 'object';
|
|
55
|
+
}
|
|
56
|
+
catch (e) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
37
60
|
function formatUrl(path) {
|
|
38
61
|
if (typeof path !== "string") {
|
|
39
62
|
throw new Error("The path must be a string");
|
package/dist/icore.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
|
|
1
|
+
import { FastifyInstance, FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
|
|
2
2
|
import { Constructor } from "./helpers";
|
|
3
|
+
import { PathLike } from "fs";
|
|
3
4
|
import { DataSourceOptions } from "typeorm";
|
|
4
5
|
import { AppMiddleware } from "./middleware";
|
|
5
6
|
import { OpenApiOptions, OpenApiUiOptions } from "./openapi";
|
|
@@ -37,6 +38,10 @@ export interface MethodParamMeta {
|
|
|
37
38
|
currentUser: ParamMetaOptions[];
|
|
38
39
|
swagger?: OpenApiUiOptions;
|
|
39
40
|
}
|
|
41
|
+
type StaticFileOptions = {
|
|
42
|
+
path?: PathLike;
|
|
43
|
+
prefix?: string;
|
|
44
|
+
};
|
|
40
45
|
declare class AvleonApplication {
|
|
41
46
|
private static instance;
|
|
42
47
|
private static buildOptions;
|
|
@@ -49,6 +54,7 @@ declare class AvleonApplication {
|
|
|
49
54
|
private hasSwagger;
|
|
50
55
|
private globalSwaggerOptions;
|
|
51
56
|
private controllers;
|
|
57
|
+
private authorizeMiddleware?;
|
|
52
58
|
private constructor();
|
|
53
59
|
static getInternalApp(buildOptions: any): AvleonApplication;
|
|
54
60
|
isDevelopment(): boolean;
|
|
@@ -67,6 +73,7 @@ declare class AvleonApplication {
|
|
|
67
73
|
handleRoute(args: any): Promise<void>;
|
|
68
74
|
private mapFn;
|
|
69
75
|
useMiddlewares<T extends AppMiddleware>(mclasses: Constructor<T>[]): void;
|
|
76
|
+
useAuthoriztion<T extends any>(middleware: Constructor<T>): void;
|
|
70
77
|
private _handleError;
|
|
71
78
|
mapRoute<T extends (...args: any[]) => any>(method: "get" | "post" | "put" | "delete", path: string | undefined, fn: T): Promise<void>;
|
|
72
79
|
private _routeHandler;
|
|
@@ -86,7 +93,9 @@ declare class AvleonApplication {
|
|
|
86
93
|
useMiddleware: <M extends AppMiddleware>(middlewares: Constructor<AppMiddleware>[]) => /*elided*/ any;
|
|
87
94
|
useSwagger: (options: OpenApiOptions) => /*elided*/ any;
|
|
88
95
|
};
|
|
96
|
+
useStaticFiles(options?: StaticFileOptions): void;
|
|
89
97
|
run(port?: number): Promise<void>;
|
|
98
|
+
getTestApp(app: AvleonApplication): FastifyInstance<import("fastify").RawServerDefault, import("http").IncomingMessage, import("http").ServerResponse<import("http").IncomingMessage>, import("fastify").FastifyBaseLogger, import("fastify").FastifyTypeProviderDefault>;
|
|
90
99
|
}
|
|
91
100
|
export declare class Builder {
|
|
92
101
|
private static instance;
|
|
@@ -95,6 +104,7 @@ export declare class Builder {
|
|
|
95
104
|
private dataSource?;
|
|
96
105
|
private constructor();
|
|
97
106
|
static createAppBuilder(): Builder;
|
|
107
|
+
static creatTestAppBilder(): Builder;
|
|
98
108
|
registerPlugin<T extends Function, S extends {}>(plugin: T, options: S): Promise<void>;
|
|
99
109
|
addDataSource(config: DataSourceOptions): Promise<void>;
|
|
100
110
|
build(): AvleonApplication;
|
package/dist/icore.js
CHANGED
|
@@ -57,7 +57,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
57
57
|
exports.Builder = void 0;
|
|
58
58
|
const fastify_1 = __importDefault(require("fastify"));
|
|
59
59
|
const typedi_1 = __importDefault(require("typedi"));
|
|
60
|
-
const promises_1 = __importDefault(require("fs/promises"));
|
|
60
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
61
61
|
const path_1 = __importDefault(require("path"));
|
|
62
62
|
const container_1 = __importStar(require("./container"));
|
|
63
63
|
const helpers_1 = require("./helpers");
|
|
@@ -82,6 +82,7 @@ class AvleonApplication {
|
|
|
82
82
|
this.hasSwagger = false;
|
|
83
83
|
this.globalSwaggerOptions = {};
|
|
84
84
|
this.controllers = [];
|
|
85
|
+
this.authorizeMiddleware = undefined;
|
|
85
86
|
this.metaCache = new Map();
|
|
86
87
|
this.app = (0, fastify_1.default)();
|
|
87
88
|
// this.app.setValidatorCompiler(() => () => true);
|
|
@@ -96,12 +97,12 @@ class AvleonApplication {
|
|
|
96
97
|
return AvleonApplication.instance;
|
|
97
98
|
}
|
|
98
99
|
isDevelopment() {
|
|
99
|
-
return environment_variables_1.env[
|
|
100
|
+
return environment_variables_1.env["NODE_ENV"] == "development";
|
|
100
101
|
}
|
|
101
102
|
async initSwagger(options) {
|
|
102
103
|
const { routePrefix } = options, restOptions = __rest(options, ["routePrefix"]);
|
|
103
104
|
this.app.register(swagger_1.default, {
|
|
104
|
-
openapi: Object.assign({ openapi:
|
|
105
|
+
openapi: Object.assign({ openapi: "3.0.0" }, restOptions),
|
|
105
106
|
});
|
|
106
107
|
const rPrefix = routePrefix ? routePrefix : "/docs";
|
|
107
108
|
//import fastifyApiReference from "@scalar/fastify-api-reference";
|
|
@@ -109,12 +110,12 @@ class AvleonApplication {
|
|
|
109
110
|
routePrefix: rPrefix,
|
|
110
111
|
configuration: {
|
|
111
112
|
metaData: {
|
|
112
|
-
title:
|
|
113
|
-
ogTitle:
|
|
113
|
+
title: "Avleon Api",
|
|
114
|
+
ogTitle: "Avleon",
|
|
114
115
|
},
|
|
115
|
-
theme:
|
|
116
|
-
favicon:
|
|
117
|
-
}
|
|
116
|
+
theme: "kepler",
|
|
117
|
+
favicon: "/static/favicon.png",
|
|
118
|
+
},
|
|
118
119
|
});
|
|
119
120
|
}
|
|
120
121
|
async useSwagger(options) {
|
|
@@ -146,6 +147,13 @@ class AvleonApplication {
|
|
|
146
147
|
let classMiddlewares = [];
|
|
147
148
|
const tag = ctrl.constructor.name.replace("Controller", "");
|
|
148
149
|
const swaggerControllerMeta = Reflect.getMetadata("controller:openapi", ctrl.constructor) || {};
|
|
150
|
+
const authClsMeata = Reflect.getMetadata(container_1.AUTHORIZATION_META_KEY, ctrl.constructor) || { authorize: false, options: undefined };
|
|
151
|
+
if (authClsMeata.authorize && this.authorizeMiddleware) {
|
|
152
|
+
this.app.addHook("preHandler", (req, res) => {
|
|
153
|
+
return this.authorizeMiddleware.authorize(req);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
console.log("ClassMiddlware:", tag + ":", authClsMeata);
|
|
149
157
|
try {
|
|
150
158
|
for (var _d = true, methods_1 = __asyncValues(methods), methods_1_1; methods_1_1 = await methods_1.next(), _a = methods_1_1.done, !_a; _d = true) {
|
|
151
159
|
_c = methods_1_1.value;
|
|
@@ -165,6 +173,17 @@ class AvleonApplication {
|
|
|
165
173
|
const classMiddlewares = this.executeMiddlewares(ctrl, method);
|
|
166
174
|
// handle openapi data
|
|
167
175
|
const swaggerMeta = Reflect.getMetadata("route:openapi", prototype, method) || {};
|
|
176
|
+
const authClsMethodMeata = Reflect.getMetadata(container_1.AUTHORIZATION_META_KEY, ctrl.constructor, method) || { authorize: false, options: undefined };
|
|
177
|
+
console.log(tag, ":", method, authClsMethodMeata);
|
|
178
|
+
// if (authClsMethodMeata.authorize && this.authorizeMiddleware) {
|
|
179
|
+
// this.app.addHook('preHandler', async (req, res) => {
|
|
180
|
+
// if (res.sent) return;
|
|
181
|
+
// console.log(this.authorizeMiddleware)
|
|
182
|
+
// const cls = container.get(this.authorizeMiddleware) as any;
|
|
183
|
+
// console.log(cls)
|
|
184
|
+
// cls.authorize(req);
|
|
185
|
+
// })
|
|
186
|
+
// }
|
|
168
187
|
const allMeta = this._processMeta(prototype, method);
|
|
169
188
|
const routePath = methodmetaOptions.path == "" ? "/" : methodmetaOptions.path;
|
|
170
189
|
this.app.route({
|
|
@@ -173,10 +192,16 @@ class AvleonApplication {
|
|
|
173
192
|
schema: Object.assign(Object.assign(Object.assign({}, swaggerControllerMeta), swaggerMeta), { tags: [tag] }),
|
|
174
193
|
handler: async (req, res) => {
|
|
175
194
|
let reqClone = req;
|
|
195
|
+
if (authClsMethodMeata.authorize && this.authorizeMiddleware) {
|
|
196
|
+
const cls = container_1.default.get(this.authorizeMiddleware);
|
|
197
|
+
await cls.authorize(reqClone, authClsMethodMeata.options);
|
|
198
|
+
if (res.sent)
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
176
201
|
if (classMiddlewares.length > 0) {
|
|
177
202
|
for (let m of classMiddlewares) {
|
|
178
203
|
const cls = typedi_1.default.get(m.constructor);
|
|
179
|
-
reqClone = await cls.invoke(reqClone, res);
|
|
204
|
+
reqClone = (await cls.invoke(reqClone, res));
|
|
180
205
|
if (res.sent)
|
|
181
206
|
return;
|
|
182
207
|
}
|
|
@@ -297,11 +322,24 @@ class AvleonApplication {
|
|
|
297
322
|
this.app.addHook("preHandler", cls.invoke);
|
|
298
323
|
}
|
|
299
324
|
}
|
|
325
|
+
useAuthoriztion(middleware) {
|
|
326
|
+
this.authorizeMiddleware = middleware;
|
|
327
|
+
}
|
|
300
328
|
_handleError(error) {
|
|
301
329
|
if (error instanceof exceptions_1.BaseHttpException) {
|
|
302
|
-
return {
|
|
330
|
+
return {
|
|
331
|
+
code: error.code,
|
|
332
|
+
error: error.name,
|
|
333
|
+
message: (0, helpers_1.isValidJsonString)(error.message)
|
|
334
|
+
? JSON.parse(error.message)
|
|
335
|
+
: error.message,
|
|
336
|
+
};
|
|
303
337
|
}
|
|
304
|
-
return {
|
|
338
|
+
return {
|
|
339
|
+
code: 500,
|
|
340
|
+
error: "INTERNALERROR",
|
|
341
|
+
message: error.message ? error.message : "Something going wrong.",
|
|
342
|
+
};
|
|
305
343
|
}
|
|
306
344
|
async mapRoute(method, path = "", fn) {
|
|
307
345
|
await this.mapFn(fn); // Assuming mapFn is needed for all methods
|
|
@@ -328,7 +366,7 @@ class AvleonApplication {
|
|
|
328
366
|
this.rMap.set(routeKey, {
|
|
329
367
|
handler: fn,
|
|
330
368
|
middlewares: [],
|
|
331
|
-
schema: {}
|
|
369
|
+
schema: {},
|
|
332
370
|
});
|
|
333
371
|
this.mapFn(fn);
|
|
334
372
|
const route = {
|
|
@@ -367,16 +405,18 @@ class AvleonApplication {
|
|
|
367
405
|
mapDelete(path = "", fn) {
|
|
368
406
|
return this._routeHandler(path, "DELETE", fn);
|
|
369
407
|
}
|
|
408
|
+
useStaticFiles(options = { path: undefined, prefix: undefined }) {
|
|
409
|
+
this.app.register(require("@fastify/static"), {
|
|
410
|
+
root: options.path ? options.path : path_1.default.join(process.cwd(), "public"),
|
|
411
|
+
prefix: options.prefix ? options.prefix : "/static/",
|
|
412
|
+
});
|
|
413
|
+
}
|
|
370
414
|
async run(port = 4000) {
|
|
371
415
|
if (this.alreadyRun)
|
|
372
416
|
throw new system_exception_1.SystemUseError("App already running");
|
|
373
417
|
this.alreadyRun = true;
|
|
374
418
|
if (AvleonApplication.buildOptions.database) {
|
|
375
419
|
}
|
|
376
|
-
this.app.register(require('@fastify/static'), {
|
|
377
|
-
root: path_1.default.join(process.cwd(), 'public'),
|
|
378
|
-
prefix: '/static/'
|
|
379
|
-
});
|
|
380
420
|
//this.app.swagger();
|
|
381
421
|
if (this.hasSwagger) {
|
|
382
422
|
await this.initSwagger(this.globalSwaggerOptions);
|
|
@@ -401,7 +441,11 @@ class AvleonApplication {
|
|
|
401
441
|
this.app.setErrorHandler(async (error, req, res) => {
|
|
402
442
|
const handledErr = this._handleError(error);
|
|
403
443
|
if (error instanceof exceptions_1.ValidationErrorException) {
|
|
404
|
-
return res.status(handledErr.code).send({
|
|
444
|
+
return res.status(handledErr.code).send({
|
|
445
|
+
code: handledErr.code,
|
|
446
|
+
error: handledErr.error,
|
|
447
|
+
errors: handledErr.message,
|
|
448
|
+
});
|
|
405
449
|
}
|
|
406
450
|
return res.status(handledErr.code).send(handledErr);
|
|
407
451
|
});
|
|
@@ -409,6 +453,9 @@ class AvleonApplication {
|
|
|
409
453
|
await this.app.listen({ port });
|
|
410
454
|
console.log(`Application running on port: 0.0.0.0:${port}`);
|
|
411
455
|
}
|
|
456
|
+
getTestApp(app) {
|
|
457
|
+
return this.app;
|
|
458
|
+
}
|
|
412
459
|
}
|
|
413
460
|
AvleonApplication.buildOptions = {};
|
|
414
461
|
// Applciation Builder
|
|
@@ -423,6 +470,12 @@ class Builder {
|
|
|
423
470
|
}
|
|
424
471
|
return Builder.instance;
|
|
425
472
|
}
|
|
473
|
+
static creatTestAppBilder() {
|
|
474
|
+
if (!Builder.instance) {
|
|
475
|
+
Builder.instance = new Builder();
|
|
476
|
+
}
|
|
477
|
+
return Builder.instance;
|
|
478
|
+
}
|
|
426
479
|
async registerPlugin(plugin, options) {
|
|
427
480
|
container_1.default.set(plugin, plugin.prototype);
|
|
428
481
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export * from "./map-types";
|
|
|
8
8
|
export * from "./response";
|
|
9
9
|
export * from "./exceptions";
|
|
10
10
|
export * from "./validator-extend";
|
|
11
|
+
export * from "./validation";
|
|
11
12
|
export * from "./environment-variables";
|
|
12
13
|
export * from "./collection";
|
|
13
14
|
export * from "./queue";
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ __exportStar(require("./map-types"), exports);
|
|
|
31
31
|
__exportStar(require("./response"), exports);
|
|
32
32
|
__exportStar(require("./exceptions"), exports);
|
|
33
33
|
__exportStar(require("./validator-extend"), exports);
|
|
34
|
+
__exportStar(require("./validation"), exports);
|
|
34
35
|
__exportStar(require("./environment-variables"), exports);
|
|
35
36
|
__exportStar(require("./collection"), exports);
|
|
36
37
|
__exportStar(require("./queue"), exports);
|
package/dist/middleware.d.ts
CHANGED
|
@@ -3,8 +3,22 @@ import { HttpException } from "./exceptions";
|
|
|
3
3
|
export declare abstract class AppMiddleware {
|
|
4
4
|
abstract invoke(req: IRequest, res?: IResponse): Promise<IRequest | HttpException>;
|
|
5
5
|
}
|
|
6
|
+
export type AuthHandler = (req: IRequest, roles?: string[]) => Promise<IRequest | HttpException>;
|
|
6
7
|
export type Constructor<T> = {
|
|
7
8
|
new (...args: any[]): T;
|
|
8
9
|
};
|
|
10
|
+
export declare abstract class AuthorizeMiddleware {
|
|
11
|
+
abstract authorize(roles: string[]): (req: IRequest, res?: IResponse) => IRequest | Promise<IRequest>;
|
|
12
|
+
}
|
|
13
|
+
export type AuthReturnTypes = IRequest | Promise<IRequest>;
|
|
14
|
+
interface AuthorizeClass {
|
|
15
|
+
authorize(req: IRequest, options?: any): AuthReturnTypes;
|
|
16
|
+
}
|
|
17
|
+
export declare function Authorize(target: {
|
|
18
|
+
new (...args: any[]): AuthorizeClass;
|
|
19
|
+
}): void;
|
|
20
|
+
export declare function Authorized(): ClassDecorator & MethodDecorator;
|
|
21
|
+
export declare function Authorized(options?: any): ClassDecorator & MethodDecorator;
|
|
9
22
|
export declare function Middleware(target: Constructor<AppMiddleware>): void;
|
|
10
23
|
export declare function UseMiddleware<T extends AppMiddleware | (new (...args: any[]) => AppMiddleware)>(options: T | T[]): MethodDecorator & ClassDecorator;
|
|
24
|
+
export {};
|
package/dist/middleware.js
CHANGED
|
@@ -1,12 +1,40 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AppMiddleware = void 0;
|
|
3
|
+
exports.AuthorizeMiddleware = exports.AppMiddleware = void 0;
|
|
4
|
+
exports.Authorize = Authorize;
|
|
5
|
+
exports.Authorized = Authorized;
|
|
4
6
|
exports.Middleware = Middleware;
|
|
5
7
|
exports.UseMiddleware = UseMiddleware;
|
|
6
8
|
const typedi_1 = require("typedi");
|
|
9
|
+
const container_1 = require("./container");
|
|
7
10
|
class AppMiddleware {
|
|
8
11
|
}
|
|
9
12
|
exports.AppMiddleware = AppMiddleware;
|
|
13
|
+
class AuthorizeMiddleware {
|
|
14
|
+
}
|
|
15
|
+
exports.AuthorizeMiddleware = AuthorizeMiddleware;
|
|
16
|
+
function Authorize(target) {
|
|
17
|
+
if (typeof target.prototype.authorize !== "function") {
|
|
18
|
+
throw new Error(`Class "${target.name}" must implement an "authorize" method.`);
|
|
19
|
+
}
|
|
20
|
+
(0, typedi_1.Service)()(target);
|
|
21
|
+
}
|
|
22
|
+
function Authorized(options = {}) {
|
|
23
|
+
return function (target, propertyKey, descriptor) {
|
|
24
|
+
if (propertyKey && descriptor) {
|
|
25
|
+
Reflect.defineMetadata(container_1.AUTHORIZATION_META_KEY, { authorize: true, options }, target.constructor, propertyKey);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
Reflect.defineMetadata(container_1.AUTHORIZATION_META_KEY, { authorize: true, options }, target);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function Middleware(target) {
|
|
33
|
+
if (typeof target.prototype.invoke !== "function") {
|
|
34
|
+
throw new Error(`Class "${target.name}" must implement an "invoke" method.`);
|
|
35
|
+
}
|
|
36
|
+
(0, typedi_1.Service)()(target);
|
|
37
|
+
}
|
|
10
38
|
// export function CurrentUser(): ParameterDecorator {
|
|
11
39
|
// return (target, propertyKey, parameterIndex) => {
|
|
12
40
|
// const existingMetadata =
|
|
@@ -15,12 +43,6 @@ exports.AppMiddleware = AppMiddleware;
|
|
|
15
43
|
// Reflect.defineMetadata("currentUser:params", existingMetadata, target, propertyKey!);
|
|
16
44
|
// };
|
|
17
45
|
// }
|
|
18
|
-
function Middleware(target) {
|
|
19
|
-
if (typeof target.prototype.invoke !== "function") {
|
|
20
|
-
throw new Error(`Class "${target.name}" must implement an "invoke" method.`);
|
|
21
|
-
}
|
|
22
|
-
(0, typedi_1.Service)()(target);
|
|
23
|
-
}
|
|
24
46
|
function UseMiddleware(options) {
|
|
25
47
|
return function (target, propertyKey, descriptor) {
|
|
26
48
|
const normalizeMiddleware = (middleware) => typeof middleware === "function" ? new middleware() : middleware;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type BaseRule = {
|
|
2
|
+
required?: boolean;
|
|
3
|
+
optional?: boolean;
|
|
4
|
+
message?: string;
|
|
5
|
+
};
|
|
6
|
+
type StringRule = BaseRule & {
|
|
7
|
+
type: "string";
|
|
8
|
+
};
|
|
9
|
+
type NumberRule = BaseRule & {
|
|
10
|
+
type: "number";
|
|
11
|
+
min?: number;
|
|
12
|
+
max?: number;
|
|
13
|
+
exact?: number;
|
|
14
|
+
};
|
|
15
|
+
type BooleanRule = BaseRule & {
|
|
16
|
+
type: "boolean";
|
|
17
|
+
};
|
|
18
|
+
export type ValidationRule = StringRule | NumberRule | BooleanRule;
|
|
19
|
+
export type ValidationProps = {
|
|
20
|
+
[key: string]: ValidationRule;
|
|
21
|
+
};
|
|
22
|
+
export declare function validateOrThrow<T extends {}>(obj: T, rules: ValidationProps): any;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateOrThrow = validateOrThrow;
|
|
4
|
+
const exceptions_1 = require("./exceptions");
|
|
5
|
+
class PValidationRule {
|
|
6
|
+
constructor(name, type, message) {
|
|
7
|
+
this.name = name;
|
|
8
|
+
this.type = type;
|
|
9
|
+
this.message = message;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
class Validator {
|
|
13
|
+
constructor(obj) {
|
|
14
|
+
this.rules = [];
|
|
15
|
+
this.init(obj);
|
|
16
|
+
}
|
|
17
|
+
init(obj) {
|
|
18
|
+
Object.keys(obj).forEach((key) => {
|
|
19
|
+
const rule = obj[key];
|
|
20
|
+
this.rules.push(new PValidationRule(key, rule.type, rule.message));
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
validate(obj) {
|
|
24
|
+
const erors = [];
|
|
25
|
+
this.rules.forEach((k) => {
|
|
26
|
+
const r = Object.keys(obj).find((key) => key == k.name);
|
|
27
|
+
let messages = [];
|
|
28
|
+
if (!r || obj[r] == undefined || obj[r] == "") {
|
|
29
|
+
messages.push({
|
|
30
|
+
constraint: "required",
|
|
31
|
+
message: k.name + " is required",
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (k.type == "string" && typeof obj[k.name] != "string") {
|
|
35
|
+
messages.push({
|
|
36
|
+
constraint: "type",
|
|
37
|
+
message: `${k.name} must be type ${k.type}`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (k.type == "number" && !parseInt(obj[k.name])) {
|
|
41
|
+
messages.push({
|
|
42
|
+
constraint: "type",
|
|
43
|
+
message: `${k.name} must be type ${k.type}`,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (k.type == "number") {
|
|
47
|
+
obj[k.name] = parseInt(obj[k.name]);
|
|
48
|
+
}
|
|
49
|
+
if (k.type == "boolean" && !isBool(obj[k.name])) {
|
|
50
|
+
messages.push({
|
|
51
|
+
constraint: "type",
|
|
52
|
+
message: `${k.name} must be type ${k.type}`,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (k.type == "boolean") {
|
|
56
|
+
obj[k.name] = parseBoolean(obj[k.name]);
|
|
57
|
+
}
|
|
58
|
+
if (messages.length > 0) {
|
|
59
|
+
erors.push({
|
|
60
|
+
path: k.name,
|
|
61
|
+
messages: messages,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return [erors, obj];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const isBool = (val) => {
|
|
69
|
+
if (typeof val == "boolean")
|
|
70
|
+
return true;
|
|
71
|
+
if (parseInt(val) == 0 || parseInt(val) == 1)
|
|
72
|
+
return true;
|
|
73
|
+
if (val == "true" || val == "false")
|
|
74
|
+
return true;
|
|
75
|
+
return false;
|
|
76
|
+
};
|
|
77
|
+
const parseBoolean = (val) => {
|
|
78
|
+
if (typeof val === "boolean")
|
|
79
|
+
return val;
|
|
80
|
+
// if (typeof val === "number") {
|
|
81
|
+
// return val !== 0; // Common convention: 0 → false, any other number → true
|
|
82
|
+
// }
|
|
83
|
+
if (parseInt(val) == 1)
|
|
84
|
+
return true;
|
|
85
|
+
if (typeof val === "string") {
|
|
86
|
+
const normalized = val.trim().toLowerCase();
|
|
87
|
+
return normalized === "true";
|
|
88
|
+
}
|
|
89
|
+
return false; // Default for unsupported types (null, undefined, objects, etc.)
|
|
90
|
+
};
|
|
91
|
+
function validateOrThrow(obj, rules) {
|
|
92
|
+
const valid = new Validator(rules);
|
|
93
|
+
const errors = valid.validate(obj);
|
|
94
|
+
if (errors[0].length > 0) {
|
|
95
|
+
throw new exceptions_1.BadRequestException(errors[0]);
|
|
96
|
+
}
|
|
97
|
+
return errors[1];
|
|
98
|
+
}
|