@avleon/core 0.0.6 → 0.0.8

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/config.d.ts CHANGED
@@ -1,29 +1,10 @@
1
- export interface IDBConfig {
2
- type: string;
3
- host: string;
4
- port: number | string;
5
- username: string;
6
- password: string;
7
- database: string;
8
- synchronize: boolean;
9
- logging: boolean;
10
- entities: any[];
11
- migrations?: string[];
12
- subscribers?: string[];
1
+ import { Constructable } from "typedi";
2
+ import { Environment } from "./environment-variables";
3
+ export interface IConfig<T = any> {
4
+ config(env: Environment): T;
13
5
  }
14
- export interface Environment extends NodeJS.ProcessEnv {
15
- [key: string]: string | undefined;
6
+ export declare function Config<T extends IConfig>(target: Constructable<T>): void;
7
+ export declare class AppConfig {
8
+ get<T extends IConfig<R>, R>(configClass: Constructable<T>): R;
16
9
  }
17
- export interface IAppConfig {
18
- apiKey: string;
19
- timezone: string;
20
- }
21
- export interface IConfig {
22
- config(env: Environment): object;
23
- }
24
- export declare function Config<T extends IConfig>(target: {
25
- new (): T;
26
- }): void;
27
- export declare function GetConfig<T extends IConfig>(ConfigClass: {
28
- new (): T;
29
- }): ReturnType<T["config"]>;
10
+ export declare function GetConfig<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>['config']>>(ConfigClass: Constructable<T>): R;
package/dist/config.js CHANGED
@@ -1,21 +1,27 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AppConfig = void 0;
3
4
  exports.Config = Config;
4
5
  exports.GetConfig = GetConfig;
5
- const CONFIG_METADATA_KEY = Symbol("config");
6
- const configInstances = new Map();
6
+ const typedi_1 = require("typedi");
7
+ const environment_variables_1 = require("./environment-variables");
7
8
  function Config(target) {
8
- if (typeof target.prototype.config !== "function") {
9
- throw new Error(`Class "${target.name}" must implement a "config" method.`);
9
+ typedi_1.Container.set({ id: target, type: target });
10
+ }
11
+ class AppConfig {
12
+ get(configClass) {
13
+ const instance = typedi_1.Container.get(configClass);
14
+ if (!instance) {
15
+ throw new Error(`Configuration for ${configClass.name} not found.`);
16
+ }
17
+ return instance.config(new environment_variables_1.Environment());
10
18
  }
11
- Reflect.defineMetadata(CONFIG_METADATA_KEY, target, target);
12
- // Auto-instantiate and store the config instance
13
- configInstances.set(target.name, new target());
14
19
  }
20
+ exports.AppConfig = AppConfig;
15
21
  function GetConfig(ConfigClass) {
16
- const instance = configInstances.get(ConfigClass.name);
22
+ const instance = typedi_1.Container.get(ConfigClass);
17
23
  if (!instance) {
18
24
  throw new Error(`Class "${ConfigClass.name}" is not registered as a config.`);
19
25
  }
20
- return instance.config(process.env);
26
+ return instance.config(new environment_variables_1.Environment());
21
27
  }
@@ -1,3 +1,5 @@
1
- export declare const e: Record<string, string>;
2
- export type Env = typeof e;
3
- export declare const env: Env;
1
+ export declare class Environment {
2
+ private parseEnvFile;
3
+ get<T = any>(key: string): T;
4
+ getAll<T = any>(): T;
5
+ }
@@ -1,33 +1,47 @@
1
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
+ };
2
8
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
9
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
10
  };
5
11
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.env = exports.e = void 0;
12
+ exports.Environment = void 0;
7
13
  const dotenv_1 = __importDefault(require("dotenv"));
8
14
  const path_1 = __importDefault(require("path"));
9
15
  const fs_1 = __importDefault(require("fs"));
16
+ const typedi_1 = require("typedi");
17
+ const system_exception_1 = require("./exceptions/system-exception");
10
18
  // Load environment variables
11
19
  dotenv_1.default.config({ path: path_1.default.join(process.cwd(), ".env") });
12
- // Read the .env file and infer keys dynamically
13
- const envFilePath = path_1.default.join(process.cwd(), ".env");
14
- const envContents = fs_1.default.readFileSync(envFilePath, "utf-8");
15
- // Parse .env file manually
16
- const parsedEnv = Object.fromEntries(envContents
17
- .split("\n")
18
- .filter((line) => line.trim() && !line.startsWith("#")) // Ignore empty lines and comments
19
- .map((line) => {
20
- const [key, ...valueParts] = line.split("="); // Split key and value
21
- return [key.trim(), valueParts.join("=").trim()]; // Handle values with `=`
22
- }));
23
- const inferType = (value) => {
24
- if (!isNaN(Number(value)))
25
- return Number(value);
26
- if (value.toLowerCase() === "true")
27
- return true;
28
- if (value.toLowerCase() === "false")
29
- return false;
30
- return value;
20
+ let Environment = class Environment {
21
+ parseEnvFile(filePath) {
22
+ try {
23
+ const fileContent = fs_1.default.readFileSync(filePath, 'utf8');
24
+ const parsedEnv = dotenv_1.default.parse(fileContent);
25
+ return Object.assign(Object.assign({}, parsedEnv), process.env);
26
+ }
27
+ catch (error) {
28
+ console.error(`Error parsing .env file: ${error}`);
29
+ return {};
30
+ }
31
+ }
32
+ get(key) {
33
+ const parsedEnv = this.parseEnvFile(path_1.default.join(process.cwd(), '.env'));
34
+ if (!Object(parsedEnv).hasOwnProperty(key)) {
35
+ throw new system_exception_1.EnvironmentVariableNotFound(key);
36
+ }
37
+ return parsedEnv[key];
38
+ }
39
+ getAll() {
40
+ const parsedEnv = this.parseEnvFile(path_1.default.join(process.cwd(), '.env'));
41
+ return parsedEnv;
42
+ }
31
43
  };
32
- exports.e = parsedEnv;
33
- exports.env = exports.e;
44
+ exports.Environment = Environment;
45
+ exports.Environment = Environment = __decorate([
46
+ (0, typedi_1.Service)()
47
+ ], Environment);
@@ -11,3 +11,6 @@ export declare class SystemUseError extends Error {
11
11
  export declare class DuplicateRouteException extends Error {
12
12
  constructor(params: IRouteDuplicateErr);
13
13
  }
14
+ export declare class EnvironmentVariableNotFound extends Error {
15
+ constructor(key: string);
16
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DuplicateRouteException = exports.SystemUseError = void 0;
3
+ exports.EnvironmentVariableNotFound = exports.DuplicateRouteException = exports.SystemUseError = void 0;
4
4
  class SystemUseError extends Error {
5
5
  constructor(message) {
6
6
  super(message);
@@ -16,3 +16,9 @@ class DuplicateRouteException extends Error {
16
16
  }
17
17
  }
18
18
  exports.DuplicateRouteException = DuplicateRouteException;
19
+ class EnvironmentVariableNotFound extends Error {
20
+ constructor(key) {
21
+ super(`${key} not found in environment variables.`);
22
+ }
23
+ }
24
+ exports.EnvironmentVariableNotFound = EnvironmentVariableNotFound;
package/dist/icore.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  import { FastifyInstance, FastifyReply, FastifyRequest, HookHandlerDoneFunction } from "fastify";
2
+ import { Constructable } from "typedi";
2
3
  import { Constructor } from "./helpers";
3
4
  import { PathLike } from "fs";
4
5
  import { DataSourceOptions } from "typeorm";
5
6
  import { AppMiddleware } from "./middleware";
6
7
  import { OpenApiOptions, OpenApiUiOptions } from "./openapi";
8
+ import { IConfig } from "./config";
7
9
  export type FuncRoute = {
8
10
  handler: any;
9
11
  middlewares?: any[];
@@ -55,10 +57,12 @@ declare class AvleonApplication {
55
57
  private globalSwaggerOptions;
56
58
  private controllers;
57
59
  private authorizeMiddleware?;
60
+ private appConfig;
58
61
  private constructor();
59
62
  static getInternalApp(buildOptions: any): AvleonApplication;
60
63
  isDevelopment(): boolean;
61
64
  private initSwagger;
65
+ useOpenApi<T extends IConfig<R>, R = ReturnType<InstanceType<Constructable<T>>['config']>>(ConfigClass: Constructable<T>, modifyConfig?: (config: R) => R): void;
62
66
  useSwagger(options: OpenApiUiOptions): Promise<void>;
63
67
  private handleMiddlewares;
64
68
  private executeMiddlewares;
@@ -104,7 +108,7 @@ export declare class Builder {
104
108
  private dataSource?;
105
109
  private constructor();
106
110
  static createAppBuilder(): Builder;
107
- static creatTestAppBilder(): Builder;
111
+ static creatTestApplication(): Builder;
108
112
  registerPlugin<T extends Function, S extends {}>(plugin: T, options: S): Promise<void>;
109
113
  addDataSource(config: DataSourceOptions): Promise<void>;
110
114
  build(): AvleonApplication;
package/dist/icore.js CHANGED
@@ -65,7 +65,7 @@ const system_exception_1 = require("./exceptions/system-exception");
65
65
  const fs_1 = require("fs");
66
66
  const exceptions_1 = require("./exceptions");
67
67
  const swagger_1 = __importDefault(require("@fastify/swagger"));
68
- const fastify_api_reference_1 = __importDefault(require("@scalar/fastify-api-reference"));
68
+ const config_1 = require("./config");
69
69
  const environment_variables_1 = require("./environment-variables");
70
70
  const isTsNode = process.env.TS_NODE_DEV ||
71
71
  process.env.TS_NODE_PROJECT ||
@@ -85,6 +85,7 @@ class AvleonApplication {
85
85
  this.authorizeMiddleware = undefined;
86
86
  this.metaCache = new Map();
87
87
  this.app = (0, fastify_1.default)();
88
+ this.appConfig = new config_1.AppConfig();
88
89
  // this.app.setValidatorCompiler(() => () => true);
89
90
  }
90
91
  static getInternalApp(buildOptions) {
@@ -97,16 +98,20 @@ class AvleonApplication {
97
98
  return AvleonApplication.instance;
98
99
  }
99
100
  isDevelopment() {
100
- return environment_variables_1.env["NODE_ENV"] == "development";
101
+ const env = container_1.default.get(environment_variables_1.Environment);
102
+ return env.get("NODE_ENV") == "development";
101
103
  }
102
104
  async initSwagger(options) {
103
- const { routePrefix } = options, restOptions = __rest(options, ["routePrefix"]);
105
+ const { routePrefix, logo, theme } = options, restOptions = __rest(options, ["routePrefix", "logo", "theme"]);
104
106
  this.app.register(swagger_1.default, {
105
107
  openapi: Object.assign({ openapi: "3.0.0" }, restOptions),
106
108
  });
107
109
  const rPrefix = routePrefix ? routePrefix : "/docs";
108
110
  //import fastifyApiReference from "@scalar/fastify-api-reference";
109
- await this.app.register(fastify_api_reference_1.default, {
111
+ //const fastifyApiReference = await require("@scalar/fastify-api-reference");
112
+ await this.app.register(require("@fastify/swagger-ui"), {
113
+ logo: logo ? logo : null,
114
+ theme: theme ? theme : {},
110
115
  routePrefix: rPrefix,
111
116
  configuration: {
112
117
  metaData: {
@@ -118,6 +123,17 @@ class AvleonApplication {
118
123
  },
119
124
  });
120
125
  }
126
+ useOpenApi(ConfigClass, modifyConfig) {
127
+ const openApiConfig = this.appConfig.get(ConfigClass);
128
+ if (modifyConfig) {
129
+ const modifiedConfig = modifyConfig(openApiConfig);
130
+ this.globalSwaggerOptions = modifiedConfig;
131
+ }
132
+ else {
133
+ this.globalSwaggerOptions = openApiConfig;
134
+ }
135
+ this.hasSwagger = true;
136
+ }
121
137
  async useSwagger(options) {
122
138
  this.hasSwagger = true;
123
139
  this.globalSwaggerOptions = options;
@@ -153,7 +169,6 @@ class AvleonApplication {
153
169
  return this.authorizeMiddleware.authorize(req);
154
170
  });
155
171
  }
156
- console.log("ClassMiddlware:", tag + ":", authClsMeata);
157
172
  try {
158
173
  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) {
159
174
  _c = methods_1_1.value;
@@ -174,16 +189,6 @@ class AvleonApplication {
174
189
  // handle openapi data
175
190
  const swaggerMeta = Reflect.getMetadata("route:openapi", prototype, method) || {};
176
191
  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
- // }
187
192
  const allMeta = this._processMeta(prototype, method);
188
193
  const routePath = methodmetaOptions.path == "" ? "/" : methodmetaOptions.path;
189
194
  this.app.route({
@@ -306,12 +311,10 @@ class AvleonApplication {
306
311
  }
307
312
  }
308
313
  async handleRoute(args) {
309
- console.log(args);
310
314
  }
311
315
  async mapFn(fn) {
312
316
  const original = fn;
313
317
  fn = function () {
314
- console.log(arguments);
315
318
  };
316
319
  return fn;
317
320
  }
@@ -451,7 +454,7 @@ class AvleonApplication {
451
454
  });
452
455
  await this.app.ready();
453
456
  await this.app.listen({ port });
454
- console.log(`Application running on port: 0.0.0.0:${port}`);
457
+ console.log(`Application running on http://127.0.0.1:${port}`);
455
458
  }
456
459
  getTestApp(app) {
457
460
  return this.app;
@@ -470,7 +473,7 @@ class Builder {
470
473
  }
471
474
  return Builder.instance;
472
475
  }
473
- static creatTestAppBilder() {
476
+ static creatTestApplication() {
474
477
  if (!Builder.instance) {
475
478
  Builder.instance = new Builder();
476
479
  }
@@ -495,7 +498,6 @@ class Builder {
495
498
  await datasource.initialize();
496
499
  }
497
500
  catch (error) {
498
- console.log(error);
499
501
  console.error("Database Initialize Error:", error.message);
500
502
  }
501
503
  }
package/dist/openapi.d.ts CHANGED
@@ -28,6 +28,8 @@ interface ServerVariableObject {
28
28
  description?: string;
29
29
  }
30
30
  export type OpenApiUiOptions = {
31
+ logo?: any;
32
+ theme?: any;
31
33
  openapi?: string;
32
34
  routePrefix?: string;
33
35
  info?: InfoObject;
@@ -4,6 +4,7 @@ exports.generateSwaggerSchema = generateSwaggerSchema;
4
4
  function generateSwaggerSchema(classType) {
5
5
  const { getMetadataStorage } = require("class-validator");
6
6
  const { plainToInstance } = require("class-transformer");
7
+ //const { isArray } = require("lodash"); // Add lodash for array check
7
8
  const metadataStorage = getMetadataStorage();
8
9
  const validationMetadata = metadataStorage.getTargetValidationMetadatas(classType, "", true);
9
10
  const schema = {
@@ -12,18 +13,136 @@ function generateSwaggerSchema(classType) {
12
13
  required: [],
13
14
  };
14
15
  validationMetadata.forEach((meta) => {
16
+ var _a, _b;
15
17
  const propertyName = meta.propertyName;
16
18
  // Infer the type dynamically using Reflect metadata
17
19
  const propertyType = Reflect.getMetadata("design:type", classType.prototype, propertyName);
18
- schema.properties[propertyName] = {
19
- type: (propertyType === null || propertyType === void 0 ? void 0 : propertyType.name.toLowerCase()) || "string", // Default to string if type cannot be inferred
20
- };
21
- if (meta.name === "isNotEmpty") {
22
- schema.required.push(propertyName);
23
- }
24
- if (meta.name === "minLength") {
25
- schema.properties[propertyName].minLength = meta.constraints[0];
20
+ let swaggerProperty = {};
21
+ switch (propertyType) {
22
+ case String:
23
+ swaggerProperty.type = "string";
24
+ break;
25
+ case Number:
26
+ swaggerProperty.type = "number";
27
+ break;
28
+ case Boolean:
29
+ swaggerProperty.type = "boolean";
30
+ break;
31
+ case Date:
32
+ swaggerProperty.type = "string";
33
+ swaggerProperty.format = "date-time";
34
+ break;
35
+ case Array:
36
+ // Attempt to infer array item type
37
+ const arrayItemType = Reflect.getMetadata("design:type", classType.prototype, propertyName + "[0]" // Attempt to get array item type. Very fragile.
38
+ );
39
+ if (arrayItemType) {
40
+ swaggerProperty.type = "array";
41
+ swaggerProperty.items = {
42
+ type: arrayItemType.name.toLowerCase(), // basic type inference
43
+ };
44
+ if (arrayItemType === Object) {
45
+ //try to infer the Object type within array
46
+ const nestedSchema = generateSwaggerSchema(Reflect.getMetadata("design:type", classType.prototype, propertyName + "[0]"));
47
+ swaggerProperty.items = nestedSchema;
48
+ }
49
+ }
50
+ else {
51
+ swaggerProperty.type = "array";
52
+ swaggerProperty.items = {}; // Array of unknown type
53
+ }
54
+ break;
55
+ case Object:
56
+ //Nested object
57
+ const nestedSchema = generateSwaggerSchema(Reflect.getMetadata("design:type", classType.prototype, propertyName));
58
+ swaggerProperty = nestedSchema;
59
+ break;
60
+ default:
61
+ swaggerProperty.type = ((_a = propertyType === null || propertyType === void 0 ? void 0 : propertyType.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || "string"; // Default to string if type cannot be inferred
26
62
  }
63
+ schema.properties[propertyName] = swaggerProperty;
64
+ (_b = meta.constraints) === null || _b === void 0 ? void 0 : _b.forEach((constraint) => {
65
+ switch (constraint.name) {
66
+ case "isNotEmpty":
67
+ if (!schema.required.includes(propertyName)) {
68
+ schema.required.push(propertyName);
69
+ }
70
+ break;
71
+ case "minLength":
72
+ schema.properties[propertyName].minLength = constraint.constraints[0];
73
+ break;
74
+ case "maxLength":
75
+ schema.properties[propertyName].maxLength = constraint.constraints[0];
76
+ break;
77
+ case "min":
78
+ schema.properties[propertyName].minimum = constraint.constraints[0];
79
+ break;
80
+ case "max":
81
+ schema.properties[propertyName].maximum = constraint.constraints[0];
82
+ break;
83
+ case "isEmail":
84
+ schema.properties[propertyName].format = "email";
85
+ break;
86
+ case "isDate":
87
+ schema.properties[propertyName].format = "date-time";
88
+ break;
89
+ case "isIn":
90
+ schema.properties[propertyName].enum = constraint.constraints[0];
91
+ break;
92
+ case "isNumber":
93
+ schema.properties[propertyName].type = "number";
94
+ break;
95
+ case "isInt":
96
+ schema.properties[propertyName].type = "integer";
97
+ break;
98
+ case "isBoolean":
99
+ schema.properties[propertyName].type = "boolean";
100
+ break;
101
+ case "isString":
102
+ schema.properties[propertyName].type = "string";
103
+ break;
104
+ case "isOptional":
105
+ if (schema.required.includes(propertyName)) {
106
+ schema.required = schema.required.filter((item) => item !== propertyName);
107
+ }
108
+ break;
109
+ // Add more cases for other validators as needed
110
+ }
111
+ });
27
112
  });
28
113
  return schema;
29
114
  }
115
+ // export function generateSwaggerSchema(classType: any) {
116
+ // const { getMetadataStorage } = require("class-validator");
117
+ // const { plainToInstance } = require("class-transformer");
118
+ // const metadataStorage = getMetadataStorage();
119
+ // const validationMetadata = metadataStorage.getTargetValidationMetadatas(
120
+ // classType,
121
+ // "",
122
+ // true,
123
+ // );
124
+ // const schema: any = {
125
+ // type: "object",
126
+ // properties: {},
127
+ // required: [],
128
+ // };
129
+ // validationMetadata.forEach((meta: any) => {
130
+ // const propertyName = meta.propertyName;
131
+ // // Infer the type dynamically using Reflect metadata
132
+ // const propertyType = Reflect.getMetadata(
133
+ // "design:type",
134
+ // classType.prototype,
135
+ // propertyName,
136
+ // );
137
+ // schema.properties[propertyName] = {
138
+ // type: propertyType?.name.toLowerCase() || "string", // Default to string if type cannot be inferred
139
+ // };
140
+ // if (meta.name === "isNotEmpty") {
141
+ // schema.required.push(propertyName);
142
+ // }
143
+ // if (meta.name === "minLength") {
144
+ // schema.properties[propertyName].minLength = meta.constraints[0];
145
+ // }
146
+ // });
147
+ // return schema;
148
+ // }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@avleon/core",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "scripts": {
@@ -25,7 +25,6 @@
25
25
  "@fastify/static": "^8.1.1",
26
26
  "@fastify/swagger": "^9.4.0",
27
27
  "@fastify/swagger-ui": "^5.1.0",
28
- "@scalar/fastify-api-reference": "^1.25.122",
29
28
  "class-transformer": "^0.5.1",
30
29
  "class-validator": "^0.14.1",
31
30
  "dotenv": "^16.4.7",
@@ -34,12 +33,15 @@
34
33
  "typedi": "^0.10.0",
35
34
  "typeorm": "^0.3.20"
36
35
  },
36
+ "peerDependencies": {
37
+ "@scalar/fastify-api-reference": "^1.25.130"
38
+ },
37
39
  "directories": {
38
40
  "test": "tests"
39
41
  },
40
42
  "description": "avleon core",
41
43
  "repository": {
42
44
  "type": "git",
43
- "url": "git+https://github.com/xtareq/avleon-core"
45
+ "url": "git+https://github.com/avleonjs/avleon-core"
44
46
  }
45
47
  }