@urga-panel/ur-panels-core 1.0.20 → 1.0.22
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/dist/ServiceManager.js +34 -16
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/services/abstract/authServices/AuthService.js +2 -3
- package/dist/services/abstract/pageServices/controllers/NSPageControllerService.js +2 -2
- package/dist/services/abstract/webviewServices/WVFrontService.js +3 -3
- package/dist/services/main/httpServices/RequestHandlerService.js +4 -4
- package/dist/services/main/logService/LogService.d.ts +31 -0
- package/dist/services/main/logService/LogService.js +131 -0
- package/dist/services/main/logService/index.d.ts +7 -0
- package/dist/services/main/logService/index.js +4 -0
- package/dist/services/main/logService/transports/ConsoleTransport.d.ts +16 -0
- package/dist/services/main/logService/transports/ConsoleTransport.js +62 -0
- package/dist/services/main/logService/transports/DatabaseTransport.d.ts +28 -0
- package/dist/services/main/logService/transports/DatabaseTransport.js +90 -0
- package/dist/services/main/logService/types.d.ts +23 -0
- package/dist/services/main/logService/types.js +1 -0
- package/dist/services/main/logService/utils/parseEnvConfig.d.ts +27 -0
- package/dist/services/main/logService/utils/parseEnvConfig.js +60 -0
- package/dist/services/main/remoteApiControllerService/RemoteApiControllerService.js +2 -2
- package/dist/services/main/testServices/TestService2.js +1 -1
- package/dist/types/Service.d.ts +17 -12
- package/dist/types/Service.js +31 -7
- package/dist/types/ServiceOts.d.ts +1 -0
- package/package.json +1 -1
- package/src/ServiceManager.ts +35 -16
- package/src/index.ts +4 -0
- package/src/services/abstract/authServices/AuthService.ts +2 -3
- package/src/services/abstract/pageServices/controllers/NSPageControllerService.ts +2 -2
- package/src/services/abstract/webviewServices/WVFrontService.ts +3 -3
- package/src/services/main/httpServices/RequestHandlerService.ts +4 -4
- package/src/services/main/logService/LogService.ts +151 -0
- package/src/services/main/logService/index.ts +7 -0
- package/src/services/main/logService/transports/ConsoleTransport.ts +73 -0
- package/src/services/main/logService/transports/DatabaseTransport.ts +116 -0
- package/src/services/main/logService/types.ts +26 -0
- package/src/services/main/logService/utils/parseEnvConfig.ts +78 -0
- package/src/services/main/remoteApiControllerService/RemoteApiControllerService.ts +2 -2
- package/src/services/main/testServices/TestService2.ts +1 -1
- package/src/types/Service.ts +54 -14
- package/src/types/ServiceOts.ts +1 -0
package/dist/ServiceManager.js
CHANGED
|
@@ -3,6 +3,7 @@ import { NSPageControllerService } from "./services/abstract/pageServices/contro
|
|
|
3
3
|
import { SVPageControllerService } from "./services/abstract/pageServices/controllers/SVPageControllerService.js";
|
|
4
4
|
import { NSPageService } from "./services/abstract/pageServices/pages/NsPageService.js";
|
|
5
5
|
import { PageService } from "./services/abstract/pageServices/PageServices.js";
|
|
6
|
+
import { LogService } from "./services/main/logService/LogService.js";
|
|
6
7
|
export class _ServiceManager {
|
|
7
8
|
services = {
|
|
8
9
|
TestService: {
|
|
@@ -12,17 +13,30 @@ export class _ServiceManager {
|
|
|
12
13
|
};
|
|
13
14
|
constructor() {
|
|
14
15
|
}
|
|
15
|
-
async initServices(type,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
async initServices(type, services, namespace) {
|
|
17
|
+
const timestamp = new Date().toLocaleTimeString('tr-TR', { hour12: false });
|
|
18
|
+
const prefix = namespace ? `[ServiceManager:${namespace}]` : '[ServiceManager]';
|
|
19
|
+
console.log(`🚀 ${timestamp} ${prefix} Initializing services...`);
|
|
20
|
+
// İLK ÖNCE LogService'i başlat
|
|
21
|
+
let logService;
|
|
22
|
+
if (!namespace) { // LogService sadece global scope'ta oluşturulur
|
|
23
|
+
const logServiceKey = "LogService";
|
|
24
|
+
const logServiceEntry = this.setKey(logServiceKey, {
|
|
25
|
+
serviceSelf: new LogService({
|
|
26
|
+
usedService: {},
|
|
27
|
+
tag: "LogService",
|
|
28
|
+
type: type,
|
|
29
|
+
}),
|
|
30
|
+
status: "waitSetup",
|
|
31
|
+
});
|
|
32
|
+
logService = logServiceEntry;
|
|
33
|
+
await logService.setup();
|
|
34
|
+
await logService.start();
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Namespace'li servisler global LogService'i kullanır
|
|
38
|
+
logService = this.getService("LogService");
|
|
39
|
+
}
|
|
26
40
|
// // TestService'i oluştur ve başlat
|
|
27
41
|
// const _TestService = this.setKey("TestService", {
|
|
28
42
|
// serviceSelf: new TestService({
|
|
@@ -37,13 +51,13 @@ export class _ServiceManager {
|
|
|
37
51
|
if (type == "ns") {
|
|
38
52
|
const _PageControllerService = this.setKey("NSPageControllerService", {
|
|
39
53
|
serviceSelf: new NSPageControllerService({
|
|
40
|
-
usedService: {},
|
|
54
|
+
usedService: logService ? { "LogService": () => logService } : {},
|
|
41
55
|
abilities: {
|
|
42
56
|
createChildService: (tag) => {
|
|
43
57
|
//console.log("createChildService called for ---", tag);
|
|
44
58
|
const _pageService = this.setKey(tag, {
|
|
45
59
|
serviceSelf: new NSPageService({
|
|
46
|
-
usedService: {},
|
|
60
|
+
usedService: logService ? { "LogService": () => logService } : {},
|
|
47
61
|
tag: tag,
|
|
48
62
|
type: type,
|
|
49
63
|
}),
|
|
@@ -63,7 +77,7 @@ export class _ServiceManager {
|
|
|
63
77
|
else if (type == "svelte") {
|
|
64
78
|
const _PageControllerService = this.setKey("SVPageControllerService", {
|
|
65
79
|
serviceSelf: new SVPageControllerService({
|
|
66
|
-
usedService: {},
|
|
80
|
+
usedService: logService ? { "LogService": () => logService } : {},
|
|
67
81
|
abilities: {
|
|
68
82
|
// Artık class referansını parametre olarak alıyor
|
|
69
83
|
createChildService: (tag, PageCtor) => {
|
|
@@ -71,7 +85,7 @@ export class _ServiceManager {
|
|
|
71
85
|
const ServiceClass = PageCtor ?? PageService;
|
|
72
86
|
const _pageService = this.setKey(tag, {
|
|
73
87
|
serviceSelf: new ServiceClass({
|
|
74
|
-
usedService: {},
|
|
88
|
+
usedService: logService ? { "LogService": () => logService } : {},
|
|
75
89
|
tag: tag,
|
|
76
90
|
type: type,
|
|
77
91
|
}),
|
|
@@ -136,6 +150,10 @@ export class _ServiceManager {
|
|
|
136
150
|
//console.log(`Service ${serviceName} has serviceInfo defined:`, service.serviceInfo);
|
|
137
151
|
}
|
|
138
152
|
const usedService = {};
|
|
153
|
+
// LogService'i her zaman ekle (eğer varsa)
|
|
154
|
+
if (logService) {
|
|
155
|
+
usedService["LogService"] = () => logService;
|
|
156
|
+
}
|
|
139
157
|
if (Array.isArray(service.serviceInfo.requiredServices)) {
|
|
140
158
|
for (const reqName of service.serviceInfo.requiredServices) {
|
|
141
159
|
// Namespace-aware service lookup: önce namespace'li ara, yoksa global'e fallback
|
|
@@ -164,7 +182,7 @@ export class _ServiceManager {
|
|
|
164
182
|
const ServiceClass = PageCtor ?? PageService;
|
|
165
183
|
const _pageService = this.setKey(tag, {
|
|
166
184
|
serviceSelf: new ServiceClass({
|
|
167
|
-
usedService: {},
|
|
185
|
+
usedService: logService ? { "LogService": () => logService } : {},
|
|
168
186
|
tag: tag,
|
|
169
187
|
type: type,
|
|
170
188
|
//@ts-ignore
|
package/dist/index.d.ts
CHANGED
|
@@ -13,3 +13,5 @@ export { ExtensionService } from "./services/abstract/extensionServices/Extensio
|
|
|
13
13
|
export { ProjectInfoService } from "./services/abstract/project/ProjectInfoService.js";
|
|
14
14
|
export { RequestHandlerService } from "./services/main/httpServices/RequestHandlerService.js";
|
|
15
15
|
export { AuthService } from "./services/abstract/authServices/AuthService.js";
|
|
16
|
+
export { LogService, ConsoleTransport, DatabaseTransport, parseLogConfigFromEnv, getDatabaseTransportConfigFromEnv } from "./services/main/logService/index.js";
|
|
17
|
+
export type { ILogEntry, ILogTransport, LogServiceConfig, DatabaseTransportOptions, EnvLogConfig } from "./services/main/logService/index.js";
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,8 @@ export { ExtensionService } from "./services/abstract/extensionServices/Extensio
|
|
|
15
15
|
export { ProjectInfoService } from "./services/abstract/project/ProjectInfoService.js";
|
|
16
16
|
export { RequestHandlerService } from "./services/main/httpServices/RequestHandlerService.js";
|
|
17
17
|
export { AuthService } from "./services/abstract/authServices/AuthService.js";
|
|
18
|
+
// LogService exports
|
|
19
|
+
export { LogService, ConsoleTransport, DatabaseTransport, parseLogConfigFromEnv, getDatabaseTransportConfigFromEnv } from "./services/main/logService/index.js";
|
|
18
20
|
// export { PageControllerService } from "./services/pageServices/controller/PageControllerService.js";
|
|
19
21
|
// export { ExtensionService } from "./services/extensionServices/controller/ExtensionService.js";
|
|
20
22
|
// export { Test2Service } from "./testServices/TestService2";
|
|
@@ -65,7 +65,7 @@ export class AuthService extends Service {
|
|
|
65
65
|
});
|
|
66
66
|
}
|
|
67
67
|
catch (error) {
|
|
68
|
-
|
|
68
|
+
this.log.error("Logout error:", error);
|
|
69
69
|
return new Response(JSON.stringify({ status: "error", message: "An error occurred during logout" }), { status: 500, headers: { "Content-Type": "application/json" } });
|
|
70
70
|
}
|
|
71
71
|
}
|
|
@@ -92,7 +92,7 @@ export class AuthService extends Service {
|
|
|
92
92
|
if (typeof window === "undefined") {
|
|
93
93
|
bcrypt = await import("bcryptjs");
|
|
94
94
|
}
|
|
95
|
-
|
|
95
|
+
this.log.debug("User authenticated:", result.user);
|
|
96
96
|
const match = await bcrypt.compare(password, result.user.password);
|
|
97
97
|
if (!match) {
|
|
98
98
|
return this.resposeHandler({ success: false });
|
|
@@ -280,7 +280,6 @@ export class AuthService extends Service {
|
|
|
280
280
|
// // const decoded = jwt.verify(token, 'gizliAnahtar');
|
|
281
281
|
// // return !!decoded;
|
|
282
282
|
// // } catch (error) {
|
|
283
|
-
// // console.error('Token verification failed:', error);
|
|
284
283
|
// // return false;
|
|
285
284
|
// // }
|
|
286
285
|
// }
|
|
@@ -2,7 +2,7 @@ import { PageControllerService } from "./PageControllerService.js";
|
|
|
2
2
|
export class NSPageControllerService extends PageControllerService {
|
|
3
3
|
serviceInfo;
|
|
4
4
|
registerPage(tag, opt) {
|
|
5
|
-
|
|
5
|
+
this.log.debug(`Registering page with tag: ${tag}`);
|
|
6
6
|
const service = this.ots.abilities.createChildService?.(tag);
|
|
7
7
|
// await service.setup();
|
|
8
8
|
this.pages[tag] = {
|
|
@@ -12,7 +12,7 @@ export class NSPageControllerService extends PageControllerService {
|
|
|
12
12
|
return service;
|
|
13
13
|
}
|
|
14
14
|
onLoaded() {
|
|
15
|
-
|
|
15
|
+
this.log.info("NSPageControllerService onLoaded called");
|
|
16
16
|
// Implement any additional logic needed when the page is loaded
|
|
17
17
|
}
|
|
18
18
|
}
|
|
@@ -33,7 +33,7 @@ export class WVFrontService extends Service {
|
|
|
33
33
|
this.oWebViewInterface.emit("gotoBack", "");
|
|
34
34
|
}
|
|
35
35
|
async sendFetchRequest(url, options) {
|
|
36
|
-
|
|
36
|
+
this.log.debug("sendFetchRequest", url, options);
|
|
37
37
|
const id = `r_${Date.now()}_${++WVFrontService._requestIdCounter}`;
|
|
38
38
|
return new Promise((resolve) => {
|
|
39
39
|
const handler = (args) => {
|
|
@@ -66,14 +66,14 @@ export class WVFrontService extends Service {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
catch (e) {
|
|
69
|
-
|
|
69
|
+
this.log.error('sendFetchRequest: failed to decode response body', e);
|
|
70
70
|
text = '';
|
|
71
71
|
}
|
|
72
72
|
const response = new Response(text, {
|
|
73
73
|
status: 200,
|
|
74
74
|
headers: { "Content-Type": "application/json" }
|
|
75
75
|
});
|
|
76
|
-
|
|
76
|
+
this.log.debug("sendFetchRequest received (id)", id, envelope.param);
|
|
77
77
|
// remove listeners
|
|
78
78
|
this.oWebViewInterface.removeListener('sendFetchRequest', handler);
|
|
79
79
|
this.oWebViewInterface.removeListener('sendFetchRequestResponse', handler);
|
|
@@ -89,14 +89,14 @@ export class RequestHandlerService extends Service {
|
|
|
89
89
|
role: handler.options?.role
|
|
90
90
|
}
|
|
91
91
|
});
|
|
92
|
-
|
|
92
|
+
this.log.debug("isAuthenticated", isAuthenticated);
|
|
93
93
|
if (!isAuthenticated.valid) {
|
|
94
94
|
return this.resposeHandler({ status: "error", message: "Unauthorized" });
|
|
95
95
|
}
|
|
96
96
|
user = isAuthenticated.user || null;
|
|
97
97
|
if (isAuthenticated.newAccessToken) {
|
|
98
98
|
// Update cookies with new tokens
|
|
99
|
-
|
|
99
|
+
this.log.debug("update token");
|
|
100
100
|
header = {
|
|
101
101
|
"Set-Cookie": `panel_token=${isAuthenticated.newAccessToken}; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=900, refreshToken=${isAuthenticated.newRefreshToken}; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=604800`,
|
|
102
102
|
};
|
|
@@ -117,8 +117,8 @@ export class RequestHandlerService extends Service {
|
|
|
117
117
|
else {
|
|
118
118
|
response = await handler.callback({ ...event, user });
|
|
119
119
|
}
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
this.log.debug("RequestHandlerService requestCome response");
|
|
121
|
+
this.log.debug("Object.keys(header).length", Object.keys(header).length);
|
|
122
122
|
// Eğer header içinde Set-Cookie veya başka header varsa response'a ekle
|
|
123
123
|
if (Object.keys(header).length > 0) {
|
|
124
124
|
// Response zaten bir Response nesnesi ise, header'ları birleştirerek yeni bir Response oluştur
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Service, ServiceLogger } from "../../../types/Service.js";
|
|
2
|
+
import { ServiceResponse } from "../../../types/ServiceResponse.js";
|
|
3
|
+
import { ServiceSetupOptions } from "../../../types/ServiceSetupOptions.js";
|
|
4
|
+
import { ILogTransport } from "./types.js";
|
|
5
|
+
export declare class LogService extends Service {
|
|
6
|
+
static serviceInfo: {
|
|
7
|
+
name: string;
|
|
8
|
+
requiredServices: any[];
|
|
9
|
+
};
|
|
10
|
+
private transports;
|
|
11
|
+
private minLevel;
|
|
12
|
+
private enabledNamespaces?;
|
|
13
|
+
private logLevelOrder;
|
|
14
|
+
protected onSetup(options?: ServiceSetupOptions): Promise<ServiceResponse>;
|
|
15
|
+
protected onStart(): Promise<ServiceResponse>;
|
|
16
|
+
protected onStop(): Promise<ServiceResponse>;
|
|
17
|
+
protected onDestroy(): Promise<ServiceResponse>;
|
|
18
|
+
/**
|
|
19
|
+
* Runtime'da yeni transport ekle
|
|
20
|
+
*/
|
|
21
|
+
addTransport(transport: ILogTransport): void;
|
|
22
|
+
/**
|
|
23
|
+
* Transport'u kaldır
|
|
24
|
+
*/
|
|
25
|
+
removeTransport(transportName: string): void;
|
|
26
|
+
/**
|
|
27
|
+
* Her service için özel logger döndürür
|
|
28
|
+
*/
|
|
29
|
+
logSetupForService(tag: string, namespace?: string): ServiceLogger;
|
|
30
|
+
private writeLog;
|
|
31
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { Service } from "../../../types/Service.js";
|
|
2
|
+
import { ConsoleTransport } from "./transports/ConsoleTransport.js";
|
|
3
|
+
export class LogService extends Service {
|
|
4
|
+
static serviceInfo = {
|
|
5
|
+
name: "LogService",
|
|
6
|
+
requiredServices: []
|
|
7
|
+
};
|
|
8
|
+
transports = [];
|
|
9
|
+
minLevel = 'debug';
|
|
10
|
+
enabledNamespaces;
|
|
11
|
+
logLevelOrder = {
|
|
12
|
+
debug: 0,
|
|
13
|
+
info: 1,
|
|
14
|
+
success: 2,
|
|
15
|
+
warn: 3,
|
|
16
|
+
error: 4
|
|
17
|
+
};
|
|
18
|
+
async onSetup(options) {
|
|
19
|
+
// Default: sadece ConsoleTransport
|
|
20
|
+
const config = options?.config;
|
|
21
|
+
if (config) {
|
|
22
|
+
this.transports = config.transports;
|
|
23
|
+
if (config.minLevel)
|
|
24
|
+
this.minLevel = config.minLevel;
|
|
25
|
+
if (config.enabledNamespaces)
|
|
26
|
+
this.enabledNamespaces = config.enabledNamespaces;
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
// Varsayılan: ConsoleTransport
|
|
30
|
+
this.transports = [new ConsoleTransport()];
|
|
31
|
+
}
|
|
32
|
+
this.log.success(`LogService initialized with ${this.transports.length} transport(s)`);
|
|
33
|
+
return { status: "success", message: "LogService setup complete" };
|
|
34
|
+
}
|
|
35
|
+
async onStart() {
|
|
36
|
+
return { status: "success", message: "LogService started" };
|
|
37
|
+
}
|
|
38
|
+
async onStop() {
|
|
39
|
+
// Tüm transport'ları flush et
|
|
40
|
+
await Promise.all(this.transports
|
|
41
|
+
.filter(t => t.flush)
|
|
42
|
+
.map(t => t.flush()));
|
|
43
|
+
return { status: "success", message: "LogService stopped" };
|
|
44
|
+
}
|
|
45
|
+
async onDestroy() {
|
|
46
|
+
// Tüm transport'ları kapat
|
|
47
|
+
await Promise.all(this.transports
|
|
48
|
+
.filter(t => t.close)
|
|
49
|
+
.map(t => t.close()));
|
|
50
|
+
this.transports = [];
|
|
51
|
+
return { status: "success", message: "LogService destroyed" };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Runtime'da yeni transport ekle
|
|
55
|
+
*/
|
|
56
|
+
addTransport(transport) {
|
|
57
|
+
this.transports.push(transport);
|
|
58
|
+
this.log.info(`Transport added: ${transport.name}`);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Transport'u kaldır
|
|
62
|
+
*/
|
|
63
|
+
removeTransport(transportName) {
|
|
64
|
+
const index = this.transports.findIndex(t => t.name === transportName);
|
|
65
|
+
if (index !== -1) {
|
|
66
|
+
const transport = this.transports[index];
|
|
67
|
+
if (transport.close) {
|
|
68
|
+
transport.close();
|
|
69
|
+
}
|
|
70
|
+
this.transports.splice(index, 1);
|
|
71
|
+
this.log.info(`Transport removed: ${transportName}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Her service için özel logger döndürür
|
|
76
|
+
*/
|
|
77
|
+
logSetupForService(tag, namespace) {
|
|
78
|
+
return {
|
|
79
|
+
debug: (...args) => this.writeLog('debug', tag, namespace, ...args),
|
|
80
|
+
info: (...args) => this.writeLog('info', tag, namespace, ...args),
|
|
81
|
+
success: (...args) => this.writeLog('success', tag, namespace, ...args),
|
|
82
|
+
warn: (...args) => this.writeLog('warn', tag, namespace, ...args),
|
|
83
|
+
error: (...args) => this.writeLog('error', tag, namespace, ...args),
|
|
84
|
+
// Backward compatibility
|
|
85
|
+
OK: (...args) => this.writeLog('success', tag, namespace, ...args),
|
|
86
|
+
ERROR: (...args) => this.writeLog('error', tag, namespace, ...args),
|
|
87
|
+
WARN: (...args) => this.writeLog('warn', tag, namespace, ...args),
|
|
88
|
+
l: (...args) => this.writeLog('info', tag, namespace, ...args),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
writeLog(level, tag, namespace, ...args) {
|
|
92
|
+
// Level filtreleme (LogService seviyesinde)
|
|
93
|
+
if (this.logLevelOrder[level] < this.logLevelOrder[this.minLevel]) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Namespace filtreleme
|
|
97
|
+
if (this.enabledNamespaces && this.enabledNamespaces.length > 0) {
|
|
98
|
+
const fullName = namespace ? `${namespace}:${tag}` : tag;
|
|
99
|
+
const isEnabled = this.enabledNamespaces.some(ns => fullName.includes(ns) || tag.includes(ns));
|
|
100
|
+
if (!isEnabled)
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const entry = {
|
|
104
|
+
timestamp: new Date(),
|
|
105
|
+
level,
|
|
106
|
+
tag,
|
|
107
|
+
namespace,
|
|
108
|
+
message: args[0],
|
|
109
|
+
args: args.slice(1)
|
|
110
|
+
};
|
|
111
|
+
// Her transport için kontrol et ve logla
|
|
112
|
+
for (const transport of this.transports) {
|
|
113
|
+
// Transport seviyesinde filtreleme
|
|
114
|
+
if (!transport.shouldLog(entry)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
try {
|
|
118
|
+
const result = transport.log(entry);
|
|
119
|
+
// Eğer Promise dönerse bekle
|
|
120
|
+
if (result instanceof Promise) {
|
|
121
|
+
result.catch(err => {
|
|
122
|
+
console.error(`[LogService] Transport ${transport.name} failed:`, err);
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch (err) {
|
|
127
|
+
console.error(`[LogService] Transport ${transport.name} failed:`, err);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { LogService } from "./LogService.js";
|
|
2
|
+
export { ConsoleTransport } from "./transports/ConsoleTransport.js";
|
|
3
|
+
export { DatabaseTransport } from "./transports/DatabaseTransport.js";
|
|
4
|
+
export { parseLogConfigFromEnv, getDatabaseTransportConfigFromEnv } from "./utils/parseEnvConfig.js";
|
|
5
|
+
export type { ILogEntry, ILogTransport, LogServiceConfig } from "./types.js";
|
|
6
|
+
export type { DatabaseTransportOptions } from "./transports/DatabaseTransport.js";
|
|
7
|
+
export type { EnvLogConfig } from "./utils/parseEnvConfig.js";
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { LogService } from "./LogService.js";
|
|
2
|
+
export { ConsoleTransport } from "./transports/ConsoleTransport.js";
|
|
3
|
+
export { DatabaseTransport } from "./transports/DatabaseTransport.js";
|
|
4
|
+
export { parseLogConfigFromEnv, getDatabaseTransportConfigFromEnv } from "./utils/parseEnvConfig.js";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ILogEntry, ILogTransport } from "../types.js";
|
|
2
|
+
import { LogLevel } from "../../../../types/Service.js";
|
|
3
|
+
export declare class ConsoleTransport implements ILogTransport {
|
|
4
|
+
name: string;
|
|
5
|
+
levels?: LogLevel[];
|
|
6
|
+
minLevel?: LogLevel;
|
|
7
|
+
private logLevelOrder;
|
|
8
|
+
constructor(options?: {
|
|
9
|
+
levels?: LogLevel[];
|
|
10
|
+
minLevel?: LogLevel;
|
|
11
|
+
});
|
|
12
|
+
shouldLog(entry: ILogEntry): boolean;
|
|
13
|
+
private getLogPrefix;
|
|
14
|
+
private getIcon;
|
|
15
|
+
log(entry: ILogEntry): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export class ConsoleTransport {
|
|
2
|
+
name = "ConsoleTransport";
|
|
3
|
+
levels;
|
|
4
|
+
minLevel;
|
|
5
|
+
logLevelOrder = {
|
|
6
|
+
debug: 0,
|
|
7
|
+
info: 1,
|
|
8
|
+
success: 2,
|
|
9
|
+
warn: 3,
|
|
10
|
+
error: 4
|
|
11
|
+
};
|
|
12
|
+
constructor(options) {
|
|
13
|
+
if (options?.levels)
|
|
14
|
+
this.levels = options.levels;
|
|
15
|
+
if (options?.minLevel)
|
|
16
|
+
this.minLevel = options.minLevel;
|
|
17
|
+
}
|
|
18
|
+
shouldLog(entry) {
|
|
19
|
+
// Eğer spesifik level'lar belirtilmişse
|
|
20
|
+
if (this.levels && this.levels.length > 0) {
|
|
21
|
+
return this.levels.includes(entry.level);
|
|
22
|
+
}
|
|
23
|
+
// Eğer minimum level belirtilmişse
|
|
24
|
+
if (this.minLevel) {
|
|
25
|
+
return this.logLevelOrder[entry.level] >= this.logLevelOrder[this.minLevel];
|
|
26
|
+
}
|
|
27
|
+
// Varsayılan: her şeyi logla
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
getLogPrefix(entry) {
|
|
31
|
+
if (entry.namespace) {
|
|
32
|
+
return `[${entry.namespace}:${entry.tag}]`;
|
|
33
|
+
}
|
|
34
|
+
return `[${entry.tag}]`;
|
|
35
|
+
}
|
|
36
|
+
getIcon(level) {
|
|
37
|
+
const icons = {
|
|
38
|
+
debug: '🔍',
|
|
39
|
+
info: 'ℹ️',
|
|
40
|
+
success: '✅',
|
|
41
|
+
warn: '⚠️',
|
|
42
|
+
error: '❌'
|
|
43
|
+
};
|
|
44
|
+
return icons[level];
|
|
45
|
+
}
|
|
46
|
+
log(entry) {
|
|
47
|
+
const timestamp = entry.timestamp.toLocaleTimeString('tr-TR', { hour12: false });
|
|
48
|
+
const prefix = this.getLogPrefix(entry);
|
|
49
|
+
const icon = this.getIcon(entry.level);
|
|
50
|
+
const formattedArgs = [`${icon} ${timestamp} ${prefix}`, entry.message, ...entry.args];
|
|
51
|
+
switch (entry.level) {
|
|
52
|
+
case 'error':
|
|
53
|
+
console.error(...formattedArgs);
|
|
54
|
+
break;
|
|
55
|
+
case 'warn':
|
|
56
|
+
console.warn(...formattedArgs);
|
|
57
|
+
break;
|
|
58
|
+
default:
|
|
59
|
+
console.log(...formattedArgs);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ILogEntry, ILogTransport } from "../types.js";
|
|
2
|
+
import { LogLevel } from "../../../../types/Service.js";
|
|
3
|
+
export interface DatabaseTransportOptions {
|
|
4
|
+
levels?: LogLevel[];
|
|
5
|
+
minLevel?: LogLevel;
|
|
6
|
+
getDatabaseService: () => any;
|
|
7
|
+
collectionName?: string;
|
|
8
|
+
batchSize?: number;
|
|
9
|
+
flushInterval?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class DatabaseTransport implements ILogTransport {
|
|
12
|
+
name: string;
|
|
13
|
+
levels?: LogLevel[];
|
|
14
|
+
minLevel?: LogLevel;
|
|
15
|
+
private getDatabaseService;
|
|
16
|
+
private collectionName;
|
|
17
|
+
private batchSize;
|
|
18
|
+
private flushInterval;
|
|
19
|
+
private logBuffer;
|
|
20
|
+
private flushTimer?;
|
|
21
|
+
private logLevelOrder;
|
|
22
|
+
constructor(options: DatabaseTransportOptions);
|
|
23
|
+
shouldLog(entry: ILogEntry): boolean;
|
|
24
|
+
log(entry: ILogEntry): Promise<void>;
|
|
25
|
+
flush(): Promise<void>;
|
|
26
|
+
close(): Promise<void>;
|
|
27
|
+
private startFlushTimer;
|
|
28
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export class DatabaseTransport {
|
|
2
|
+
name = "DatabaseTransport";
|
|
3
|
+
levels;
|
|
4
|
+
minLevel;
|
|
5
|
+
getDatabaseService;
|
|
6
|
+
collectionName;
|
|
7
|
+
batchSize;
|
|
8
|
+
flushInterval;
|
|
9
|
+
logBuffer = [];
|
|
10
|
+
flushTimer;
|
|
11
|
+
logLevelOrder = {
|
|
12
|
+
debug: 0,
|
|
13
|
+
info: 1,
|
|
14
|
+
success: 2,
|
|
15
|
+
warn: 3,
|
|
16
|
+
error: 4
|
|
17
|
+
};
|
|
18
|
+
constructor(options) {
|
|
19
|
+
this.getDatabaseService = options.getDatabaseService;
|
|
20
|
+
this.collectionName = options.collectionName || "logs";
|
|
21
|
+
this.batchSize = options.batchSize || 10;
|
|
22
|
+
this.flushInterval = options.flushInterval || 5000; // 5 saniye
|
|
23
|
+
if (options.levels)
|
|
24
|
+
this.levels = options.levels;
|
|
25
|
+
if (options.minLevel)
|
|
26
|
+
this.minLevel = options.minLevel;
|
|
27
|
+
// Periyodik flush başlat
|
|
28
|
+
this.startFlushTimer();
|
|
29
|
+
}
|
|
30
|
+
shouldLog(entry) {
|
|
31
|
+
// Eğer spesifik level'lar belirtilmişse
|
|
32
|
+
if (this.levels && this.levels.length > 0) {
|
|
33
|
+
return this.levels.includes(entry.level);
|
|
34
|
+
}
|
|
35
|
+
// Eğer minimum level belirtilmişse
|
|
36
|
+
if (this.minLevel) {
|
|
37
|
+
return this.logLevelOrder[entry.level] >= this.logLevelOrder[this.minLevel];
|
|
38
|
+
}
|
|
39
|
+
// Varsayılan: sadece warn ve error
|
|
40
|
+
return entry.level === 'warn' || entry.level === 'error';
|
|
41
|
+
}
|
|
42
|
+
async log(entry) {
|
|
43
|
+
// Buffer'a ekle
|
|
44
|
+
this.logBuffer.push(entry);
|
|
45
|
+
// Eğer buffer dolmuşsa hemen flush et
|
|
46
|
+
if (this.logBuffer.length >= this.batchSize) {
|
|
47
|
+
await this.flush();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async flush() {
|
|
51
|
+
if (this.logBuffer.length === 0)
|
|
52
|
+
return;
|
|
53
|
+
try {
|
|
54
|
+
const dbService = this.getDatabaseService();
|
|
55
|
+
if (!dbService || !dbService.client) {
|
|
56
|
+
console.error('[DatabaseTransport] DatabaseService not ready');
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const db = dbService.client.db();
|
|
60
|
+
const logsCollection = db.collection(this.collectionName);
|
|
61
|
+
const documents = this.logBuffer.map(entry => ({
|
|
62
|
+
timestamp: entry.timestamp,
|
|
63
|
+
level: entry.level,
|
|
64
|
+
service: entry.tag,
|
|
65
|
+
namespace: entry.namespace,
|
|
66
|
+
message: entry.message,
|
|
67
|
+
args: entry.args,
|
|
68
|
+
createdAt: new Date()
|
|
69
|
+
}));
|
|
70
|
+
await logsCollection.insertMany(documents);
|
|
71
|
+
this.logBuffer = []; // Buffer'ı temizle
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error('[DatabaseTransport] Failed to write logs:', error);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
async close() {
|
|
78
|
+
// Timer'ı durdur
|
|
79
|
+
if (this.flushTimer) {
|
|
80
|
+
clearInterval(this.flushTimer);
|
|
81
|
+
}
|
|
82
|
+
// Kalan log'ları flush et
|
|
83
|
+
await this.flush();
|
|
84
|
+
}
|
|
85
|
+
startFlushTimer() {
|
|
86
|
+
this.flushTimer = setInterval(async () => {
|
|
87
|
+
await this.flush();
|
|
88
|
+
}, this.flushInterval);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { LogLevel } from "../../../types/Service.js";
|
|
2
|
+
export interface ILogEntry {
|
|
3
|
+
timestamp: Date;
|
|
4
|
+
level: LogLevel;
|
|
5
|
+
tag: string;
|
|
6
|
+
namespace?: string;
|
|
7
|
+
message: string;
|
|
8
|
+
args: any[];
|
|
9
|
+
}
|
|
10
|
+
export interface ILogTransport {
|
|
11
|
+
name: string;
|
|
12
|
+
levels?: LogLevel[];
|
|
13
|
+
minLevel?: LogLevel;
|
|
14
|
+
shouldLog(entry: ILogEntry): boolean;
|
|
15
|
+
log(entry: ILogEntry): void | Promise<void>;
|
|
16
|
+
flush?(): void | Promise<void>;
|
|
17
|
+
close?(): void | Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
export interface LogServiceConfig {
|
|
20
|
+
transports: ILogTransport[];
|
|
21
|
+
minLevel?: LogLevel;
|
|
22
|
+
enabledNamespaces?: string[];
|
|
23
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { LogLevel } from "../../../../types/Service.js";
|
|
2
|
+
import { LogServiceConfig } from "../types.js";
|
|
3
|
+
export interface EnvLogConfig {
|
|
4
|
+
LOG_LEVEL?: string;
|
|
5
|
+
LOG_CONSOLE_LEVELS?: string;
|
|
6
|
+
LOG_NAMESPACES?: string;
|
|
7
|
+
LOG_DATABASE_ENABLED?: string;
|
|
8
|
+
LOG_DATABASE_LEVELS?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Environment variable'lardan LogService config'i oluşturur
|
|
12
|
+
*
|
|
13
|
+
* Örnek .env:
|
|
14
|
+
* LOG_LEVEL=info
|
|
15
|
+
* LOG_CONSOLE_LEVELS=debug,info,success,warn,error
|
|
16
|
+
* LOG_NAMESPACES=DatabaseService,AuthService
|
|
17
|
+
* LOG_DATABASE_ENABLED=true
|
|
18
|
+
* LOG_DATABASE_LEVELS=warn,error
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseLogConfigFromEnv(env: EnvLogConfig): Partial<LogServiceConfig>;
|
|
21
|
+
/**
|
|
22
|
+
* DatabaseTransport için config döner
|
|
23
|
+
*/
|
|
24
|
+
export declare function getDatabaseTransportConfigFromEnv(env: EnvLogConfig): {
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
levels?: LogLevel[];
|
|
27
|
+
};
|