@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 CHANGED
@@ -1,4 +1,4 @@
1
1
  # avleon-core
2
2
 
3
3
 
4
- # Api (V0.0.)
4
+ # Api (V0.0.1)
@@ -1,9 +1,7 @@
1
1
  export type CurrentUser = {};
2
- export declare abstract class Authetication {
3
- abstract login(): void;
4
- abstract register(): void;
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;
@@ -1,11 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Authetication = void 0;
3
+ exports.BaseAuthetication = void 0;
4
4
  exports.Authorized = Authorized;
5
5
  exports.CurrentUser = CurrentUser;
6
- class Authetication {
6
+ class BaseAuthetication {
7
7
  }
8
- exports.Authetication = Authetication;
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 ConfigClass {
22
- invoke(env: Environment): object;
21
+ export interface IConfig {
22
+ config(env: Environment): object;
23
23
  }
24
- export declare function Config(target: {
25
- new (...args: any[]): ConfigClass;
24
+ export declare function Config<T extends IConfig>(target: {
25
+ new (): T;
26
26
  }): void;
27
- export declare function GetConfig<T extends ConfigClass>(ConfigClass: {
28
- new (...args: any[]): T;
29
- }): ReturnType<T["invoke"]>;
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.invoke !== "function") {
8
- throw new Error(`Class "${target.name}" must implement an "invoke" method.`);
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 ConfigCtor = Reflect.getMetadata(CONFIG_METADATA_KEY, ConfigClass);
14
- if (!ConfigCtor) {
15
- throw new Error(`Class "${ConfigClass.name}" is not decorated with @Config.`);
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
- const instance = new ConfigCtor();
18
- return instance.invoke(process.env);
20
+ return instance.config(process.env);
19
21
  }
@@ -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();
@@ -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(path?: string): ClassDecorator;
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
@@ -31,8 +31,22 @@ function createControllerDecorator(type = "web") {
31
31
  };
32
32
  }
33
33
  function ApiController(pathOrOptions = "/", mayBeOptions) {
34
- if (mayBeOptions) {
35
- return createControllerDecorator("api")(pathOrOptions, mayBeOptions);
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")); // Use promises for asynchronous file operations
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['NODE_ENV'] == "development";
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: '3.0.0' }, restOptions)
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: 'Avleon Api',
113
- ogTitle: 'Avleon'
113
+ title: "Avleon Api",
114
+ ogTitle: "Avleon",
114
115
  },
115
- theme: 'kepler',
116
- favicon: '/static/favicon.png'
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 { code: error.code, error: error.name, message: (0, helpers_1.isValidJsonString)(error.message) ? JSON.parse(error.message) : error.message };
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 { code: 500, error: 'INTERNALERROR', message: error.message ? error.message : "Something going wrong." };
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({ code: handledErr.code, error: handledErr.error, errors: handledErr.message });
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);
@@ -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 {};
@@ -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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avleon/core",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "scripts": {