@xrystal/core 3.20.9 → 3.21.1

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "author": "Yusuf Yasir KAYGUSUZ",
3
3
  "name": "@xrystal/core",
4
- "version": "3.20.9",
4
+ "version": "3.21.1",
5
5
  "description": "Project core for xrystal",
6
6
  "publishConfig": {
7
7
  "access": "public",
@@ -26,26 +26,9 @@ export declare const getControllerCtx: () => {
26
26
  _isRaw?: boolean;
27
27
  };
28
28
  };
29
- export declare const protocol: (callback: () => Promise<any>, protocol?: ProtocolEnum) => Promise<any>;
30
- export interface CustomRequest {
31
- accounts?: any;
32
- url: string;
33
- method: string;
34
- headers: Record<string, any>;
35
- body?: any;
36
- params: Record<string, any>;
37
- query: Record<string, any>;
38
- lang: string;
39
- t: (k: string, args?: any) => string;
40
- }
41
- export interface CustomResponse {
42
- status: (code: number) => CustomResponse;
43
- send: (data: any) => any;
44
- json: (data: any) => any;
45
- locals: Record<string, any>;
46
- }
47
- declare abstract class Controller {
29
+ export declare abstract class Controller {
48
30
  protected logger: LoggerService;
31
+ protected systemService: SystemService;
49
32
  protected supportedProtocols: ProtocolEnum[];
50
33
  protected get protocol(): ProtocolEnum;
51
34
  protected get currentStore(): {
@@ -64,9 +47,9 @@ declare abstract class Controller {
64
47
  protected get res(): CustomResponse;
65
48
  }
66
49
  export declare abstract class ControllerService extends Controller implements IService<any> {
67
- protected systemService: SystemService;
68
- constructor({ systemService }: {
50
+ constructor({ systemService, loggerService }: {
69
51
  systemService: SystemService;
52
+ loggerService: LoggerService;
70
53
  });
71
54
  load(): Promise<void>;
72
55
  schema({ checks, logic, response }: {
@@ -75,4 +58,20 @@ export declare abstract class ControllerService extends Controller implements IS
75
58
  response?: (args: any) => Promise<any>;
76
59
  }): Promise<any>;
77
60
  }
78
- export { Controller };
61
+ export interface CustomRequest {
62
+ accounts?: any;
63
+ url: string;
64
+ method: string;
65
+ headers: Record<string, any>;
66
+ body?: any;
67
+ params: Record<string, any>;
68
+ query: Record<string, any>;
69
+ lang: string;
70
+ t: (k: string, args?: any) => string;
71
+ }
72
+ export interface CustomResponse {
73
+ status: (code: number) => CustomResponse;
74
+ send: (data: any) => any;
75
+ json: (data: any) => any;
76
+ locals: Record<string, any>;
77
+ }
@@ -1,17 +1,10 @@
1
1
  import { AsyncLocalStorage } from 'node:async_hooks';
2
- import { ProtocolEnum, responseMessageHelper, ResponseSchema, x } from '../../utils/index';
3
- import LoggerService from '../logger';
2
+ import { LoggerLayerEnum, ProtocolEnum, responseMessageHelper, ResponseSchema } from '../../utils/index';
4
3
  export const controllerContextStorage = new AsyncLocalStorage();
5
4
  export const getControllerCtx = () => controllerContextStorage.getStore();
6
- export const protocol = async (callback, protocol = ProtocolEnum.HTTP) => {
7
- const store = controllerContextStorage.getStore();
8
- if (store) {
9
- store.protocol = protocol;
10
- }
11
- return await callback();
12
- };
13
- class Controller {
14
- logger = x.get(LoggerService);
5
+ export class Controller {
6
+ logger;
7
+ systemService;
15
8
  supportedProtocols = [ProtocolEnum.HTTP, ProtocolEnum.WEBSOCKET];
16
9
  get protocol() {
17
10
  return this.currentStore?.protocol || ProtocolEnum.HTTP;
@@ -79,14 +72,14 @@ class Controller {
79
72
  }
80
73
  }
81
74
  export class ControllerService extends Controller {
82
- systemService;
83
- constructor({ systemService }) {
75
+ constructor({ systemService, loggerService }) {
84
76
  super();
85
77
  this.systemService = systemService;
78
+ this.logger = loggerService;
86
79
  }
87
80
  async load() {
88
- const protocols = this.systemService.tmp.configs.loaders.controller.protocols;
89
- this.supportedProtocols = Array.isArray(protocols) ? protocols : [protocols];
81
+ const protocols = this.systemService?.tmp?.configs?.loaders?.controller?.protocols;
82
+ this.supportedProtocols = Array.isArray(protocols) ? protocols : [protocols || ProtocolEnum.HTTP];
90
83
  }
91
84
  async schema({ checks, logic, response }) {
92
85
  try {
@@ -153,10 +146,7 @@ export class ControllerService extends Controller {
153
146
  }).getResponse);
154
147
  }
155
148
  catch (error) {
156
- this.logger.winston.log({
157
- level: 'error',
158
- message: `Controller Error: ${error.message}`
159
- });
149
+ this.logger?.log(LoggerLayerEnum.ERROR, `Controller Error: ${error.message}`);
160
150
  return this.res.status(500).send(new ResponseSchema({
161
151
  status: false,
162
152
  message: error.message,
@@ -165,4 +155,3 @@ export class ControllerService extends Controller {
165
155
  }
166
156
  }
167
157
  }
168
- export { Controller };
@@ -43,10 +43,10 @@ export default class LoggerService {
43
43
  constructor({ systemService, configsService }) {
44
44
  this.#systemService = systemService;
45
45
  this.#configsService = configsService;
46
- this.serviceName = this.#systemService?.tmp?.configs?.service;
47
- this.kafkaLogsTopic = this.#configsService?.all?.kafkaLogsTopic;
48
46
  }
49
47
  load = async () => {
48
+ this.serviceName = this.#systemService?.tmp?.configs?.service;
49
+ this.kafkaLogsTopic = this.#configsService?.all?.kafkaLogsTopic;
50
50
  winston.addColors(customColors);
51
51
  this.winston = winston.createLogger({
52
52
  level: this.#configsService?.all?.systemLoggerLayer || 'info',
@@ -7,8 +7,8 @@ export default class SystemService {
7
7
  load = async ({ core }) => {
8
8
  this._core = core;
9
9
  this._tmp = this._core._;
10
- await this.initializeKafkaInfrastructure();
11
10
  await this._systemLoader({});
11
+ await this.initializeKafkaInfrastructure();
12
12
  };
13
13
  initializeKafkaInfrastructure = async () => {
14
14
  const { kafkaBrokers, kafkaTopics, isKafkaPassive, serviceName } = {
@@ -1,5 +1,6 @@
1
1
  export declare abstract class ILifeCycle<T = any> {
2
2
  load(props?: T | {}): Promise<void>;
3
+ ready?(_context?: any): Promise<void> | void;
3
4
  dispose?(_context?: any): Promise<void> | void;
4
5
  }
5
6
  export declare abstract class IService<T = any> extends ILifeCycle<T> {
@@ -1,6 +1,8 @@
1
1
  export class ILifeCycle {
2
2
  async load(props = {}) {
3
3
  }
4
+ ready(_context) {
5
+ }
4
6
  dispose(_context) {
5
7
  }
6
8
  }
@@ -1,16 +1,18 @@
1
1
  import { AwilixContainer, LifetimeType } from 'awilix';
2
+ export declare const xSymbol: unique symbol;
2
3
  type Constructor<T> = new (...args: any[]) => T;
3
4
  type AbstractConstructor<T> = abstract new (...args: any[]) => T;
4
- declare abstract class XHelper {
5
+ declare abstract class X {
5
6
  protected checkRegistration(container: AwilixContainer, name: string): boolean;
6
7
  }
7
- declare class X extends XHelper {
8
+ declare class DIM extends X {
8
9
  private container;
9
10
  private initializedNames;
10
11
  private loadedPaths;
11
12
  private registeredClasses;
12
13
  private isInitializing;
13
14
  constructor();
15
+ private getName;
14
16
  load(patterns: string | string[], options?: {
15
17
  verbose?: boolean;
16
18
  exclude?: string | Function | (string | Function)[];
@@ -29,5 +31,5 @@ declare class X extends XHelper {
29
31
  shutdown(): Promise<void>;
30
32
  get cradle(): any;
31
33
  }
32
- declare const _default: X;
34
+ declare const _default: DIM;
33
35
  export default _default;
@@ -1,12 +1,13 @@
1
1
  import { createContainer, asClass, asValue, InjectionMode, listModules, Lifetime } from 'awilix';
2
2
  import path from 'node:path';
3
3
  import { pathToFileURL } from 'node:url';
4
- class XHelper {
4
+ export const xSymbol = Symbol.for('@xrystal/core/di-container');
5
+ class X {
5
6
  checkRegistration(container, name) {
6
7
  return !!container.registrations[name];
7
8
  }
8
9
  }
9
- class X extends XHelper {
10
+ class DIM extends X {
10
11
  container;
11
12
  initializedNames = new Set();
12
13
  loadedPaths = new Set();
@@ -19,10 +20,16 @@ class X extends XHelper {
19
20
  strict: true
20
21
  });
21
22
  }
23
+ getName(target) {
24
+ if (typeof target === 'string')
25
+ return target.charAt(0).toLowerCase() + target.slice(1);
26
+ if (typeof target === 'function' && target.name)
27
+ return target.name.charAt(0).toLowerCase() + target.name.slice(1);
28
+ return '';
29
+ }
22
30
  async load(patterns, options = {}) {
23
31
  const { verbose = false, exclude = [], lifetime = Lifetime.SINGLETON } = options;
24
32
  const cwd = process.cwd();
25
- const excludeList = Array.isArray(exclude) ? exclude : [exclude];
26
33
  const resolvedPatterns = (Array.isArray(patterns) ? patterns : [patterns]).map(p => {
27
34
  const resolved = path.isAbsolute(p) ? p : path.resolve(cwd, p);
28
35
  return resolved.replace(/\\/g, '/').toLowerCase();
@@ -50,10 +57,10 @@ class X extends XHelper {
50
57
  if (typeof dependency === 'function' && !!dependency.prototype && !!dependency.name) {
51
58
  if (this.registeredClasses.has(dependency))
52
59
  continue;
53
- const name = dependency.name.charAt(0).toLowerCase() + dependency.name.slice(1);
54
- if (!this.checkRegistration(this.container, name)) {
60
+ const name = this.getName(dependency);
61
+ if (name && !this.checkRegistration(this.container, name)) {
55
62
  this.container.register({
56
- [name]: asClass(dependency).singleton()
63
+ [name]: asClass(dependency).setLifetime(lifetime)
57
64
  });
58
65
  this.loadedPaths.add(normalizedMPath);
59
66
  this.registeredClasses.add(dependency);
@@ -68,19 +75,19 @@ class X extends XHelper {
68
75
  return this;
69
76
  }
70
77
  register(Dependency, lifetime = Lifetime.SINGLETON) {
71
- if (!Dependency?.name || this.registeredClasses.has(Dependency))
78
+ const name = this.getName(Dependency);
79
+ if (!name || this.registeredClasses.has(Dependency))
72
80
  return this;
73
- const name = Dependency.name.charAt(0).toLowerCase() + Dependency.name.slice(1);
74
81
  if (this.checkRegistration(this.container, name))
75
82
  return this;
76
- this.container.register({ [name]: asClass(Dependency).singleton() });
83
+ this.container.register({ [name]: asClass(Dependency).setLifetime(lifetime) });
77
84
  this.registeredClasses.add(Dependency);
78
85
  return this;
79
86
  }
80
87
  registerInstance(name, instance) {
81
88
  if (!name)
82
89
  return this;
83
- const formattedName = name.charAt(0).toLowerCase() + name.slice(1);
90
+ const formattedName = this.getName(name);
84
91
  this.container.register({ [formattedName]: asValue(instance) });
85
92
  return this;
86
93
  }
@@ -89,34 +96,55 @@ class X extends XHelper {
89
96
  return this;
90
97
  this.isInitializing = true;
91
98
  try {
92
- const cradle = this.container.cradle;
93
99
  const inputList = input ? (Array.isArray(input) ? input : [input]) : [];
94
- const propsMap = new Map();
95
100
  for (const item of inputList) {
96
- if (!item?.service)
101
+ const name = this.getName(item.service);
102
+ if (!name || this.initializedNames.has(name))
103
+ continue;
104
+ const reg = this.container.registrations[name];
105
+ if (!reg || reg.lifetime !== Lifetime.SINGLETON)
97
106
  continue;
98
- const name = typeof item.service === 'function' ? item.service.name.charAt(0).toLowerCase() + item.service.name.slice(1) : item.service;
99
- if (name)
100
- propsMap.set(name, item.props);
107
+ try {
108
+ const instance = this.container.cradle[name];
109
+ if (instance && typeof instance.load === 'function') {
110
+ await instance.load(item.props || {});
111
+ }
112
+ this.initializedNames.add(name);
113
+ }
114
+ catch (err) {
115
+ if (verbose)
116
+ console.error(`[DI] Priority Init Failed (${name}):`, err.message);
117
+ }
101
118
  }
102
- const keys = Object.keys(this.container.registrations);
103
- for (const key of keys) {
119
+ const allKeys = Object.keys(this.container.registrations);
120
+ for (const key of allKeys) {
104
121
  if (this.initializedNames.has(key))
105
122
  continue;
106
123
  const reg = this.container.registrations[key];
107
124
  if (reg.lifetime !== Lifetime.SINGLETON)
108
125
  continue;
109
126
  try {
110
- const instance = cradle[key];
127
+ const instance = this.container.cradle[key];
111
128
  if (instance && typeof instance.load === 'function') {
112
- const props = propsMap.get(key) || {};
113
- await instance.load(props);
129
+ await instance.load({});
114
130
  }
115
131
  this.initializedNames.add(key);
116
132
  }
117
133
  catch (err) {
118
134
  if (verbose)
119
- console.error(`[DI] Init Failed (${key}):`, err.message);
135
+ console.error(`[DI] Auto Init Failed (${key}):`, err.message);
136
+ }
137
+ }
138
+ for (const name of this.initializedNames) {
139
+ try {
140
+ const instance = this.container.cradle[name];
141
+ if (instance && typeof instance.ready === 'function') {
142
+ await instance.afterInit();
143
+ }
144
+ }
145
+ catch (err) {
146
+ if (verbose)
147
+ console.error(`[DI] afterInit Hook Failed (${name}):`, err.message);
120
148
  }
121
149
  }
122
150
  }
@@ -126,9 +154,7 @@ class X extends XHelper {
126
154
  return this;
127
155
  }
128
156
  get(target) {
129
- const resolveName = typeof target === 'function'
130
- ? target.name.charAt(0).toLowerCase() + target.name.slice(1)
131
- : target;
157
+ const resolveName = this.getName(target);
132
158
  return this.container.resolve(resolveName);
133
159
  }
134
160
  async shutdown() {
@@ -136,9 +162,7 @@ class X extends XHelper {
136
162
  }
137
163
  get cradle() { return this.container.cradle; }
138
164
  }
139
- const X_SYMBOL = Symbol.for('X');
140
- const globalObj = global;
141
- if (!globalObj[X_SYMBOL]) {
142
- globalObj[X_SYMBOL] = new X();
165
+ if (!global[xSymbol]) {
166
+ global[xSymbol] = new DIM();
143
167
  }
144
- export default globalObj[X_SYMBOL];
168
+ export default global[xSymbol];