@xrystal/core 3.10.3 → 3.10.5

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/bin/main-cli.js CHANGED
@@ -22,6 +22,12 @@ import { findFileRecursively, resolveObjWithHandlebars } from "./helpers/index.m
22
22
  const setupCLI = async () => {
23
23
  const cli = new Command()
24
24
 
25
+ const isBun = !!process.versions.bun
26
+ const runtimeName = isBun ? "Bun" : "Node.js"
27
+ const packageManager = isBun ? "bun" : "npm"
28
+ const installCommand = isBun ? "bun install" : "npm install"
29
+ const devCommand = isBun ? "bun run dev:local" : "npm run dev:local"
30
+
25
31
  try {
26
32
  let ownerTmpFilePath = findFileRecursively(".", tmpFileDefaultName, tmpFileDefaultExt)
27
33
 
@@ -54,7 +60,7 @@ const setupCLI = async () => {
54
60
 
55
61
  cli
56
62
  .command("create <project-name> [target-path]")
57
- .description("Project initializer with git setup")
63
+ .description(`Project initializer using ${runtimeName}`)
58
64
  .action(async (projectName, targetDir) => {
59
65
  let targetPath = ""
60
66
  const isCurrentDir = projectName === "."
@@ -75,7 +81,7 @@ const setupCLI = async () => {
75
81
  fs.mkdirSync(targetPath, { recursive: true })
76
82
  }
77
83
 
78
- const spinner = ora("Cloning and initializing git...").start()
84
+ const spinner = ora(`${runtimeName} environment detected. Cloning template...`).start()
79
85
 
80
86
  try {
81
87
  execSync(`git clone --depth 1 ${templateRepoUri} "${targetPath}"`, { stdio: "ignore" })
@@ -91,9 +97,9 @@ const setupCLI = async () => {
91
97
  }
92
98
 
93
99
  spinner.succeed(chalk.green("Template cloned and git initialized!"))
94
- console.log(chalk.blue(`\nšŸ“¦ Installing dependencies with bun...`))
100
+ console.log(chalk.blue(`\nšŸ“¦ Installing dependencies with ${packageManager}...`))
95
101
 
96
- execSync("bun install", { cwd: targetPath, stdio: "inherit" })
102
+ execSync(installCommand, { cwd: targetPath, stdio: "inherit" })
97
103
 
98
104
  console.log(chalk.green("\nāœ… Done!"))
99
105
 
@@ -102,7 +108,7 @@ const setupCLI = async () => {
102
108
  console.log(chalk.cyan(`\n cd ${relativePath}`))
103
109
  }
104
110
 
105
- console.log(chalk.cyan(` bun run dev:local`))
111
+ console.log(chalk.cyan(` ${devCommand}`))
106
112
 
107
113
  } catch (err) {
108
114
  spinner.fail(chalk.red("Failed!"))
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "author": "Yusuf Yasir KAYGUSUZ",
3
3
  "name": "@xrystal/core",
4
- "version": "3.10.3",
4
+ "version": "3.10.5",
5
5
  "description": "Project core for xrystal",
6
6
  "publishConfig": {
7
7
  "access": "public",
@@ -37,8 +37,8 @@
37
37
  "start": "bun --env-file=../infrastructer/x/environments/.global.env --env-file=../infrastructer/x/environments/.dev.env source/index.js"
38
38
  },
39
39
  "dependencies": {
40
- "@types/bcrypt": "^5.0.2",
41
40
  "@types/yaml": "^1.9.7",
41
+ "awilix": "^12.0.5",
42
42
  "chalk": "^5.6.2",
43
43
  "commander": "^13.0.0",
44
44
  "ejs": "^3.1.9",
@@ -1,9 +1,10 @@
1
1
  import ConfigsService from '../configs';
2
2
  export default class ClientsService {
3
3
  #private;
4
+ constructor({ configsService }: {
5
+ configsService: ConfigsService;
6
+ });
4
7
  static get instances(): Record<string, any>;
5
8
  static set instances(value: Record<string, any>);
6
- load({ configs }: {
7
- configs: ConfigsService;
8
- }): Promise<void>;
9
+ load({}: {}): Promise<void>;
9
10
  }
@@ -1,16 +1,20 @@
1
1
  import { BaseApiClient, CoreServiceEnum } from '../../utils/index';
2
2
  export default class ClientsService {
3
3
  static #services = {};
4
+ #configs;
5
+ constructor({ configsService }) {
6
+ this.#configs = configsService;
7
+ }
4
8
  static get instances() {
5
9
  return this.#services;
6
10
  }
7
11
  static set instances(value) {
8
12
  this.#services = { ...this.#services, ...value };
9
13
  }
10
- async load({ configs }) {
14
+ async load({}) {
11
15
  const baseClient = new BaseApiClient({
12
16
  clientName: CoreServiceEnum.BASE_API_CLIENT,
13
- baseURL: configs.all.baseApiUri || ''
17
+ baseURL: this.#configs.all.baseApiUri || ''
14
18
  });
15
19
  ClientsService.instances[CoreServiceEnum.BASE_API_CLIENT] = baseClient;
16
20
  }
@@ -1,11 +1,11 @@
1
1
  import SystemService from '../system/index';
2
2
  export default class ConfigsService {
3
+ #private;
3
4
  private config;
4
- protected _systemService: SystemService;
5
5
  publicFolderName: string;
6
- load: ({ tmp, systemService }: {
7
- tmp: any;
6
+ constructor({ systemService }: {
8
7
  systemService: SystemService;
9
- }) => void;
8
+ });
9
+ load: ({}: {}) => void;
10
10
  get all(): Record<string, any>;
11
11
  }
@@ -1,10 +1,14 @@
1
1
  import path from 'node:path';
2
+ import { publicFolderName } from '../../utils';
2
3
  export default class ConfigsService {
3
4
  config = {};
4
- _systemService;
5
- publicFolderName = 'public';
6
- load = ({ tmp, systemService }) => {
7
- this._systemService = systemService;
5
+ publicFolderName = publicFolderName;
6
+ #systemService;
7
+ constructor({ systemService }) {
8
+ this.#systemService = systemService;
9
+ }
10
+ load = ({}) => {
11
+ const tmp = this.#systemService.tmp;
8
12
  const rawConfigs = tmp?.configs || tmp?.configs || {};
9
13
  this.config = {
10
14
  debug: process.env.SYSTEM_LOGGER_LAYER,
@@ -1,7 +1,10 @@
1
1
  import LoggerService from '../logger/index';
2
2
  export default class EventsService {
3
- private logger;
4
- load: ({ logger, }: {
3
+ #private;
4
+ constructor({ loggerService }: {
5
+ loggerService: LoggerService;
6
+ });
7
+ load: ({}: {
5
8
  logger: LoggerService;
6
9
  }) => any;
7
10
  private _globalLoader;
@@ -1,19 +1,21 @@
1
1
  import { LoggerLayerEnum } from '../../utils/index';
2
2
  export default class EventsService {
3
- logger;
4
- load = ({ logger, }) => {
5
- this.logger = logger;
3
+ #loggerService;
4
+ constructor({ loggerService }) {
5
+ this.#loggerService = loggerService;
6
+ }
7
+ load = ({}) => {
6
8
  this._globalLoader();
7
9
  };
8
10
  _globalLoader = () => {
9
11
  process.on("uncaughtException", (exception) => {
10
- this.logger.winston.log({
12
+ this.#loggerService.winston.log({
11
13
  level: LoggerLayerEnum[LoggerLayerEnum.CRITICAL].toLowerCase(),
12
14
  message: `UncaughtException: ${exception}`,
13
15
  });
14
16
  });
15
17
  process.on("unhandledRejection", (exception) => {
16
- this.logger.winston.log({
18
+ this.#loggerService.winston.log({
17
19
  level: LoggerLayerEnum[LoggerLayerEnum.CRITICAL].toLowerCase(),
18
20
  message: `UnhandledRejection: ${exception}`,
19
21
  });
@@ -1,22 +1,25 @@
1
1
  import winston from "winston";
2
2
  import "winston-daily-rotate-file";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
+ import ConfigsService from "../configs";
4
5
  interface CustomLogger extends winston.Logger {
5
6
  critical: winston.LeveledLogMethod;
6
7
  http: winston.LeveledLogMethod;
7
8
  }
8
9
  export default class LoggerService {
10
+ #private;
9
11
  static readonly storage: AsyncLocalStorage<Map<string, string>>;
10
12
  private serviceName;
11
- private environment;
12
13
  private kafkaProducer;
13
14
  private kafkaTopic;
14
15
  private isKafkaReady;
16
+ constructor({ configsService }: {
17
+ configsService: ConfigsService;
18
+ });
15
19
  private safeReplacer;
16
20
  private getTracingFormat;
17
21
  private getConsoleFormat;
18
22
  winston: CustomLogger;
19
- constructor();
20
23
  runWithId: <T>(id: string, callback: () => T) => T;
21
24
  load: (config: Record<string, any>) => Promise<void>;
22
25
  winstonLoader: ({ loadPath, loggerLevel }: {
@@ -34,10 +34,14 @@ const customColors = {
34
34
  export default class LoggerService {
35
35
  static storage = new AsyncLocalStorage();
36
36
  serviceName = "";
37
- environment = "";
38
37
  kafkaProducer = null;
39
38
  kafkaTopic = "";
40
39
  isKafkaReady = false;
40
+ #configsService;
41
+ constructor({ configsService }) {
42
+ this.#configsService = configsService;
43
+ winston.addColors(customColors);
44
+ }
41
45
  safeReplacer = (key, value) => {
42
46
  if (value instanceof Headers)
43
47
  return Object.fromEntries(value.entries());
@@ -72,9 +76,6 @@ export default class LoggerService {
72
76
  format: this.getConsoleFormat(),
73
77
  transports: [new winston.transports.Console()]
74
78
  });
75
- constructor() {
76
- winston.addColors(customColors);
77
- }
78
79
  runWithId = (id, callback) => {
79
80
  const store = new Map();
80
81
  store.set("correlationId", id);
@@ -82,7 +83,6 @@ export default class LoggerService {
82
83
  };
83
84
  load = async (config) => {
84
85
  this.serviceName = config?.serviceName || "service";
85
- this.environment = config?.env || "dev";
86
86
  this.kafkaTopic = config?.kafkaTopic || "logs";
87
87
  const rawBrokers = config?.kafkaBrokers;
88
88
  const brokers = rawBrokers ? String(rawBrokers).split(",").map((b) => b.trim()) : [];
@@ -100,7 +100,6 @@ export default class LoggerService {
100
100
  try {
101
101
  await this.kafkaProducer?.connect();
102
102
  this.isKafkaReady = true;
103
- this.winston.info("Kafka connected successfully");
104
103
  }
105
104
  catch (err) {
106
105
  this.isKafkaReady = false;
@@ -163,7 +162,7 @@ export default class LoggerService {
163
162
  ...rest,
164
163
  timestamp: new Date().toISOString(),
165
164
  id: id || null,
166
- env: this.environment
165
+ env: this.#configsService.all.env
167
166
  }, this.safeReplacer)
168
167
  }]
169
168
  });
@@ -1,8 +1,8 @@
1
1
  export default class SystemService {
2
- private static _tmp;
2
+ _tmp: Record<string, any>;
3
3
  load: ({ tmp, }: {
4
4
  tmp: any;
5
5
  }) => Promise<void>;
6
6
  private _systemLoader;
7
- static get tmp(): any;
7
+ get tmp(): Record<string, any>;
8
8
  }
@@ -1,14 +1,14 @@
1
1
  export default class SystemService {
2
- static _tmp;
2
+ _tmp = {};
3
3
  load = async ({ tmp, }) => {
4
- SystemService._tmp = tmp;
4
+ this._tmp = tmp;
5
5
  await this._systemLoader({});
6
6
  };
7
7
  _systemLoader = async ({}) => {
8
8
  //console.log(this._tmp)
9
9
  };
10
10
  // => getters
11
- static get tmp() {
12
- return SystemService._tmp;
11
+ get tmp() {
12
+ return this._tmp;
13
13
  }
14
14
  }
@@ -24,42 +24,48 @@ const coreLoader = async ({}) => {
24
24
  LocalizationsService,
25
25
  ClientsService
26
26
  ];
27
- services.forEach(service => x.set({ service, reference: service }));
28
- const system = x.get(SystemService);
29
- const configService = x.get(ConfigsService);
30
- const logger = x.get(LoggerService);
31
- const events = x.get(EventsService);
32
- const i18n = x.get(LocalizationsService);
33
- const clientsService = x.get(ClientsService);
34
- await system.load({
35
- tmp: core._
36
- });
37
- configService.load({
38
- tmp: core._,
39
- systemService: system,
40
- ...(configs.loaders.configs.globalEnvFileName && { globalEnvFileName: configs.loaders.configs.globalEnvFileName })
41
- });
42
- await logger.load({
43
- loadPath: path.join(rootFolderPath, configs.loaders.loggers.loadPath),
44
- loggerLevel: systemLoggerLayer ?? configs.loaders.loggers.logLevel,
45
- serviceName: configs.service,
46
- env: process.env.NODE_ENV,
47
- kafkaBrokers: kafkaBrokers ?? "",
48
- kafkaTopic: configs.loaders.loggers.topic
49
- });
50
- await events.load({
51
- logger
52
- });
53
- await i18n.load({
54
- loadPath: path.resolve(rootFolderPath, configs.loaders.localization.loadPath),
55
- fallbackLang: configs.loaders.localization.fallbackLang,
56
- preloadLang: configs.loaders.localization.preloadLangs
57
- });
58
- await clientsService.load({
59
- configs: configService,
60
- });
27
+ x.registerServices(services);
28
+ x.initialize([
29
+ {
30
+ service: SystemService,
31
+ props: {
32
+ tmp: core._
33
+ }
34
+ },
35
+ {
36
+ service: ConfigsService,
37
+ props: {
38
+ ...(configs.loaders.configs.globalEnvFileName && { globalEnvFileName: configs.loaders.configs.globalEnvFileName })
39
+ }
40
+ },
41
+ {
42
+ service: LoggerService,
43
+ props: {
44
+ loadPath: path.join(rootFolderPath, configs.loaders.loggers.loadPath),
45
+ loggerLevel: systemLoggerLayer ?? configs.loaders.loggers.logLevel,
46
+ serviceName: configs.service,
47
+ kafkaBrokers: kafkaBrokers ?? "",
48
+ kafkaTopic: configs.loaders.loggers.topic
49
+ }
50
+ },
51
+ {
52
+ service: EventsService,
53
+ props: {}
54
+ },
55
+ {
56
+ service: LocalizationsService,
57
+ props: {
58
+ loadPath: path.resolve(rootFolderPath, configs.loaders.localization.loadPath),
59
+ fallbackLang: configs.loaders.localization.fallbackLang,
60
+ preloadLang: configs.loaders.localization.preloadLangs
61
+ }
62
+ },
63
+ {
64
+ service: ClientsService,
65
+ props: {}
66
+ },
67
+ ]);
61
68
  coreHasRun = true;
62
- return {};
63
69
  }
64
70
  catch (error) {
65
71
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -6,3 +6,4 @@ export declare const defaultTmpFilePath: string;
6
6
  export declare const defaultOwnerTmpFilePath: string;
7
7
  export declare const systemLoggerLayer: string;
8
8
  export declare const kafkaBrokers: string;
9
+ export declare const publicFolderName = "public";
@@ -8,3 +8,4 @@ export const defaultTmpFilePath = path.resolve(__dirname(import.meta.url), `../.
8
8
  export const defaultOwnerTmpFilePath = path.resolve(`./${tmpFileDefaultMainFolderName}/${tmpFileDefaultName}.yml`);
9
9
  export const systemLoggerLayer = process.env.SYSTEM_LOGGER_LAYER;
10
10
  export const kafkaBrokers = process.env?.KAFKA_BROKERS;
11
+ export const publicFolderName = 'public';
@@ -0,0 +1,12 @@
1
+ export declare class Locator {
2
+ private _context;
3
+ constructor({}: {});
4
+ set: <T extends new (...args: any[]) => any>({ service, reference, args }: {
5
+ service: T;
6
+ reference: T;
7
+ args?: ConstructorParameters<T>;
8
+ }) => void;
9
+ get: <T>(service: new (...args: any) => T) => T;
10
+ }
11
+ declare const _default: Locator;
12
+ export default _default;
@@ -0,0 +1,16 @@
1
+ // => // X Service Locator
2
+ export class Locator {
3
+ _context = new Map();
4
+ constructor({}) {
5
+ }
6
+ set = ({ service, reference, args }) => {
7
+ this._context.set(service, new reference(...(args || [])));
8
+ };
9
+ get = (service) => {
10
+ if (!this._context.has(service)) {
11
+ throw new Error(`${service} not found in context.`);
12
+ }
13
+ return this._context.get(service);
14
+ };
15
+ }
16
+ export default new Locator({});
@@ -1,12 +1,18 @@
1
1
  export declare class X {
2
- private _context;
3
- constructor({}: {});
4
- set: <T extends new (...args: any[]) => any>({ service, reference, args }: {
5
- service: T;
6
- reference: T;
7
- args?: ConstructorParameters<T>;
8
- }) => void;
9
- get: <T>(service: new (...args: any) => T) => T;
2
+ private container;
3
+ constructor();
4
+ registerService(ServiceClass: any): void;
5
+ registerServices(services: any[]): void;
6
+ registerInstance(name: string, instance: any): void;
7
+ initialize(input: {
8
+ service: any;
9
+ props?: any;
10
+ } | {
11
+ service: any;
12
+ props?: any;
13
+ }[]): Promise<void>;
14
+ get<T>(name: string | any): T;
15
+ get cradle(): any;
10
16
  }
11
17
  declare const _default: X;
12
18
  export default _default;
@@ -1,16 +1,45 @@
1
- // => // X Service Locator
1
+ import { createContainer, asClass, asValue, InjectionMode } from 'awilix';
2
2
  export class X {
3
- _context = new Map();
4
- constructor({}) {
3
+ container;
4
+ constructor() {
5
+ this.container = createContainer({
6
+ injectionMode: InjectionMode.PROXY,
7
+ strict: true
8
+ });
5
9
  }
6
- set = ({ service, reference, args }) => {
7
- this._context.set(service, new reference(...(args || [])));
8
- };
9
- get = (service) => {
10
- if (!this._context.has(service)) {
11
- throw new Error(`${service} not found in context.`);
10
+ registerService(ServiceClass) {
11
+ const name = ServiceClass.name.charAt(0).toLowerCase() + ServiceClass.name.slice(1);
12
+ this.container.register({
13
+ [name]: asClass(ServiceClass).singleton()
14
+ });
15
+ }
16
+ registerServices(services) {
17
+ services.forEach(ServiceClass => {
18
+ this.registerService(ServiceClass);
19
+ });
20
+ }
21
+ registerInstance(name, instance) {
22
+ this.container.register({
23
+ [name]: asValue(instance)
24
+ });
25
+ }
26
+ async initialize(input) {
27
+ const items = Array.isArray(input) ? input : [input];
28
+ for (const item of items) {
29
+ const instance = this.get(item.service);
30
+ if (instance && typeof instance.load === 'function') {
31
+ await instance.load(item.props);
32
+ }
12
33
  }
13
- return this._context.get(service);
14
- };
34
+ }
35
+ get(name) {
36
+ const resolveName = typeof name === 'function'
37
+ ? name.name.charAt(0).toLowerCase() + name.name.slice(1)
38
+ : name;
39
+ return this.container.resolve(resolveName);
40
+ }
41
+ get cradle() {
42
+ return this.container.cradle;
43
+ }
15
44
  }
16
- export default new X({});
45
+ export default new X();
@@ -1,8 +1,9 @@
1
1
  import x, { X } from './classes/class.x';
2
+ import locator, { Locator } from './classes/class.service-locator';
2
3
  export * from './classes/class.tmp-file-loader';
3
4
  export * from './classes/class.controller';
4
5
  export * from './classes/class.response';
5
6
  export * from './classes/class.services';
6
7
  export * from './types';
7
8
  export * from './enums';
8
- export { x, X };
9
+ export { x, X, locator, Locator };
@@ -1,8 +1,9 @@
1
1
  import x, { X } from './classes/class.x';
2
+ import locator, { Locator } from './classes/class.service-locator';
2
3
  export * from './classes/class.tmp-file-loader';
3
4
  export * from './classes/class.controller';
4
5
  export * from './classes/class.response';
5
6
  export * from './classes/class.services';
6
7
  export * from './types';
7
8
  export * from './enums';
8
- export { x, X };
9
+ export { x, X, locator, Locator };