@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 +1 -1
- package/source/{utils/models/classes/class.controller.d.ts → loader/controller/index.d.ts} +26 -8
- package/source/{utils/models/classes/class.controller.js → loader/controller/index.js} +80 -54
- package/source/loader/index.d.ts +2 -1
- package/source/loader/index.js +2 -1
- package/source/project/index.js +7 -1
- package/source/utils/models/classes/class.x.d.ts +6 -2
- package/source/utils/models/classes/class.x.js +28 -17
- package/source/utils/models/index.d.ts +1 -1
- package/source/utils/models/index.js +1 -1
package/package.json
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
21
|
-
protected
|
|
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
|
-
|
|
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
|
|
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 {
|
|
3
|
-
import { ProtocolEnum, responseMessageHelper, ResponseSchema
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
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
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
|
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
|
-
|
|
107
|
+
const currentReq = this.req;
|
|
108
|
+
const currentRes = this.res;
|
|
109
|
+
if (!currentReq || !currentRes)
|
|
84
110
|
return;
|
|
85
|
-
const payload = { req:
|
|
111
|
+
const payload = { req: currentReq, res: currentRes };
|
|
86
112
|
const convertedPayload = {
|
|
87
113
|
...payload,
|
|
88
|
-
parsedQuerys: this.parsedQuerys(
|
|
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:
|
|
100
|
-
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:
|
|
112
|
-
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:
|
|
128
|
-
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:
|
|
145
|
-
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
|
|
182
|
+
return currentRes.status(500).send({ status: false, message: error.message });
|
|
157
183
|
}
|
|
158
184
|
}
|
|
159
185
|
}
|
package/source/loader/index.d.ts
CHANGED
|
@@ -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 };
|
package/source/loader/index.js
CHANGED
|
@@ -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 };
|
package/source/project/index.js
CHANGED
|
@@ -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({
|
|
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({
|
|
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
|
|
109
|
-
const allKeys = new Set([...propsMap.keys(), ...
|
|
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 =
|
|
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]
|
|
140
|
-
console.error(`🔍
|
|
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 '
|
|
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 '
|
|
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';
|