@xrystal/core 3.16.3 → 3.16.7

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.16.3",
4
+ "version": "3.16.7",
5
5
  "description": "Project core for xrystal",
6
6
  "publishConfig": {
7
7
  "access": "public",
@@ -1,18 +1,29 @@
1
1
  import { AsyncLocalStorage } from 'node:async_hooks';
2
+ import LoggerService from '../logger';
2
3
  import { ProtocolEnum } from '../../utils/index';
3
4
  export declare const controllerContextStorage: AsyncLocalStorage<{
4
5
  protocol?: ProtocolEnum;
5
6
  ctx?: any;
6
7
  req?: any;
7
8
  res?: any;
8
- metadata?: Record<string, any>;
9
+ metadata?: {
10
+ locals: Record<string, any>;
11
+ _code?: number;
12
+ _contentType?: string;
13
+ _isRaw?: boolean;
14
+ };
9
15
  }>;
10
16
  export declare const getControllerCtx: () => {
11
17
  protocol?: ProtocolEnum;
12
18
  ctx?: any;
13
19
  req?: any;
14
20
  res?: any;
15
- metadata?: Record<string, any>;
21
+ metadata?: {
22
+ locals: Record<string, any>;
23
+ _code?: number;
24
+ _contentType?: string;
25
+ _isRaw?: boolean;
26
+ };
16
27
  };
17
28
  export interface CustomRequest {
18
29
  accounts?: any;
@@ -22,7 +33,7 @@ export interface CustomRequest {
22
33
  body?: any;
23
34
  params: Record<string, any>;
24
35
  query: Record<string, any>;
25
- t?: any;
36
+ t: (k: string) => string;
26
37
  }
27
38
  export interface CustomResponse {
28
39
  status: (code: number) => CustomResponse;
@@ -31,23 +42,28 @@ export interface CustomResponse {
31
42
  locals: Record<string, any>;
32
43
  }
33
44
  declare abstract class Controller {
34
- protected loggerService: any;
45
+ protected loggerService: LoggerService;
35
46
  protected supportedProtocols: ProtocolEnum[];
36
47
  constructor({ loggerService }: any);
48
+ protected get protocol(): ProtocolEnum;
37
49
  protected get currentStore(): {
38
50
  protocol?: ProtocolEnum;
39
51
  ctx?: any;
40
52
  req?: any;
41
53
  res?: any;
42
- metadata?: Record<string, any>;
54
+ metadata?: {
55
+ locals: Record<string, any>;
56
+ _code?: number;
57
+ _contentType?: string;
58
+ _isRaw?: boolean;
59
+ };
43
60
  };
44
- protected get protocol(): ProtocolEnum;
45
61
  protected get req(): CustomRequest;
46
62
  protected get res(): CustomResponse;
47
- protected responseProtocolSwitch: ({ res, resStatus, context }: any) => Promise<any>;
48
63
  protected parsedQuerys: (url: string) => Record<string, any>;
49
64
  }
50
65
  export declare abstract class ControllerService extends Controller {
66
+ constructor({ loggerService }: any);
51
67
  load(props?: {
52
68
  type?: ProtocolEnum | ProtocolEnum[];
53
69
  }): Promise<void>;
@@ -9,13 +9,11 @@ class Controller {
9
9
  constructor({ loggerService }) {
10
10
  this.loggerService = loggerService;
11
11
  }
12
- get currentStore() { return getControllerCtx(); }
13
12
  get protocol() {
14
- const incomingProtocol = this.currentStore?.protocol || ProtocolEnum.HTTP;
15
- if (!this.supportedProtocols.includes(incomingProtocol)) {
16
- throw new Error(`[DI] Protocol ${incomingProtocol} not supported.`);
17
- }
18
- return incomingProtocol;
13
+ return this.currentStore?.protocol || ProtocolEnum.HTTP;
14
+ }
15
+ get currentStore() {
16
+ return getControllerCtx();
19
17
  }
20
18
  get req() {
21
19
  const store = this.currentStore;
@@ -23,65 +21,66 @@ class Controller {
23
21
  if (!store)
24
22
  return { url: '', method: '', headers: {}, params: {}, query: {}, t: identityT };
25
23
  const { ctx, req: nativeReq } = store;
26
- const reqSource = nativeReq || ctx?.request || ctx?.data?.request;
24
+ const source = nativeReq || ctx?.request || ctx;
27
25
  return {
28
- url: reqSource?.url || '',
29
- method: reqSource?.method || 'GET',
30
- headers: reqSource?.headers && typeof reqSource.headers.entries === 'function'
31
- ? Object.fromEntries(reqSource.headers.entries())
32
- : (ctx?.headers || nativeReq?.headers || {}),
33
- body: ctx?.body || nativeReq?.body,
34
- params: ctx?.params || nativeReq?.params || {},
35
- query: ctx?.query || nativeReq?.query || {},
36
- accounts: ctx?.user || ctx?.data?.user || nativeReq?.accounts,
37
- t: ctx?.t || ctx?.data?.t || nativeReq?.t || identityT
26
+ url: source?.url || '',
27
+ method: source?.method || 'GET',
28
+ headers: source?.headers && typeof source.headers.entries === 'function'
29
+ ? Object.fromEntries(source.headers.entries())
30
+ : (source?.headers || {}),
31
+ body: ctx?.body || nativeReq?.body || source?.body,
32
+ params: ctx?.params || nativeReq?.params || source?.params || {},
33
+ query: ctx?.query || nativeReq?.query || source?.query || {},
34
+ accounts: ctx?.user || nativeReq?.accounts || source?.accounts,
35
+ t: ctx?.t || nativeReq?.t || identityT
38
36
  };
39
37
  }
40
38
  get res() {
41
39
  const store = this.currentStore;
40
+ const self = this;
42
41
  const fallbackRes = {
43
42
  status: function () { return this; },
44
- send: (d) => new Response(typeof d === 'string' ? d : JSON.stringify(d), { status: 500, headers: { 'content-type': 'application/json' } }),
43
+ send: (d) => d instanceof Response ? d : new Response(JSON.stringify(d), { status: 500 }),
45
44
  json: function (d) { return this.send(d); },
46
45
  locals: {}
47
46
  };
48
47
  if (!store)
49
48
  return fallbackRes;
50
- if (store.ctx || store.req) {
51
- if (!store.metadata)
52
- store.metadata = { locals: {} };
53
- const currentProtocol = this.protocol;
54
- return {
55
- locals: store.metadata.locals,
56
- status(code) {
57
- store.metadata._code = code;
58
- return this;
59
- },
60
- send: (data) => {
61
- if (currentProtocol === ProtocolEnum.WEBSOCKET)
62
- return data;
63
- const isBinary = data instanceof Blob || data instanceof Uint8Array || data instanceof ArrayBuffer;
64
- const isRaw = store.metadata?._isRaw || isBinary;
65
- const contentType = store.metadata?._contentType || (isBinary ? 'application/octet-stream' : 'application/json');
66
- const body = isRaw ? data : JSON.stringify(data && typeof data === 'object' ? (data.getResponse || data) : data);
67
- return new Response(body, {
68
- status: store.metadata?._code || 200,
69
- headers: { 'content-type': contentType }
70
- });
71
- },
72
- json(data) { return this.send(data); }
73
- };
74
- }
75
- return store.res || fallbackRes;
49
+ if (!store.metadata)
50
+ store.metadata = { locals: {} };
51
+ return {
52
+ get locals() { return store.metadata.locals; },
53
+ status(code) {
54
+ store.metadata._code = code;
55
+ return this;
56
+ },
57
+ send(data) {
58
+ if (self.protocol === ProtocolEnum.WEBSOCKET)
59
+ return data;
60
+ if (data instanceof Response)
61
+ return data;
62
+ const isBinary = data instanceof Blob || data instanceof Uint8Array || data instanceof ArrayBuffer;
63
+ const isRaw = store.metadata?._isRaw || isBinary;
64
+ let contentType = store.metadata?._contentType;
65
+ if (!contentType) {
66
+ contentType = isRaw ? 'application/octet-stream' : 'application/json';
67
+ }
68
+ const status = store.metadata?._code || 200;
69
+ const body = isRaw || typeof data === 'string'
70
+ ? data
71
+ : JSON.stringify(data?.getResponse ? data.getResponse : data);
72
+ return new Response(body, {
73
+ status,
74
+ headers: { 'content-type': contentType }
75
+ });
76
+ },
77
+ json(data) { return this.send(data); }
78
+ };
76
79
  }
77
- responseProtocolSwitch = async ({ res, resStatus = 200, context }) => {
78
- const responseData = context({ localeLanguageConverter: this.req?.t });
79
- return res.status(resStatus).send(responseData);
80
- };
81
80
  parsedQuerys = (url) => {
82
81
  try {
83
- const queryString = url.includes('?') ? url.split('?')[1] : '';
84
- return queryString ? qs.parse(queryString, { decoder: decodeURIComponent }) : {};
82
+ const queryPart = url.split('?')[1];
83
+ return queryPart ? qs.parse(queryPart, { decoder: decodeURIComponent }) : {};
85
84
  }
86
85
  catch {
87
86
  return {};
@@ -89,45 +88,49 @@ class Controller {
89
88
  };
90
89
  }
91
90
  export class ControllerService extends Controller {
91
+ constructor({ loggerService }) {
92
+ super({ loggerService });
93
+ }
92
94
  async load(props = {}) {
93
95
  if (props.type)
94
96
  this.supportedProtocols = Array.isArray(props.type) ? props.type : [props.type];
95
97
  }
96
98
  async schema({ checks, logic, response }) {
97
99
  try {
98
- const currentReq = this.req;
99
- const currentRes = this.res;
100
- if (!currentReq.url)
101
- throw new Error("Request URL is missing from context");
102
- const payload = { req: currentReq, res: currentRes };
103
- const convertedPayload = { ...payload, parsedQuerys: this.parsedQuerys(currentReq.url) };
100
+ const req = this.req;
101
+ const res = this.res;
102
+ const payload = { req, res };
103
+ const convertedPayload = { ...payload, query: this.parsedQuerys(req.url) };
104
104
  if (checks) {
105
105
  const checkResult = await checks({ payload, convertedPayload });
106
- if (checkResult?.message) {
107
- return await this.responseProtocolSwitch({ res: currentRes, context: () => new ResponseSchema(checkResult).getResponse });
106
+ if (checkResult) {
107
+ return res.status(checkResult.code || 400).send(new ResponseSchema(checkResult).getResponse);
108
108
  }
109
109
  }
110
110
  const logicResult = await logic({ payload, convertedPayload });
111
111
  if (logicResult?.response instanceof Function)
112
112
  return logicResult.response(logicResult.payload);
113
- if (logicResult?.message) {
114
- return await this.responseProtocolSwitch({ res: currentRes, resStatus: 400, context: () => new ResponseSchema(logicResult).getResponse });
115
- }
113
+ if (logicResult instanceof Response)
114
+ return logicResult;
116
115
  if (response) {
117
116
  const resResult = await response({ payload, convertedPayload, logicResult });
118
117
  const successObj = {
119
118
  status: true,
120
119
  message: Array.isArray(resResult.message)
121
- ? responseMessageHelper.successFully(resResult.message[0], resResult.message[1], currentReq.t)
120
+ ? responseMessageHelper.successFully(resResult.message[0], resResult.message[1], req.t)
122
121
  : resResult.message,
123
- payload: logicResult?.payload || logicResult
122
+ payload: logicResult?.payload !== undefined ? logicResult.payload : logicResult
124
123
  };
125
- return await this.responseProtocolSwitch({ res: currentRes, resStatus: 200, context: () => new ResponseSchema(successObj).getResponse });
124
+ return res.status(200).send(new ResponseSchema(successObj).getResponse);
126
125
  }
127
- return currentRes.send(logicResult?.payload !== undefined ? logicResult.payload : logicResult);
126
+ return res.send(logicResult?.payload !== undefined ? logicResult.payload : logicResult);
128
127
  }
129
128
  catch (error) {
130
- return this.res.status(500).send({ status: false, message: error.message });
129
+ this.loggerService.winston.error(`Controller Error: ${error.message}`, { stack: error.stack });
130
+ return this.res.status(500).send({
131
+ status: false,
132
+ message: error.message
133
+ });
131
134
  }
132
135
  }
133
136
  }