@xrystal/core 3.9.0 → 3.9.3
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 -5
- package/source/loader/clients/index.d.ts +3 -2
- package/source/loader/clients/index.js +11 -6
- package/source/utils/models/classes/class.services.d.ts +18 -42
- package/source/utils/models/classes/class.services.js +79 -61
- package/source/utils/models/enums/index.d.ts +5 -0
- package/source/utils/models/enums/index.js +6 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"author": "Yusuf Yasir KAYGUSUZ",
|
|
3
3
|
"name": "@xrystal/core",
|
|
4
|
-
"version": "3.9.
|
|
4
|
+
"version": "3.9.3",
|
|
5
5
|
"description": "Project core for xrystal",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public",
|
|
@@ -49,8 +49,6 @@
|
|
|
49
49
|
"i18next-http-middleware": "^3.8.2",
|
|
50
50
|
"kafkajs": "^2.2.4",
|
|
51
51
|
"moment-timezone": "^0.6.0",
|
|
52
|
-
"nodemailer": "^7.0.11",
|
|
53
|
-
"nodemailer-express-handlebars": "^7.0.0",
|
|
54
52
|
"ora": "^9.0.0",
|
|
55
53
|
"picocolors": "^1.1.1",
|
|
56
54
|
"qs": "^6.14.1",
|
|
@@ -64,8 +62,6 @@
|
|
|
64
62
|
"@types/bun": "^1.3.5",
|
|
65
63
|
"@types/minimist": "^1.2.5",
|
|
66
64
|
"@types/node": "^25.0.6",
|
|
67
|
-
"@types/nodemailer": "^7.0.4",
|
|
68
|
-
"@types/nodemailer-express-handlebars": "^4.0.6",
|
|
69
65
|
"typescript": "^5.5.3"
|
|
70
66
|
}
|
|
71
67
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import ConfigsService from '../configs';
|
|
2
2
|
export default class ClientsService {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
#private;
|
|
4
|
+
static get instances(): Record<string, any>;
|
|
5
|
+
static set instances(value: Record<string, any>);
|
|
5
6
|
load({ configs }: {
|
|
6
7
|
configs: ConfigsService;
|
|
7
8
|
}): Promise<void>;
|
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import { BaseApiClient } from '../../utils/index';
|
|
1
|
+
import { BaseApiClient, CoreServiceEnum } from '../../utils/index';
|
|
2
2
|
export default class ClientsService {
|
|
3
|
-
static services = {};
|
|
4
|
-
|
|
3
|
+
static #services = {};
|
|
4
|
+
static get instances() {
|
|
5
|
+
return this.#services;
|
|
6
|
+
}
|
|
7
|
+
static set instances(value) {
|
|
8
|
+
this.#services = { ...this.#services, ...value };
|
|
9
|
+
}
|
|
5
10
|
async load({ configs }) {
|
|
6
|
-
const
|
|
7
|
-
clientName:
|
|
11
|
+
const baseClient = new BaseApiClient({
|
|
12
|
+
clientName: CoreServiceEnum.BASE_API_CLIENT,
|
|
8
13
|
baseURL: configs.all.baseApiUri || ''
|
|
9
14
|
});
|
|
10
|
-
ClientsService.
|
|
15
|
+
ClientsService.instances[CoreServiceEnum.BASE_API_CLIENT] = baseClient;
|
|
11
16
|
}
|
|
12
17
|
}
|
|
@@ -1,66 +1,42 @@
|
|
|
1
|
-
import nodemailer from 'nodemailer';
|
|
2
1
|
import { ConfigsService, LoggerService } from '../../../loader';
|
|
3
|
-
export declare
|
|
2
|
+
export declare class ClientStore {
|
|
3
|
+
private static _store;
|
|
4
|
+
static get(clientName: string): any;
|
|
5
|
+
static set(clientName: string, data: Record<string, any>): void;
|
|
6
|
+
}
|
|
7
|
+
export declare abstract class Client {
|
|
4
8
|
protected configService: ConfigsService;
|
|
5
9
|
protected logger: LoggerService;
|
|
6
10
|
clientName: string;
|
|
7
11
|
protected baseURL: string;
|
|
8
12
|
protected version: string | null;
|
|
9
13
|
protected timeout: number;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
version?: string;
|
|
14
|
-
timeout?: number;
|
|
15
|
-
});
|
|
14
|
+
protected authConfigs: any;
|
|
15
|
+
constructor({ clientName, baseURL, version, timeout, auth }: any);
|
|
16
|
+
protected resolvePath(obj: any, path: string): any;
|
|
16
17
|
static cryptoHashGenerate: ({ algorithm, input, digest }: {
|
|
17
18
|
algorithm: string;
|
|
18
19
|
input: string;
|
|
19
20
|
digest?: string;
|
|
20
21
|
}) => string;
|
|
21
|
-
static generateRandomNumber: ({ length }: {
|
|
22
|
-
length?: number;
|
|
23
|
-
}) => string;
|
|
24
22
|
}
|
|
25
|
-
export declare class BaseApiClient extends
|
|
26
|
-
constructor(config:
|
|
27
|
-
clientName: string;
|
|
28
|
-
baseURL: string;
|
|
29
|
-
version?: string;
|
|
30
|
-
timeout?: number;
|
|
31
|
-
});
|
|
23
|
+
export declare class BaseApiClient extends Client {
|
|
24
|
+
constructor(config: any);
|
|
32
25
|
request(path: string, options?: RequestInit & {
|
|
33
26
|
version?: string;
|
|
34
27
|
}): Promise<Response>;
|
|
35
28
|
}
|
|
36
29
|
export declare abstract class AuthenticatedApiClient extends BaseApiClient {
|
|
37
|
-
|
|
38
|
-
constructor(config:
|
|
39
|
-
clientName: string;
|
|
40
|
-
baseURL: string;
|
|
41
|
-
version?: string;
|
|
42
|
-
timeout?: number;
|
|
43
|
-
});
|
|
30
|
+
private _authPromise;
|
|
31
|
+
constructor(config: any);
|
|
44
32
|
request(path: string, options?: RequestInit & {
|
|
45
33
|
version?: string;
|
|
46
34
|
}): Promise<Response>;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
constructor(config: {
|
|
51
|
-
clientName: string;
|
|
52
|
-
baseURL: string;
|
|
53
|
-
version?: string;
|
|
54
|
-
timeout?: number;
|
|
55
|
-
});
|
|
56
|
-
nodemailerLoader(config: any): nodemailer.Transporter<import("nodemailer/lib/smtp-transport").SentMessageInfo, import("nodemailer/lib/smtp-transport").Options>;
|
|
35
|
+
private _synchronizedAuthentication;
|
|
36
|
+
private internalLogin;
|
|
37
|
+
authentication(): Promise<any>;
|
|
57
38
|
}
|
|
58
|
-
export declare class SoapClient extends
|
|
59
|
-
constructor(config:
|
|
60
|
-
clientName: string;
|
|
61
|
-
baseURL: string;
|
|
62
|
-
version?: string;
|
|
63
|
-
timeout?: number;
|
|
64
|
-
});
|
|
39
|
+
export declare class SoapClient extends Client {
|
|
40
|
+
constructor(config: any);
|
|
65
41
|
call(methodName: string, args: any): Promise<any>;
|
|
66
42
|
}
|
|
@@ -1,59 +1,66 @@
|
|
|
1
|
-
import { createHash } from 'node:crypto';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import nodemailer from 'nodemailer';
|
|
4
|
-
import hbs from 'nodemailer-express-handlebars';
|
|
1
|
+
import { createHash, createHmac } from 'node:crypto';
|
|
5
2
|
import soap from 'soap';
|
|
6
3
|
import { ConfigsService, LoggerService } from '../../../loader';
|
|
7
|
-
import {
|
|
8
|
-
export class
|
|
4
|
+
import { x } from '../../index';
|
|
5
|
+
export class ClientStore {
|
|
6
|
+
static _store = {};
|
|
7
|
+
static get(clientName) { return this._store[clientName] || {}; }
|
|
8
|
+
static set(clientName, data) {
|
|
9
|
+
this._store[clientName] = { ...this._store[clientName], ...data };
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class Client {
|
|
9
13
|
configService = x.get(ConfigsService);
|
|
10
14
|
logger = x.get(LoggerService);
|
|
11
15
|
clientName;
|
|
12
16
|
baseURL;
|
|
13
17
|
version = null;
|
|
14
18
|
timeout = 15000;
|
|
15
|
-
|
|
19
|
+
authConfigs;
|
|
20
|
+
constructor({ clientName, baseURL, version, timeout, auth }) {
|
|
16
21
|
this.clientName = clientName;
|
|
17
22
|
this.baseURL = baseURL;
|
|
18
23
|
this.version = version || null;
|
|
24
|
+
this.authConfigs = auth;
|
|
19
25
|
if (timeout)
|
|
20
26
|
this.timeout = timeout;
|
|
27
|
+
if (auth?.token) {
|
|
28
|
+
ClientStore.set(clientName, { accessToken: auth.token });
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
resolvePath(obj, path) {
|
|
32
|
+
return path.split('.').reduce((prev, curr) => prev ? prev[curr] : undefined, obj);
|
|
21
33
|
}
|
|
22
34
|
static cryptoHashGenerate = ({ algorithm, input, digest = 'hex' }) => {
|
|
23
35
|
return createHash(algorithm).update(input).digest(digest);
|
|
24
36
|
};
|
|
25
|
-
static generateRandomNumber = ({ length = 10 }) => {
|
|
26
|
-
let result = '';
|
|
27
|
-
for (let i = 0; i < length; i++) {
|
|
28
|
-
result += Math.floor(Math.random() * 10).toString();
|
|
29
|
-
}
|
|
30
|
-
return result;
|
|
31
|
-
};
|
|
32
37
|
}
|
|
33
|
-
export class BaseApiClient extends
|
|
34
|
-
constructor(config) {
|
|
35
|
-
super(config);
|
|
36
|
-
}
|
|
37
|
-
// version opsiyonel yapıldı, default constructor'dan gelir ama istek anında ezilebilir
|
|
38
|
+
export class BaseApiClient extends Client {
|
|
39
|
+
constructor(config) { super(config); }
|
|
38
40
|
async request(path, options = {}) {
|
|
39
41
|
const base = this.baseURL.replace(/\/$/, '');
|
|
40
|
-
// İstekte versiyon varsa onu, yoksa sınıftaki default versiyonu kullan
|
|
41
42
|
const activeVersion = options.version !== undefined ? options.version : this.version;
|
|
42
43
|
const ver = activeVersion ? `/${activeVersion.replace(/^\//, '')}` : '';
|
|
43
44
|
const url = `${base}${ver}${path}`;
|
|
44
45
|
const store = LoggerService.storage.getStore();
|
|
45
46
|
const correlationId = store?.get('correlationId');
|
|
46
47
|
const headers = new Headers(options.headers || {});
|
|
47
|
-
|
|
48
|
-
headers.set('Content-Type', 'application/json');
|
|
48
|
+
headers.set('Content-Type', 'application/json');
|
|
49
49
|
if (correlationId)
|
|
50
50
|
headers.set('x-correlation-id', correlationId);
|
|
51
|
-
|
|
52
|
-
|
|
51
|
+
const systemSecret = this.configService.all.internalSecret || process.env.INTERNAL_SECRET;
|
|
52
|
+
if (systemSecret) {
|
|
53
|
+
const timestamp = Date.now().toString();
|
|
54
|
+
const signature = createHmac('sha256', systemSecret)
|
|
55
|
+
.update(timestamp + this.clientName)
|
|
56
|
+
.digest('hex');
|
|
57
|
+
headers.set('x-internal-signature', signature);
|
|
58
|
+
headers.set('x-internal-timestamp', timestamp);
|
|
59
|
+
headers.set('x-internal-client', this.clientName);
|
|
60
|
+
}
|
|
53
61
|
const controller = new AbortController();
|
|
54
62
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
55
63
|
try {
|
|
56
|
-
// version alanını fetch options'dan ayıklıyoruz
|
|
57
64
|
const { version, ...fetchOptions } = options;
|
|
58
65
|
const response = await fetch(url, { ...fetchOptions, headers, signal: controller.signal });
|
|
59
66
|
clearTimeout(timeoutId);
|
|
@@ -66,56 +73,67 @@ export class BaseApiClient extends Service {
|
|
|
66
73
|
}
|
|
67
74
|
}
|
|
68
75
|
export class AuthenticatedApiClient extends BaseApiClient {
|
|
69
|
-
|
|
70
|
-
constructor(config) {
|
|
71
|
-
super(config);
|
|
72
|
-
}
|
|
76
|
+
_authPromise = null;
|
|
77
|
+
constructor(config) { super(config); }
|
|
73
78
|
async request(path, options = {}) {
|
|
74
|
-
const
|
|
79
|
+
const headerName = this.authConfigs?.header || 'Authorization';
|
|
80
|
+
const prefix = this.authConfigs?.prefix ?? 'Bearer';
|
|
81
|
+
const injectToken = (h, t) => {
|
|
82
|
+
const value = prefix ? `${prefix} ${t}` : t;
|
|
83
|
+
h.set(headerName, value);
|
|
84
|
+
};
|
|
85
|
+
let store = ClientStore.get(this.clientName);
|
|
75
86
|
const headers = new Headers(options.headers || {});
|
|
76
|
-
if (
|
|
77
|
-
injectToken(headers,
|
|
87
|
+
if (store.accessToken)
|
|
88
|
+
injectToken(headers, store.accessToken);
|
|
78
89
|
options.headers = headers;
|
|
79
90
|
let response = await super.request(path, options);
|
|
80
91
|
if (response.status === 401) {
|
|
81
|
-
await this.
|
|
82
|
-
|
|
92
|
+
await this._synchronizedAuthentication();
|
|
93
|
+
store = ClientStore.get(this.clientName);
|
|
94
|
+
if (store.accessToken) {
|
|
83
95
|
const retryHeaders = new Headers(options.headers);
|
|
84
|
-
injectToken(retryHeaders,
|
|
96
|
+
injectToken(retryHeaders, store.accessToken);
|
|
85
97
|
return super.request(path, { ...options, headers: retryHeaders });
|
|
86
98
|
}
|
|
87
99
|
}
|
|
88
100
|
return response;
|
|
89
101
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
102
|
+
async _synchronizedAuthentication() {
|
|
103
|
+
if (this._authPromise)
|
|
104
|
+
return this._authPromise;
|
|
105
|
+
this._authPromise = (async () => {
|
|
106
|
+
await this.authentication();
|
|
107
|
+
await this.internalLogin();
|
|
108
|
+
})().finally(() => { this._authPromise = null; });
|
|
109
|
+
return this._authPromise;
|
|
94
110
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
async internalLogin() {
|
|
112
|
+
if (!this.authConfigs || !this.authConfigs.endpoint)
|
|
113
|
+
return;
|
|
114
|
+
const { endpoint, payload, method, tokenPath } = this.authConfigs;
|
|
115
|
+
try {
|
|
116
|
+
const response = await fetch(`${this.baseURL}${endpoint}`, {
|
|
117
|
+
method: method || 'POST',
|
|
118
|
+
headers: { 'Content-Type': 'application/json' },
|
|
119
|
+
body: JSON.stringify(payload)
|
|
120
|
+
});
|
|
121
|
+
const data = await response.json();
|
|
122
|
+
const token = this.resolvePath(data, tokenPath || 'accessToken');
|
|
123
|
+
if (token)
|
|
124
|
+
ClientStore.set(this.clientName, { accessToken: token });
|
|
125
|
+
return data;
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
113
130
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
constructor(config) {
|
|
117
|
-
super(config);
|
|
131
|
+
async authentication() {
|
|
132
|
+
return true;
|
|
118
133
|
}
|
|
134
|
+
}
|
|
135
|
+
export class SoapClient extends Client {
|
|
136
|
+
constructor(config) { super(config); }
|
|
119
137
|
async call(methodName, args) {
|
|
120
138
|
try {
|
|
121
139
|
const client = await soap.createClientAsync(this.baseURL);
|
|
@@ -86,12 +86,17 @@ export declare enum WsKeyEnum {
|
|
|
86
86
|
ROOM = "ws:room"
|
|
87
87
|
}
|
|
88
88
|
export declare enum TokensEnum {
|
|
89
|
+
INTERNAL_API_TOKEN = "internal_api_key",
|
|
89
90
|
CSRF_TOKEN = "csrf_token",
|
|
90
91
|
ACCESS_TOKEN = "access_token",
|
|
91
92
|
REFRESH_TOKEN = "refresh_token",
|
|
92
93
|
REFERENCE_TOKEN = "reference_token",
|
|
93
94
|
PERSONAL_ACCESS_TOKEN = "personal_access_token"
|
|
94
95
|
}
|
|
96
|
+
export declare enum CoreServiceEnum {
|
|
97
|
+
BASE_API_CLIENT = "base_client_name",
|
|
98
|
+
SOAP_API_CLIENT = "soap_api_client"
|
|
99
|
+
}
|
|
95
100
|
export declare enum EndpointResourceEnum {
|
|
96
101
|
EXAMPLE = "example",
|
|
97
102
|
FULL = "full",
|
|
@@ -103,12 +103,18 @@ export var WsKeyEnum;
|
|
|
103
103
|
})(WsKeyEnum || (WsKeyEnum = {}));
|
|
104
104
|
export var TokensEnum;
|
|
105
105
|
(function (TokensEnum) {
|
|
106
|
+
TokensEnum["INTERNAL_API_TOKEN"] = "internal_api_key";
|
|
106
107
|
TokensEnum["CSRF_TOKEN"] = "csrf_token";
|
|
107
108
|
TokensEnum["ACCESS_TOKEN"] = "access_token";
|
|
108
109
|
TokensEnum["REFRESH_TOKEN"] = "refresh_token";
|
|
109
110
|
TokensEnum["REFERENCE_TOKEN"] = "reference_token";
|
|
110
111
|
TokensEnum["PERSONAL_ACCESS_TOKEN"] = "personal_access_token";
|
|
111
112
|
})(TokensEnum || (TokensEnum = {}));
|
|
113
|
+
export var CoreServiceEnum;
|
|
114
|
+
(function (CoreServiceEnum) {
|
|
115
|
+
CoreServiceEnum["BASE_API_CLIENT"] = "base_client_name";
|
|
116
|
+
CoreServiceEnum["SOAP_API_CLIENT"] = "soap_api_client";
|
|
117
|
+
})(CoreServiceEnum || (CoreServiceEnum = {}));
|
|
112
118
|
export var EndpointResourceEnum;
|
|
113
119
|
(function (EndpointResourceEnum) {
|
|
114
120
|
EndpointResourceEnum["EXAMPLE"] = "example";
|