@xrystal/core 3.14.1 → 3.14.2

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.14.1",
4
+ "version": "3.14.2",
5
5
  "description": "Project core for xrystal",
6
6
  "publishConfig": {
7
7
  "access": "public",
@@ -1,4 +1,17 @@
1
- import { ProtocolEnum } from '../../index';
1
+ import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import { ProtocolEnum } from '../../utils/index';
3
+ export declare const controllerContextStorage: AsyncLocalStorage<{
4
+ protocol: ProtocolEnum;
5
+ ctx?: any;
6
+ req?: any;
7
+ res?: any;
8
+ }>;
9
+ export declare const getControllerCtx: () => {
10
+ protocol: ProtocolEnum;
11
+ ctx?: any;
12
+ req?: any;
13
+ res?: any;
14
+ };
2
15
  export interface CustomRequest {
3
16
  accounts?: any;
4
17
  url: string;
@@ -17,19 +30,24 @@ export interface CustomResponse {
17
30
  }
18
31
  declare abstract class Controller {
19
32
  protected loggerService: any;
20
- protected protocol: ProtocolEnum | null;
21
- protected req: CustomRequest | null;
22
- protected res: CustomResponse | null;
23
- constructor({ protocol, req, res, ctx, }: {
33
+ constructor({ loggerService }: any);
34
+ protected get currentStore(): {
24
35
  protocol: ProtocolEnum;
36
+ ctx?: any;
25
37
  req?: any;
26
38
  res?: any;
27
- ctx?: any;
28
- });
39
+ };
40
+ protected get protocol(): ProtocolEnum;
41
+ protected get req(): CustomRequest;
42
+ protected get res(): CustomResponse;
29
43
  protected responseProtocolSwitch: ({ res, resStatus, context, req }: any) => Promise<any>;
30
44
  protected parsedQuerys: (url: string) => Record<string, any>;
31
45
  }
32
- export declare class ControllerSchema extends Controller {
46
+ export declare abstract class ControllerService extends Controller {
47
+ protected controllerType: string;
48
+ load({ type }: {
49
+ type?: string;
50
+ }): Promise<void>;
33
51
  schema({ checks, logic, response, }: {
34
52
  checks?: (args: any) => Promise<any>;
35
53
  logic: (args: any) => Promise<any>;
@@ -1,15 +1,26 @@
1
1
  import qs from 'qs';
2
- import { LoggerService } from '../../../loader';
3
- import { ProtocolEnum, responseMessageHelper, ResponseSchema, x } from '../../index';
2
+ import { AsyncLocalStorage } from 'node:async_hooks';
3
+ import { ProtocolEnum, responseMessageHelper, ResponseSchema } from '../../utils/index';
4
+ export const controllerContextStorage = new AsyncLocalStorage();
5
+ export const getControllerCtx = () => controllerContextStorage.getStore();
4
6
  class Controller {
5
- loggerService = x.get(LoggerService);
6
- protocol = null;
7
- req = null;
8
- res = null;
9
- constructor({ protocol, req, res, ctx, }) {
10
- this.protocol = protocol;
11
- if (ctx) {
12
- this.req = {
7
+ loggerService;
8
+ constructor({ loggerService }) {
9
+ this.loggerService = loggerService;
10
+ }
11
+ get currentStore() {
12
+ return getControllerCtx();
13
+ }
14
+ get protocol() {
15
+ return this.currentStore?.protocol || ProtocolEnum.HTTP;
16
+ }
17
+ get req() {
18
+ const store = this.currentStore;
19
+ if (!store)
20
+ return { url: '', method: '', headers: {}, params: {}, query: {} };
21
+ if (store.ctx) {
22
+ const { ctx } = store;
23
+ return {
13
24
  url: ctx.request?.url || '',
14
25
  method: ctx.request?.method || '',
15
26
  headers: ctx.headers || {},
@@ -19,7 +30,26 @@ class Controller {
19
30
  accounts: ctx.user || ctx.accounts,
20
31
  t: ctx.t
21
32
  };
22
- this.res = {
33
+ }
34
+ const { req } = store;
35
+ return {
36
+ url: req?.originalUrl || req?.url || '',
37
+ method: req?.method || 'GET',
38
+ headers: req?.headers || {},
39
+ body: req?.body,
40
+ params: req?.params || {},
41
+ query: req?.query || {},
42
+ accounts: req?.accounts,
43
+ t: req?.t
44
+ };
45
+ }
46
+ get res() {
47
+ const store = this.currentStore;
48
+ const protocol = this.protocol;
49
+ if (!store)
50
+ return { status: () => { }, send: () => { }, json: () => { }, locals: {} };
51
+ if (store.ctx) {
52
+ return {
23
53
  locals: {},
24
54
  status(code) {
25
55
  this.locals._code = code;
@@ -38,36 +68,25 @@ class Controller {
38
68
  }
39
69
  };
40
70
  }
41
- else {
42
- this.req = {
43
- url: req?.originalUrl || req?.url || '',
44
- method: req?.method || 'GET',
45
- headers: req?.headers || {},
46
- body: req?.body,
47
- params: req?.params || {},
48
- query: req?.query || {},
49
- accounts: req?.accounts,
50
- t: req?.t
51
- };
52
- this.res = {
53
- locals: res?.locals || {},
54
- status(code) {
55
- if (res?.status)
56
- res.status(code);
57
- return this;
58
- },
59
- send(data) {
60
- if (res?.send)
61
- return res.send(data);
62
- return data;
63
- },
64
- json(data) {
65
- if (res?.json)
66
- return res.json(data);
67
- return data;
68
- }
69
- };
70
- }
71
+ const { res } = store;
72
+ return {
73
+ locals: res?.locals || {},
74
+ status(code) {
75
+ if (res?.status)
76
+ res.status(code);
77
+ return this;
78
+ },
79
+ send(data) {
80
+ if (res?.send)
81
+ return res.send(data);
82
+ return data;
83
+ },
84
+ json(data) {
85
+ if (res?.json)
86
+ return res.json(data);
87
+ return data;
88
+ }
89
+ };
71
90
  }
72
91
  responseProtocolSwitch = async ({ res, resStatus = 200, context, req }) => {
73
92
  const responseData = context({ localeLanguageConverter: req.t });
@@ -78,14 +97,21 @@ class Controller {
78
97
  return queryString ? qs.parse(queryString, { decoder: decodeURIComponent }) : {};
79
98
  };
80
99
  }
81
- export class ControllerSchema extends Controller {
100
+ export class ControllerService extends Controller {
101
+ controllerType = 'default';
102
+ async load({ type }) {
103
+ if (type)
104
+ this.controllerType = type;
105
+ }
82
106
  async schema({ checks, logic, response, }) {
83
- if (!this.req || !this.res)
107
+ const currentReq = this.req;
108
+ const currentRes = this.res;
109
+ if (!currentReq || !currentRes)
84
110
  return;
85
- const payload = { req: this.req, res: this.res };
111
+ const payload = { req: currentReq, res: currentRes };
86
112
  const convertedPayload = {
87
113
  ...payload,
88
- parsedQuerys: this.parsedQuerys(this.req.url)
114
+ parsedQuerys: this.parsedQuerys(currentReq.url)
89
115
  };
90
116
  try {
91
117
  if (checks) {
@@ -96,8 +122,8 @@ export class ControllerSchema extends Controller {
96
122
  }
97
123
  else if (typeof checkResult === 'object' && checkResult.message) {
98
124
  return await this.responseProtocolSwitch({
99
- req: this.req,
100
- res: this.res,
125
+ req: currentReq,
126
+ res: currentRes,
101
127
  context: () => new ResponseSchema({
102
128
  status: checkResult.status || false,
103
129
  message: checkResult.message,
@@ -108,8 +134,8 @@ export class ControllerSchema extends Controller {
108
134
  }
109
135
  if (isInvalid) {
110
136
  return await this.responseProtocolSwitch({
111
- req: this.req,
112
- res: this.res,
137
+ req: currentReq,
138
+ res: currentRes,
113
139
  resStatus: 400,
114
140
  context: ({ localeLanguageConverter }) => new ResponseSchema({
115
141
  status: false,
@@ -124,8 +150,8 @@ export class ControllerSchema extends Controller {
124
150
  }
125
151
  if (logicResult.message) {
126
152
  return await this.responseProtocolSwitch({
127
- req: this.req,
128
- res: this.res,
153
+ req: currentReq,
154
+ res: currentRes,
129
155
  resStatus: 400,
130
156
  context: () => new ResponseSchema({
131
157
  status: logicResult.status || false,
@@ -141,8 +167,8 @@ export class ControllerSchema extends Controller {
141
167
  return resResult.response(resResult);
142
168
  }
143
169
  return await this.responseProtocolSwitch({
144
- req: this.req,
145
- res: this.res,
170
+ req: currentReq,
171
+ res: currentRes,
146
172
  resStatus: 200,
147
173
  context: ({ localeLanguageConverter }) => new ResponseSchema({
148
174
  status: true,
@@ -153,7 +179,7 @@ export class ControllerSchema extends Controller {
153
179
  }
154
180
  }
155
181
  catch (error) {
156
- return this.res.status(500).send({ status: false, message: error.message });
182
+ return currentRes.status(500).send({ status: false, message: error.message });
157
183
  }
158
184
  }
159
185
  }
@@ -3,5 +3,6 @@ import ConfigsService from "./configs";
3
3
  import LoggerService from "./logger";
4
4
  import EventsService from "./events";
5
5
  import LocalizationsService from "./localizations";
6
+ import { ControllerService } from "./controller";
6
7
  import ClientsService from "./clients";
7
- export { SystemService, ConfigsService, LoggerService, EventsService, LocalizationsService, ClientsService };
8
+ export { SystemService, ConfigsService, LoggerService, EventsService, LocalizationsService, ControllerService, ClientsService };
@@ -3,5 +3,6 @@ import ConfigsService from "./configs";
3
3
  import LoggerService from "./logger";
4
4
  import EventsService from "./events";
5
5
  import LocalizationsService from "./localizations";
6
+ import { ControllerService } from "./controller";
6
7
  import ClientsService from "./clients";
7
- export { SystemService, ConfigsService, LoggerService, EventsService, LocalizationsService, ClientsService };
8
+ export { SystemService, ConfigsService, LoggerService, EventsService, LocalizationsService, ControllerService, ClientsService };
@@ -1,7 +1,7 @@
1
1
  // => import dependencies
2
2
  import path from 'path';
3
3
  import { SystemService, ConfigsService, LoggerService, EventsService, LocalizationsService, ClientsService } from '../loader/index';
4
- import { packageName, x, kafkaBrokers, systemLoggerLayer, getTmp, } from '../utils/index';
4
+ import { packageName, x, kafkaBrokers, systemLoggerLayer, getTmp, ControllerService, ProtocolEnum, } from '../utils/index';
5
5
  //
6
6
  let coreHasRun = false;
7
7
  export const core = getTmp();
@@ -59,6 +59,12 @@ const coreLoader = async ({}) => {
59
59
  preloadLang: configs.loaders.localization.preloadLangs
60
60
  }
61
61
  },
62
+ {
63
+ service: ControllerService,
64
+ props: {
65
+ type: ProtocolEnum.HTTP
66
+ }
67
+ },
62
68
  {
63
69
  service: ClientsService,
64
70
  props: {}
@@ -1,3 +1,4 @@
1
+ import { AwilixContainer, LifetimeType } from 'awilix';
1
2
  export declare class X {
2
3
  private container;
3
4
  private initializedNames;
@@ -6,9 +7,10 @@ export declare class X {
6
7
  load(patterns: string | string[], options?: {
7
8
  verbose?: boolean;
8
9
  exclude?: string | Function | (string | Function)[];
10
+ lifetime?: LifetimeType;
9
11
  }): this;
10
- register(Dependency: any): this;
11
- registerAll(dependencies: any[]): this;
12
+ register(Dependency: any, lifetime?: LifetimeType): this;
13
+ registerAll(dependencies: any[], lifetime?: LifetimeType): this;
12
14
  registerInstance(name: string, instance: any): this;
13
15
  initialize(input?: {
14
16
  service: any;
@@ -18,8 +20,10 @@ export declare class X {
18
20
  props?: any;
19
21
  }[], verbose?: boolean): Promise<this>;
20
22
  get<T>(target: string | any): T;
23
+ createScope(): AwilixContainer<any>;
21
24
  get cradle(): any;
22
25
  private isRegistered;
26
+ private getSourceByInstance;
23
27
  }
24
28
  declare const _default: X;
25
29
  export default _default;
@@ -1,4 +1,4 @@
1
- import { createContainer, asClass, asValue, InjectionMode, listModules } from 'awilix';
1
+ import { createContainer, asClass, asValue, InjectionMode, listModules, Lifetime } from 'awilix';
2
2
  import path from 'node:path';
3
3
  export class X {
4
4
  container;
@@ -15,7 +15,7 @@ export class X {
15
15
  return normalizedPath.includes('node_modules') || !normalizedPath.startsWith(projectRoot) ? 'LIB' : 'APP';
16
16
  }
17
17
  load(patterns, options = {}) {
18
- const { verbose = false, exclude = [] } = options;
18
+ const { verbose = false, exclude = [], lifetime = Lifetime.SINGLETON } = options;
19
19
  const cwd = process.cwd();
20
20
  const excludeList = Array.isArray(exclude) ? exclude : [exclude];
21
21
  const resolvedPatterns = (Array.isArray(patterns) ? patterns : [patterns]).map(p => {
@@ -41,12 +41,10 @@ export class X {
41
41
  dependency = Object.values(loaded).find(val => typeof val === 'function' && !!val.prototype && !!val.name);
42
42
  }
43
43
  const isExcluded = excludeList.some(ex => {
44
- if (typeof ex === 'string') {
44
+ if (typeof ex === 'string')
45
45
  return m.path.includes(ex) || m.name === ex;
46
- }
47
- if (typeof ex === 'function') {
46
+ if (typeof ex === 'function')
48
47
  return dependency === ex;
49
- }
50
48
  return false;
51
49
  });
52
50
  if (isExcluded) {
@@ -59,9 +57,11 @@ export class X {
59
57
  const className = dependency.name;
60
58
  const name = className.charAt(0).toLowerCase() + className.slice(1);
61
59
  if (!this.isRegistered(name)) {
62
- this.container.register({ [name]: asClass(dependency).singleton() });
60
+ this.container.register({
61
+ [name]: asClass(dependency).setLifetime(lifetime)
62
+ });
63
63
  if (verbose)
64
- console.log(`[DI][${source}] Registered: ${name}`);
64
+ console.log(`[DI][${source}] Registered (${lifetime}): ${name}`);
65
65
  }
66
66
  }
67
67
  }
@@ -71,18 +71,20 @@ export class X {
71
71
  }
72
72
  return this;
73
73
  }
74
- register(Dependency) {
74
+ register(Dependency, lifetime = Lifetime.SINGLETON) {
75
75
  if (!Dependency?.name)
76
76
  return this;
77
77
  const name = Dependency.name.charAt(0).toLowerCase() + Dependency.name.slice(1);
78
78
  if (this.isRegistered(name))
79
79
  return this;
80
- this.container.register({ [name]: asClass(Dependency).singleton() });
80
+ this.container.register({
81
+ [name]: asClass(Dependency).setLifetime(lifetime)
82
+ });
81
83
  return this;
82
84
  }
83
- registerAll(dependencies) {
85
+ registerAll(dependencies, lifetime = Lifetime.SINGLETON) {
84
86
  if (Array.isArray(dependencies))
85
- dependencies.forEach(dep => this.register(dep));
87
+ dependencies.forEach(dep => this.register(dep, lifetime));
86
88
  return this;
87
89
  }
88
90
  registerInstance(name, instance) {
@@ -105,14 +107,17 @@ export class X {
105
107
  if (name)
106
108
  propsMap.set(name, item.props);
107
109
  }
108
- const registrationKeys = Object.keys(this.container.registrations);
109
- const allKeys = new Set([...propsMap.keys(), ...registrationKeys]);
110
+ const registrations = this.container.registrations;
111
+ const allKeys = new Set([...propsMap.keys(), ...Object.keys(registrations)]);
110
112
  for (const key of allKeys) {
111
113
  if (this.initializedNames.has(key))
112
114
  continue;
115
+ const reg = registrations[key];
116
+ if (!reg || reg.lifetime !== Lifetime.SINGLETON)
117
+ continue;
113
118
  const instance = cradle[key];
114
119
  if (instance && typeof instance.load === 'function') {
115
- const source = instance.constructor && instance.constructor.name ? 'APP' : 'LIB';
120
+ const source = this.getSourceByInstance(instance);
116
121
  try {
117
122
  const props = propsMap.get(key) || {};
118
123
  await instance.load(props);
@@ -136,15 +141,21 @@ export class X {
136
141
  }
137
142
  catch (err) {
138
143
  if (err.message.includes('Cyclic dependencies')) {
139
- console.error('\n❌ [DI] addiction detected!');
140
- console.error(`🔍 Hata Yolu: ${err.resolutionStack}`);
144
+ console.error('\n❌ [DI][CRITICAL] Cyclic dependency detected!');
145
+ console.error(`🔍 Resolution Path: ${err.resolutionStack}`);
141
146
  }
142
147
  throw err;
143
148
  }
144
149
  }
150
+ createScope() {
151
+ return this.container.createScope();
152
+ }
145
153
  get cradle() { return this.container.cradle; }
146
154
  isRegistered(name) {
147
155
  return !!this.container.registrations[name] && this.container.registrations[name].resolve !== undefined;
148
156
  }
157
+ getSourceByInstance(instance) {
158
+ return instance.constructor?.name?.includes('Service') || instance.constructor?.name?.includes('Controller') ? 'APP' : 'LIB';
159
+ }
149
160
  }
150
161
  export default new X();
@@ -1,7 +1,7 @@
1
1
  import x, { X } from './classes/class.x';
2
2
  import locator, { Locator } from './classes/class.service-locator';
3
3
  export * from './classes/class.tmp-file-loader';
4
- export * from './classes/class.controller';
4
+ export * from '../../loader/controller';
5
5
  export * from './classes/class.response';
6
6
  export * from './classes/class.services';
7
7
  export * from './classes/class.interfaces';
@@ -1,7 +1,7 @@
1
1
  import x, { X } from './classes/class.x';
2
2
  import locator, { Locator } from './classes/class.service-locator';
3
3
  export * from './classes/class.tmp-file-loader';
4
- export * from './classes/class.controller';
4
+ export * from '../../loader/controller';
5
5
  export * from './classes/class.response';
6
6
  export * from './classes/class.services';
7
7
  export * from './classes/class.interfaces';