@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,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?:
|
|
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?:
|
|
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
|
|
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:
|
|
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?:
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
|
24
|
+
const source = nativeReq || ctx?.request || ctx;
|
|
27
25
|
return {
|
|
28
|
-
url:
|
|
29
|
-
method:
|
|
30
|
-
headers:
|
|
31
|
-
? Object.fromEntries(
|
|
32
|
-
: (
|
|
33
|
-
body: ctx?.body || nativeReq?.body,
|
|
34
|
-
params: ctx?.params || nativeReq?.params || {},
|
|
35
|
-
query: ctx?.query || nativeReq?.query || {},
|
|
36
|
-
accounts: ctx?.user ||
|
|
37
|
-
t: ctx?.t ||
|
|
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) =>
|
|
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.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
|
84
|
-
return
|
|
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
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
107
|
-
return
|
|
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
|
|
114
|
-
return
|
|
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],
|
|
120
|
+
? responseMessageHelper.successFully(resResult.message[0], resResult.message[1], req.t)
|
|
122
121
|
: resResult.message,
|
|
123
|
-
payload: logicResult?.payload
|
|
122
|
+
payload: logicResult?.payload !== undefined ? logicResult.payload : logicResult
|
|
124
123
|
};
|
|
125
|
-
return
|
|
124
|
+
return res.status(200).send(new ResponseSchema(successObj).getResponse);
|
|
126
125
|
}
|
|
127
|
-
return
|
|
126
|
+
return res.send(logicResult?.payload !== undefined ? logicResult.payload : logicResult);
|
|
128
127
|
}
|
|
129
128
|
catch (error) {
|
|
130
|
-
|
|
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
|
}
|