@xrystal/core 3.20.5 ā 3.20.9
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 +13 -20
- package/source/loader/configs/index.d.ts +1 -1
- package/source/loader/configs/index.js +1 -1
- package/source/loader/logger/index.d.ts +1 -1
- package/source/loader/logger/index.js +10 -8
- package/source/project/index.js +3 -1
- package/source/utils/models/classes/class.x.d.ts +7 -4
- package/source/utils/models/classes/class.x.js +62 -90
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.
|
|
4
|
+
"version": "3.20.9",
|
|
5
5
|
"description": "Project core for xrystal",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public",
|
|
@@ -37,34 +37,27 @@
|
|
|
37
37
|
"start": "bun --env-file=../infrastructer/x/environments/.global.env --env-file=../infrastructer/x/environments/.dev.env source/index.js"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"
|
|
41
|
-
"@types/yaml": "^1.9.7",
|
|
40
|
+
"lodash": "^4.17.23",
|
|
42
41
|
"awilix": "^12.0.5",
|
|
43
|
-
"
|
|
44
|
-
"commander": "^13.0.0",
|
|
45
|
-
"ejs": "^3.1.9",
|
|
42
|
+
"yaml": "^2.5.0",
|
|
46
43
|
"handlebars": "^4.7.8",
|
|
47
|
-
"
|
|
44
|
+
"winston": "^3.19.0",
|
|
45
|
+
"winston-daily-rotate-file": "^5.0.0",
|
|
46
|
+
"winston-mongodb": "^7.0.1",
|
|
47
|
+
"kafkajs": "^2.2.4",
|
|
48
48
|
"i18next": "^25.6.3",
|
|
49
49
|
"i18next-fs-backend": "^2.6.1",
|
|
50
50
|
"i18next-http-middleware": "^3.8.2",
|
|
51
|
-
"kafkajs": "^2.2.4",
|
|
52
|
-
"lodash": "^4.17.23",
|
|
53
|
-
"moment-timezone": "^0.6.0",
|
|
54
|
-
"npm": "^11.7.0",
|
|
55
51
|
"ora": "^9.0.0",
|
|
56
|
-
"picocolors": "^1.1.1",
|
|
57
52
|
"qs": "^6.14.1",
|
|
58
53
|
"soap": "^1.6.3",
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"yaml": "^2.5.0"
|
|
54
|
+
"chalk": "^5.6.2",
|
|
55
|
+
"commander": "^13.0.0",
|
|
56
|
+
"picocolors": "^1.1.1"
|
|
63
57
|
},
|
|
64
58
|
"devDependencies": {
|
|
65
|
-
"@types/
|
|
66
|
-
"@types/
|
|
67
|
-
"@types/
|
|
68
|
-
"typescript": "^5.5.3"
|
|
59
|
+
"@types/lodash": "^4.17.23",
|
|
60
|
+
"@types/yaml": "^1.9.7",
|
|
61
|
+
"@types/bun": "^1.3.5"
|
|
69
62
|
}
|
|
70
63
|
}
|
|
@@ -44,7 +44,7 @@ export default class ConfigsService {
|
|
|
44
44
|
systemLoggerLayer: process.env.SYSTEM_LOGGER_LAYER,
|
|
45
45
|
isKafkaPassive: process.env.IS_KAFKA_PASSIVE === 'true' ? true : false,
|
|
46
46
|
kafkaBrokers: process.env?.KAFKA_BROKERS,
|
|
47
|
-
kafkaTopics:
|
|
47
|
+
kafkaTopics: [],
|
|
48
48
|
kafkaLogsTopic: this.kafkaLogsTopic,
|
|
49
49
|
baseApiUri: process.env.HTTPS === 'true' ? process.env.SYSTEM_HTTPS_BASE_API_URI : process.env.SYSTEM_BASE_API_URI,
|
|
50
50
|
port: Number(process.env.PORT),
|
|
@@ -26,7 +26,7 @@ export default class LoggerService implements IService<any> {
|
|
|
26
26
|
systemService: SystemService;
|
|
27
27
|
configsService: ConfigsService;
|
|
28
28
|
});
|
|
29
|
-
load: (
|
|
29
|
+
load: () => Promise<void>;
|
|
30
30
|
winstonLoader: ({ loadPath, loggerLevel }: {
|
|
31
31
|
loadPath: string;
|
|
32
32
|
loggerLevel: string;
|
|
@@ -43,18 +43,18 @@ export default class LoggerService {
|
|
|
43
43
|
constructor({ systemService, configsService }) {
|
|
44
44
|
this.#systemService = systemService;
|
|
45
45
|
this.#configsService = configsService;
|
|
46
|
-
this.
|
|
46
|
+
this.serviceName = this.#systemService?.tmp?.configs?.service;
|
|
47
|
+
this.kafkaLogsTopic = this.#configsService?.all?.kafkaLogsTopic;
|
|
48
|
+
}
|
|
49
|
+
load = async () => {
|
|
47
50
|
winston.addColors(customColors);
|
|
48
51
|
this.winston = winston.createLogger({
|
|
49
|
-
level: this.#configsService
|
|
52
|
+
level: this.#configsService?.all?.systemLoggerLayer || 'info',
|
|
50
53
|
levels: customLevels,
|
|
51
54
|
format: this.getConsoleFormat(),
|
|
52
55
|
transports: [new winston.transports.Console()]
|
|
53
56
|
});
|
|
54
|
-
|
|
55
|
-
load = async ({}) => {
|
|
56
|
-
const loggersConfigs = this.#systemService.tmp.configs.loaders.loggers;
|
|
57
|
-
this.serviceName = this.#systemService.tmp.configs.service;
|
|
57
|
+
const loggersConfigs = this.#systemService?.tmp?.configs?.loaders?.loggers;
|
|
58
58
|
const { kafkaBrokers, isKafkaPassive } = this.#configsService.all;
|
|
59
59
|
const brokers = kafkaBrokers ? String(kafkaBrokers).split(",").map((b) => b.trim()) : [];
|
|
60
60
|
const isKafkaEnabled = isKafkaPassive === false && brokers.length > 0;
|
|
@@ -76,9 +76,11 @@ export default class LoggerService {
|
|
|
76
76
|
this.isKafkaReady = false;
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
+
const logPath = loggersConfigs?.loadPath || "logs";
|
|
80
|
+
const loggerLevel = loggersConfigs?.loggerLevel || "info";
|
|
79
81
|
this.winstonLoader({
|
|
80
|
-
loadPath: path.join(this.#configsService.all.rootFolderPath,
|
|
81
|
-
loggerLevel:
|
|
82
|
+
loadPath: path.join(this.#configsService.all.rootFolderPath, logPath),
|
|
83
|
+
loggerLevel: loggerLevel
|
|
82
84
|
});
|
|
83
85
|
};
|
|
84
86
|
winstonLoader = ({ loadPath, loggerLevel }) => {
|
package/source/project/index.js
CHANGED
|
@@ -16,7 +16,9 @@ const coreLoader = async ({}) => {
|
|
|
16
16
|
await (await x.load([
|
|
17
17
|
path.join(__dirname, '..', 'loader', '**/*.{ts,js}'),
|
|
18
18
|
], {
|
|
19
|
-
exclude: [
|
|
19
|
+
exclude: [
|
|
20
|
+
path.join(__dirname, '..', 'utils', '**/class.x.{ts,js}'),
|
|
21
|
+
]
|
|
20
22
|
}))
|
|
21
23
|
.initialize([
|
|
22
24
|
{
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import { AwilixContainer, LifetimeType } from 'awilix';
|
|
2
|
+
type Constructor<T> = new (...args: any[]) => T;
|
|
3
|
+
type AbstractConstructor<T> = abstract new (...args: any[]) => T;
|
|
2
4
|
declare abstract class XHelper {
|
|
3
5
|
protected checkRegistration(container: AwilixContainer, name: string): boolean;
|
|
4
6
|
}
|
|
5
7
|
declare class X extends XHelper {
|
|
6
8
|
private container;
|
|
7
9
|
private initializedNames;
|
|
10
|
+
private loadedPaths;
|
|
11
|
+
private registeredClasses;
|
|
12
|
+
private isInitializing;
|
|
8
13
|
constructor();
|
|
9
|
-
private getSource;
|
|
10
14
|
load(patterns: string | string[], options?: {
|
|
11
15
|
verbose?: boolean;
|
|
12
16
|
exclude?: string | Function | (string | Function)[];
|
|
13
17
|
lifetime?: LifetimeType;
|
|
14
18
|
}): Promise<this>;
|
|
15
19
|
register(Dependency: any, lifetime?: LifetimeType): this;
|
|
16
|
-
registerAll(dependencies: any[], lifetime?: LifetimeType): this;
|
|
17
20
|
registerInstance(name: string, instance: any): this;
|
|
18
21
|
initialize<T = any>(input?: {
|
|
19
22
|
service: any;
|
|
@@ -22,8 +25,8 @@ declare class X extends XHelper {
|
|
|
22
25
|
service: any;
|
|
23
26
|
props?: T;
|
|
24
27
|
}[], verbose?: boolean): Promise<this>;
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
get<T>(target: Constructor<T> | AbstractConstructor<T> | string): T;
|
|
29
|
+
shutdown(): Promise<void>;
|
|
27
30
|
get cradle(): any;
|
|
28
31
|
}
|
|
29
32
|
declare const _default: X;
|
|
@@ -3,12 +3,15 @@ import path from 'node:path';
|
|
|
3
3
|
import { pathToFileURL } from 'node:url';
|
|
4
4
|
class XHelper {
|
|
5
5
|
checkRegistration(container, name) {
|
|
6
|
-
return !!container.registrations[name]
|
|
6
|
+
return !!container.registrations[name];
|
|
7
7
|
}
|
|
8
8
|
}
|
|
9
9
|
class X extends XHelper {
|
|
10
10
|
container;
|
|
11
11
|
initializedNames = new Set();
|
|
12
|
+
loadedPaths = new Set();
|
|
13
|
+
registeredClasses = new Set();
|
|
14
|
+
isInitializing = false;
|
|
12
15
|
constructor() {
|
|
13
16
|
super();
|
|
14
17
|
this.container = createContainer({
|
|
@@ -16,18 +19,13 @@ class X extends XHelper {
|
|
|
16
19
|
strict: true
|
|
17
20
|
});
|
|
18
21
|
}
|
|
19
|
-
getSource(filePath) {
|
|
20
|
-
const projectRoot = process.cwd().replace(/\\/g, '/');
|
|
21
|
-
const normalizedPath = filePath.replace(/\\/g, '/');
|
|
22
|
-
return normalizedPath.includes('node_modules') || !normalizedPath.startsWith(projectRoot) ? 'LIB' : 'APP';
|
|
23
|
-
}
|
|
24
22
|
async load(patterns, options = {}) {
|
|
25
23
|
const { verbose = false, exclude = [], lifetime = Lifetime.SINGLETON } = options;
|
|
26
24
|
const cwd = process.cwd();
|
|
27
25
|
const excludeList = Array.isArray(exclude) ? exclude : [exclude];
|
|
28
26
|
const resolvedPatterns = (Array.isArray(patterns) ? patterns : [patterns]).map(p => {
|
|
29
27
|
const resolved = path.isAbsolute(p) ? p : path.resolve(cwd, p);
|
|
30
|
-
return resolved.replace(/\\/g, '/');
|
|
28
|
+
return resolved.replace(/\\/g, '/').toLowerCase();
|
|
31
29
|
});
|
|
32
30
|
let modules = [];
|
|
33
31
|
try {
|
|
@@ -37,18 +35,10 @@ class X extends XHelper {
|
|
|
37
35
|
return this;
|
|
38
36
|
}
|
|
39
37
|
for (const m of modules) {
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
if (normalizedMPath === __filename.replace(/\\/g, '/') || normalizedMPath.endsWith('.d.ts'))
|
|
38
|
+
const normalizedMPath = m.path.replace(/\\/g, '/').toLowerCase();
|
|
39
|
+
if (this.loadedPaths.has(normalizedMPath))
|
|
43
40
|
continue;
|
|
44
|
-
|
|
45
|
-
if (typeof ex === 'string') {
|
|
46
|
-
const normalizedEx = ex.replace(/\\/g, '/');
|
|
47
|
-
return normalizedMPath.includes(normalizedEx) || m.name === ex;
|
|
48
|
-
}
|
|
49
|
-
return false;
|
|
50
|
-
});
|
|
51
|
-
if (isPathExcluded)
|
|
41
|
+
if (normalizedMPath === __filename.replace(/\\/g, '/').toLowerCase() || normalizedMPath.endsWith('.d.ts'))
|
|
52
42
|
continue;
|
|
53
43
|
try {
|
|
54
44
|
const fileUrl = pathToFileURL(m.path).href;
|
|
@@ -57,116 +47,98 @@ class X extends XHelper {
|
|
|
57
47
|
if (!dependency) {
|
|
58
48
|
dependency = Object.values(loaded).find(val => typeof val === 'function' && !!val.prototype && !!val.name);
|
|
59
49
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if (isClass) {
|
|
65
|
-
const className = dependency.name;
|
|
66
|
-
const name = className.charAt(0).toLowerCase() + className.slice(1);
|
|
50
|
+
if (typeof dependency === 'function' && !!dependency.prototype && !!dependency.name) {
|
|
51
|
+
if (this.registeredClasses.has(dependency))
|
|
52
|
+
continue;
|
|
53
|
+
const name = dependency.name.charAt(0).toLowerCase() + dependency.name.slice(1);
|
|
67
54
|
if (!this.checkRegistration(this.container, name)) {
|
|
68
55
|
this.container.register({
|
|
69
|
-
[name]: asClass(dependency).
|
|
56
|
+
[name]: asClass(dependency).singleton()
|
|
70
57
|
});
|
|
58
|
+
this.loadedPaths.add(normalizedMPath);
|
|
59
|
+
this.registeredClasses.add(dependency);
|
|
71
60
|
}
|
|
72
61
|
}
|
|
73
62
|
}
|
|
74
63
|
catch (err) {
|
|
75
64
|
if (verbose)
|
|
76
|
-
console.error(`[DI]
|
|
65
|
+
console.error(`[DI] Load Error:`, err.message);
|
|
77
66
|
}
|
|
78
67
|
}
|
|
79
68
|
return this;
|
|
80
69
|
}
|
|
81
70
|
register(Dependency, lifetime = Lifetime.SINGLETON) {
|
|
82
|
-
if (!Dependency?.name)
|
|
71
|
+
if (!Dependency?.name || this.registeredClasses.has(Dependency))
|
|
83
72
|
return this;
|
|
84
73
|
const name = Dependency.name.charAt(0).toLowerCase() + Dependency.name.slice(1);
|
|
85
74
|
if (this.checkRegistration(this.container, name))
|
|
86
75
|
return this;
|
|
87
|
-
this.container.register({ [name]: asClass(Dependency).
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
registerAll(dependencies, lifetime = Lifetime.SINGLETON) {
|
|
91
|
-
if (Array.isArray(dependencies))
|
|
92
|
-
dependencies.forEach(dep => this.register(dep, lifetime));
|
|
76
|
+
this.container.register({ [name]: asClass(Dependency).singleton() });
|
|
77
|
+
this.registeredClasses.add(Dependency);
|
|
93
78
|
return this;
|
|
94
79
|
}
|
|
95
80
|
registerInstance(name, instance) {
|
|
96
81
|
if (!name)
|
|
97
82
|
return this;
|
|
98
83
|
const formattedName = name.charAt(0).toLowerCase() + name.slice(1);
|
|
99
|
-
if (this.checkRegistration(this.container, formattedName))
|
|
100
|
-
return this;
|
|
101
84
|
this.container.register({ [formattedName]: asValue(instance) });
|
|
102
85
|
return this;
|
|
103
86
|
}
|
|
104
87
|
async initialize(input, verbose = false) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
88
|
+
if (this.isInitializing)
|
|
89
|
+
return this;
|
|
90
|
+
this.isInitializing = true;
|
|
91
|
+
try {
|
|
92
|
+
const cradle = this.container.cradle;
|
|
93
|
+
const inputList = input ? (Array.isArray(input) ? input : [input]) : [];
|
|
94
|
+
const propsMap = new Map();
|
|
95
|
+
for (const item of inputList) {
|
|
96
|
+
if (!item?.service)
|
|
97
|
+
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);
|
|
101
|
+
}
|
|
102
|
+
const keys = Object.keys(this.container.registrations);
|
|
103
|
+
for (const key of keys) {
|
|
104
|
+
if (this.initializedNames.has(key))
|
|
105
|
+
continue;
|
|
106
|
+
const reg = this.container.registrations[key];
|
|
107
|
+
if (reg.lifetime !== Lifetime.SINGLETON)
|
|
108
|
+
continue;
|
|
125
109
|
try {
|
|
126
|
-
const
|
|
127
|
-
|
|
110
|
+
const instance = cradle[key];
|
|
111
|
+
if (instance && typeof instance.load === 'function') {
|
|
112
|
+
const props = propsMap.get(key) || {};
|
|
113
|
+
await instance.load(props);
|
|
114
|
+
}
|
|
128
115
|
this.initializedNames.add(key);
|
|
129
116
|
}
|
|
130
117
|
catch (err) {
|
|
131
118
|
if (verbose)
|
|
132
|
-
console.error(`[DI]
|
|
119
|
+
console.error(`[DI] Init Failed (${key}):`, err.message);
|
|
133
120
|
}
|
|
134
121
|
}
|
|
135
122
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
async shutdown(verbose = false) {
|
|
139
|
-
const registrations = this.container.registrations;
|
|
140
|
-
for (const key in registrations) {
|
|
141
|
-
const instance = this.container.cradle[key];
|
|
142
|
-
const shutdownMethod = instance?.dispose || instance?.destroy;
|
|
143
|
-
if (instance && typeof shutdownMethod === 'function') {
|
|
144
|
-
try {
|
|
145
|
-
await shutdownMethod.call(instance);
|
|
146
|
-
if (verbose)
|
|
147
|
-
console.log(`[DI] Shutdown: ${key}`);
|
|
148
|
-
}
|
|
149
|
-
catch (err) {
|
|
150
|
-
console.error(`[DI] Shutdown Error (${key}):`, err.message);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
123
|
+
finally {
|
|
124
|
+
this.isInitializing = false;
|
|
153
125
|
}
|
|
154
|
-
|
|
126
|
+
return this;
|
|
155
127
|
}
|
|
156
128
|
get(target) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (err.message.includes('Cyclic dependencies')) {
|
|
165
|
-
console.error(`\nā [DI][CRITICAL] Cyclic dependency detected!\nš Path: ${err.resolutionStack}`);
|
|
166
|
-
}
|
|
167
|
-
throw err;
|
|
168
|
-
}
|
|
129
|
+
const resolveName = typeof target === 'function'
|
|
130
|
+
? target.name.charAt(0).toLowerCase() + target.name.slice(1)
|
|
131
|
+
: target;
|
|
132
|
+
return this.container.resolve(resolveName);
|
|
133
|
+
}
|
|
134
|
+
async shutdown() {
|
|
135
|
+
await this.container.dispose();
|
|
169
136
|
}
|
|
170
137
|
get cradle() { return this.container.cradle; }
|
|
171
138
|
}
|
|
172
|
-
|
|
139
|
+
const X_SYMBOL = Symbol.for('X');
|
|
140
|
+
const globalObj = global;
|
|
141
|
+
if (!globalObj[X_SYMBOL]) {
|
|
142
|
+
globalObj[X_SYMBOL] = new X();
|
|
143
|
+
}
|
|
144
|
+
export default globalObj[X_SYMBOL];
|