vloggo 1.0.0

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.
@@ -0,0 +1,2 @@
1
+ export { VLoggo } from "./services/logService";
2
+ export * from "./interfaces/interfaces";
package/build/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { VLoggo } from "./services/logService";
2
+ export * from "./interfaces/interfaces";
@@ -0,0 +1,36 @@
1
+ export interface VLoggoConfig {
2
+ client?: string;
3
+ json?: boolean;
4
+ debug?: boolean;
5
+ console?: boolean;
6
+ directory?: VLoggoDirectory;
7
+ filecount?: VLoggoFilecount;
8
+ notify?: boolean;
9
+ smtp?: VLoggoSMTPConfig;
10
+ throttle?: number;
11
+ }
12
+ export interface VLoggoDirectory {
13
+ txt?: string;
14
+ json?: string;
15
+ }
16
+ export interface VLoggoFilecount {
17
+ txt?: number;
18
+ json?: number;
19
+ }
20
+ export interface VLoggoSMTPConfig {
21
+ host: string;
22
+ port: number;
23
+ username: string;
24
+ password: string;
25
+ from: string;
26
+ to: string | string[];
27
+ secure: boolean;
28
+ }
29
+ export type LogLevel = "INFO" | "WARN" | "ERROR" | "FATAL" | "DEBUG";
30
+ export interface LogEntry {
31
+ level: LogLevel;
32
+ timestamp: string;
33
+ code: string;
34
+ caller: string;
35
+ message: string;
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,57 @@
1
+ import Config from "../config/config";
2
+ /**
3
+ * Service responsible for sending email notifications via SMTP.
4
+ * Handles error notifications with throttling to prevent spam.
5
+ *
6
+ * @class EmailService
7
+ */
8
+ declare class EmailService {
9
+ private config;
10
+ private format;
11
+ private transporter;
12
+ private _ready;
13
+ private lastEmailSent;
14
+ /**
15
+ * Creates an instance of EmailService and initializes the SMTP transport.
16
+ *
17
+ * @param {Config} config - Configuration object containing SMTP settings
18
+ */
19
+ constructor(config: Config);
20
+ /**
21
+ * Initializes SMTP transport using nodemailer.
22
+ * Sets up connection pooling and authentication.
23
+ * Logs initialization status if debug mode is enabled.
24
+ *
25
+ * @private
26
+ * @returns {void}
27
+ */
28
+ private initialize;
29
+ /**
30
+ * Sends an error notification email to configured recipients.
31
+ * Implements throttling based on config.throttle to prevent email spam.
32
+ *
33
+ * @async
34
+ * @param {string} client - Name of the client/application reporting the error
35
+ * @param {string} code - Error code identifier
36
+ * @param {string} error - Detailed error message
37
+ * @returns {Promise<void>}
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * await emailService.sendErrorNotification(
42
+ * "MyApp",
43
+ * "ERR_DATABASE",
44
+ * "Failed to connect to database"
45
+ * );
46
+ * ```
47
+ */
48
+ sendErrorNotification(client: string, code: string, error: string): Promise<void>;
49
+ /**
50
+ * Gets the ready status of the email service.
51
+ *
52
+ * @readonly
53
+ * @returns {boolean} True if the service is initialized and ready to send emails
54
+ */
55
+ get ready(): boolean;
56
+ }
57
+ export default EmailService;
@@ -0,0 +1,132 @@
1
+ import nodemailer from "nodemailer";
2
+ import FormatService from "./formatService";
3
+ /**
4
+ * Service responsible for sending email notifications via SMTP.
5
+ * Handles error notifications with throttling to prevent spam.
6
+ *
7
+ * @class EmailService
8
+ */
9
+ class EmailService {
10
+ config;
11
+ format = new FormatService();
12
+ transporter = null;
13
+ _ready = false;
14
+ lastEmailSent = 0;
15
+ /**
16
+ * Creates an instance of EmailService and initializes the SMTP transport.
17
+ *
18
+ * @param {Config} config - Configuration object containing SMTP settings
19
+ */
20
+ constructor(config) {
21
+ this.config = config;
22
+ this.initialize();
23
+ }
24
+ /**
25
+ * Initializes SMTP transport using nodemailer.
26
+ * Sets up connection pooling and authentication.
27
+ * Logs initialization status if debug mode is enabled.
28
+ *
29
+ * @private
30
+ * @returns {void}
31
+ */
32
+ initialize() {
33
+ if (!this.config.smtp) {
34
+ if (this.config.console) {
35
+ console.info(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [INFO] : notification service disabled > missing configuration`);
36
+ }
37
+ return;
38
+ }
39
+ try {
40
+ this.transporter = nodemailer.createTransport({
41
+ host: this.config.smtp.host,
42
+ port: this.config.smtp.port,
43
+ secure: this.config.smtp.secure ?? this.config.smtp.port === 465,
44
+ pool: true,
45
+ auth: {
46
+ user: this.config.smtp.username,
47
+ pass: this.config.smtp.password,
48
+ },
49
+ debug: this.config.debug,
50
+ logger: this.config.debug,
51
+ });
52
+ this._ready = true;
53
+ if (this.config.debug) {
54
+ console.info(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [INFO] : notification service initialized successfully`);
55
+ }
56
+ }
57
+ catch (error) {
58
+ console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : error initializing notification service > ${error.message}`);
59
+ this.transporter = null;
60
+ }
61
+ }
62
+ /**
63
+ * Sends an error notification email to configured recipients.
64
+ * Implements throttling based on config.throttle to prevent email spam.
65
+ *
66
+ * @async
67
+ * @param {string} client - Name of the client/application reporting the error
68
+ * @param {string} code - Error code identifier
69
+ * @param {string} error - Detailed error message
70
+ * @returns {Promise<void>}
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * await emailService.sendErrorNotification(
75
+ * "MyApp",
76
+ * "ERR_DATABASE",
77
+ * "Failed to connect to database"
78
+ * );
79
+ * ```
80
+ */
81
+ async sendErrorNotification(client, code, error) {
82
+ if (!this.transporter || !this.config.smtp) {
83
+ console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : failed to send error message > email service not initialized`);
84
+ return;
85
+ }
86
+ const now = Date.now();
87
+ if (now - this.lastEmailSent < this.config.throttle) {
88
+ if (this.config.debug) {
89
+ console.info(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [INFO] : email throttled > ${now - this.lastEmailSent} ms remaining`);
90
+ }
91
+ return;
92
+ }
93
+ this.lastEmailSent = now;
94
+ const recipients = Array.isArray(this.config.smtp.to)
95
+ ? this.config.smtp.to.join(", ")
96
+ : this.config.smtp.to;
97
+ const caller = this.format.caller(3);
98
+ const emailContent = {
99
+ from: `"${client}" <${this.config.smtp.from}>`,
100
+ to: recipients,
101
+ subject: `[${client}] Error Alert - ${code}`,
102
+ html: `
103
+ <h2>Error Report</h2>
104
+ <p><strong>Client:</strong> ${client}</p>
105
+ <p><strong>Error Code:</strong> ${code}</p>
106
+ <p><strong>Caller:</strong> ${caller}</p>
107
+ <p><strong>Error Message:</strong> ${error}</p>
108
+ <p><strong>Timestamp:</strong> ${new Date().toLocaleString("pt-BR")}</p>
109
+ <hr>
110
+ `,
111
+ };
112
+ try {
113
+ await this.transporter.sendMail(emailContent);
114
+ if (this.config.debug) {
115
+ console.info(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [INFO] : error email sent successfully to ${recipients}`);
116
+ }
117
+ }
118
+ catch (error) {
119
+ console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : failed to send error message > ${error.message}`);
120
+ }
121
+ }
122
+ /**
123
+ * Gets the ready status of the email service.
124
+ *
125
+ * @readonly
126
+ * @returns {boolean} True if the service is initialized and ready to send emails
127
+ */
128
+ get ready() {
129
+ return this._ready;
130
+ }
131
+ }
132
+ export default EmailService;
@@ -0,0 +1,68 @@
1
+ import Config from "../config/config";
2
+ /**
3
+ * Service responsible for managing log file operations.
4
+ * Handles file creation, writing, rotation, and cleanup based on retention policies.
5
+ *
6
+ * @class FileService
7
+ */
8
+ declare class FileService {
9
+ private config;
10
+ private _txtFilename;
11
+ private _jsonFilename;
12
+ private _currentDay;
13
+ private _initialized;
14
+ private format;
15
+ /**
16
+ * Creates an instance of FileService.
17
+ *
18
+ * @param {Config} config - Configuration object containing directory and file retention settings
19
+ */
20
+ constructor(config: Config);
21
+ /**
22
+ * Initializes the file service by creating the log directory and first log file.
23
+ * Sets up the current day tracking for rotation purposes.
24
+ * This method is idempotent - calling it multiple times has no effect after first initialization.
25
+ *
26
+ * @returns {void}
27
+ */
28
+ initialize(): void;
29
+ /**
30
+ * Writes a line to the current log file.
31
+ * Checks if the service is initialized before writing.
32
+ *
33
+ * @param {string} line - Log line to write (should include newline character)
34
+ * @returns {void}
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * fileService.write("[INFO] User logged in\n");
39
+ * ```
40
+ */
41
+ write(line: string, json?: string): void;
42
+ /**
43
+ * Verifies if log rotation is needed by checking if the day has changed.
44
+ * If rotation is needed, creates a new log file and triggers cleanup of old files.
45
+ * This method should be called before each write operation to ensure proper rotation.
46
+ *
47
+ * @returns {void}
48
+ */
49
+ verify(): void;
50
+ /**
51
+ * Rotates log files by removing old files that exceed the retention count.
52
+ * Scans the log directory, sorts files by modification time (newest first),
53
+ * and deletes the oldest files when the count exceeds config.filecount.
54
+ *
55
+ * @private
56
+ * @async
57
+ * @returns {Promise<void>}
58
+ */
59
+ private rotate;
60
+ /**
61
+ * Gets the initialization status of the file service.
62
+ *
63
+ * @readonly
64
+ * @returns {boolean} True if the service is initialized and ready to write logs
65
+ */
66
+ get initialized(): boolean;
67
+ }
68
+ export default FileService;
@@ -0,0 +1,189 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import * as fsp from "fs/promises";
4
+ import FormatService from "./formatService";
5
+ /**
6
+ * Service responsible for managing log file operations.
7
+ * Handles file creation, writing, rotation, and cleanup based on retention policies.
8
+ *
9
+ * @class FileService
10
+ */
11
+ class FileService {
12
+ config;
13
+ _txtFilename = "";
14
+ _jsonFilename = "";
15
+ _currentDay = 0;
16
+ _initialized = false;
17
+ format;
18
+ /**
19
+ * Creates an instance of FileService.
20
+ *
21
+ * @param {Config} config - Configuration object containing directory and file retention settings
22
+ */
23
+ constructor(config) {
24
+ this.config = config;
25
+ this.format = new FormatService(this.config.client);
26
+ }
27
+ /**
28
+ * Initializes the file service by creating the log directory and first log file.
29
+ * Sets up the current day tracking for rotation purposes.
30
+ * This method is idempotent - calling it multiple times has no effect after first initialization.
31
+ *
32
+ * @returns {void}
33
+ */
34
+ initialize() {
35
+ if (this._initialized) {
36
+ return;
37
+ }
38
+ try {
39
+ this._currentDay = new Date().getDate();
40
+ const txtDirectory = this.config.directory.txt;
41
+ fs.mkdirSync(txtDirectory, { recursive: true });
42
+ this._txtFilename = path.resolve(txtDirectory, this.format.filename());
43
+ fs.appendFileSync(this._txtFilename, this.format.separator());
44
+ if (this.config.json) {
45
+ const jsonDirectory = this.config.directory.json;
46
+ fs.mkdirSync(jsonDirectory, { recursive: true });
47
+ this._jsonFilename = path.resolve(jsonDirectory, this.format.jsonFilename());
48
+ fs.appendFileSync(this._jsonFilename, this.format.jsonSeparator());
49
+ }
50
+ this._initialized = true;
51
+ }
52
+ catch (error) {
53
+ console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : error initializing VLoggo > ${error.message}`);
54
+ }
55
+ }
56
+ /**
57
+ * Writes a line to the current log file.
58
+ * Checks if the service is initialized before writing.
59
+ *
60
+ * @param {string} line - Log line to write (should include newline character)
61
+ * @returns {void}
62
+ *
63
+ * @example
64
+ * ```typescript
65
+ * fileService.write("[INFO] User logged in\n");
66
+ * ```
67
+ */
68
+ write(line, json) {
69
+ if (!this.initialized) {
70
+ console.warn(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [WARN] : file service not initialized`);
71
+ return;
72
+ }
73
+ try {
74
+ fs.appendFileSync(this._txtFilename, line);
75
+ if (this.config.json && json != undefined) {
76
+ fs.appendFileSync(this._jsonFilename, json);
77
+ }
78
+ }
79
+ catch (error) {
80
+ console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : failed to write to log file > ${error.message}`);
81
+ }
82
+ }
83
+ /**
84
+ * Verifies if log rotation is needed by checking if the day has changed.
85
+ * If rotation is needed, creates a new log file and triggers cleanup of old files.
86
+ * This method should be called before each write operation to ensure proper rotation.
87
+ *
88
+ * @returns {void}
89
+ */
90
+ verify() {
91
+ const today = new Date().getDate();
92
+ if (today === this._currentDay) {
93
+ return;
94
+ }
95
+ try {
96
+ fs.mkdirSync(this.config.directory.txt, { recursive: true });
97
+ this._txtFilename = path.resolve(this.config.directory.txt, this.format.filename());
98
+ fs.appendFileSync(this._txtFilename, this.format.separator());
99
+ if (this.config.json) {
100
+ fs.mkdirSync(this.config.directory.json, { recursive: true });
101
+ this._jsonFilename = path.resolve(this.config.directory.json, this.format.jsonFilename());
102
+ fs.appendFileSync(this._jsonFilename, this.format.jsonSeparator());
103
+ }
104
+ this._initialized = true;
105
+ this.rotate().catch((error) => console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : error rotating VLoggo > ${error.message}`));
106
+ }
107
+ catch (error) {
108
+ console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : error verifying VLoggo rotation > ${error.message}`);
109
+ }
110
+ }
111
+ /**
112
+ * Rotates log files by removing old files that exceed the retention count.
113
+ * Scans the log directory, sorts files by modification time (newest first),
114
+ * and deletes the oldest files when the count exceeds config.filecount.
115
+ *
116
+ * @private
117
+ * @async
118
+ * @returns {Promise<void>}
119
+ */
120
+ async rotate() {
121
+ try {
122
+ const txtDirectory = this.config.directory.txt;
123
+ const txtFiles = await fsp.readdir(txtDirectory);
124
+ const logFilesPromises = txtFiles
125
+ .filter((file) => file.endsWith(".txt"))
126
+ .map(async (file) => {
127
+ const filePath = path.join(txtDirectory, file);
128
+ const stats = await fsp.stat(filePath);
129
+ return {
130
+ name: file,
131
+ path: filePath,
132
+ mtime: stats.mtime.getTime(),
133
+ };
134
+ });
135
+ const logFiles = (await Promise.all(logFilesPromises)).sort((a, b) => b.mtime - a.mtime);
136
+ if (logFiles.length > this.config.filecount.txt) {
137
+ const filesToDelete = logFiles.slice(this.config.filecount.txt);
138
+ await Promise.allSettled(filesToDelete.map(async (file) => {
139
+ try {
140
+ await fsp.unlink(file.path);
141
+ }
142
+ catch (error) {
143
+ console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : error deleting old .txt file > ${error.message}`);
144
+ }
145
+ }));
146
+ }
147
+ if (this.config.json) {
148
+ const jsonDirectory = this.config.directory.json;
149
+ const jsonFiles = await fsp.readdir(jsonDirectory);
150
+ const logFilesPromises = jsonFiles
151
+ .filter((file) => file.endsWith(".jsonl"))
152
+ .map(async (file) => {
153
+ const filePath = path.join(jsonDirectory, file);
154
+ const stats = await fsp.stat(filePath);
155
+ return {
156
+ name: file,
157
+ path: filePath,
158
+ mtime: stats.mtime.getTime(),
159
+ };
160
+ });
161
+ const logFiles = (await Promise.all(logFilesPromises)).sort((a, b) => b.mtime - a.mtime);
162
+ if (logFiles.length > this.config.filecount.json) {
163
+ const filesToDelete = logFiles.slice(this.config.filecount.json);
164
+ await Promise.allSettled(filesToDelete.map(async (file) => {
165
+ try {
166
+ await fsp.unlink(file.path);
167
+ }
168
+ catch (error) {
169
+ console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : error deleting old .json file > ${error.message}`);
170
+ }
171
+ }));
172
+ }
173
+ }
174
+ }
175
+ catch (error) {
176
+ console.error(`[VLoggo] > [${this.config.client}] [${this.format.date()}] [ERROR] : VLoggo cleanup failed > ${error.message}`);
177
+ }
178
+ }
179
+ /**
180
+ * Gets the initialization status of the file service.
181
+ *
182
+ * @readonly
183
+ * @returns {boolean} True if the service is initialized and ready to write logs
184
+ */
185
+ get initialized() {
186
+ return this._initialized;
187
+ }
188
+ }
189
+ export default FileService;
@@ -0,0 +1,64 @@
1
+ import { LogEntry } from "../interfaces/interfaces";
2
+ /**
3
+ * Service responsible for formatting log-related strings.
4
+ * Provides utilities for date formatting, filename generation, separators, and caller traceability.
5
+ *
6
+ * @class FormatService
7
+ */
8
+ declare class FormatService {
9
+ private client?;
10
+ constructor(client?: string | undefined);
11
+ /**
12
+ * Formats a date object into DD/MM/YYYY HH:mm:ss format.
13
+ * @param date - Date to format
14
+ * @returns Formatted date string
15
+ */
16
+ date(date?: Date): string;
17
+ /**
18
+ * Formats a date into ISO 8601 format for JSON logs.
19
+ * @param date - Date to format
20
+ * @returns ISO formatted date string
21
+ */
22
+ isoDate(date?: Date): string;
23
+ /**
24
+ * Formats a filename based on the current date (YYYY-MM-DD).
25
+ * @returns Filename in format log-YYYY-MM-DD.txt
26
+ */
27
+ filename(): string;
28
+ /**
29
+ * Formats a JSON filename based on the current date.
30
+ * @returns Filename in format log-YYYY-MM-DD.jsonl
31
+ */
32
+ jsonFilename(): string;
33
+ /**
34
+ * Formats a complete log entry into a single line.
35
+ * @param entry - Log entry to format
36
+ * @returns Formatted log line
37
+ */
38
+ line(entry: LogEntry): string;
39
+ /**
40
+ * Formats a log entry as JSON.
41
+ * @param entry - Log entry to format
42
+ * @param pretty - Whether to pretty-print the JSON
43
+ * @returns JSON string with newline
44
+ */
45
+ jsonLine(entry: LogEntry, pretty?: boolean): string;
46
+ /**
47
+ * Creates a separator line for log file initialization.
48
+ * @param message - Optional message to include
49
+ * @returns Formatted separator with message
50
+ */
51
+ separator(): string;
52
+ /**
53
+ * Creates a JSON separator for log file initialization.
54
+ * @returns JSON formatted initialization entry
55
+ */
56
+ jsonSeparator(): string;
57
+ /**
58
+ * Gets caller location as "file.ts:line"
59
+ * @param skip - Number of stack frames to skip (default: 0)
60
+ * @returns Formatted string like "server.ts:123" or empty string if failed
61
+ */
62
+ caller(skip?: number): string;
63
+ }
64
+ export default FormatService;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Service responsible for formatting log-related strings.
3
+ * Provides utilities for date formatting, filename generation, separators, and caller traceability.
4
+ *
5
+ * @class FormatService
6
+ */
7
+ class FormatService {
8
+ client;
9
+ constructor(client) {
10
+ this.client = client;
11
+ if (!client) {
12
+ client = "VLoggo";
13
+ }
14
+ }
15
+ /**
16
+ * Formats a date object into DD/MM/YYYY HH:mm:ss format.
17
+ * @param date - Date to format
18
+ * @returns Formatted date string
19
+ */
20
+ date(date = new Date()) {
21
+ const pad = (num) => num.toString().padStart(2, "0");
22
+ const d = pad(date.getDate());
23
+ const m = pad(date.getMonth() + 1);
24
+ const y = date.getFullYear();
25
+ const h = pad(date.getHours());
26
+ const min = pad(date.getMinutes());
27
+ const s = pad(date.getSeconds());
28
+ return `${d}/${m}/${y} ${h}:${min}:${s}`;
29
+ }
30
+ /**
31
+ * Formats a date into ISO 8601 format for JSON logs.
32
+ * @param date - Date to format
33
+ * @returns ISO formatted date string
34
+ */
35
+ isoDate(date = new Date()) {
36
+ return date.toISOString();
37
+ }
38
+ /**
39
+ * Formats a filename based on the current date (YYYY-MM-DD).
40
+ * @returns Filename in format log-YYYY-MM-DD.txt
41
+ */
42
+ filename() {
43
+ const now = new Date();
44
+ const year = now.getFullYear();
45
+ const month = String(now.getMonth() + 1).padStart(2, "0");
46
+ const day = String(now.getDate()).padStart(2, "0");
47
+ return `log-${year}-${month}-${day}.txt`;
48
+ }
49
+ /**
50
+ * Formats a JSON filename based on the current date.
51
+ * @returns Filename in format log-YYYY-MM-DD.jsonl
52
+ */
53
+ jsonFilename() {
54
+ const now = new Date();
55
+ const year = now.getFullYear();
56
+ const month = String(now.getMonth() + 1).padStart(2, "0");
57
+ const day = String(now.getDate()).padStart(2, "0");
58
+ return `log-${year}-${month}-${day}.jsonl`;
59
+ }
60
+ /**
61
+ * Formats a complete log entry into a single line.
62
+ * @param entry - Log entry to format
63
+ * @returns Formatted log line
64
+ */
65
+ line(entry) {
66
+ const timestamp = this.date(new Date());
67
+ return `[${this.client}] [${timestamp}] [${entry.level}] [${entry.code}] [${entry.caller}]: ${entry.message}\n`;
68
+ }
69
+ /**
70
+ * Formats a log entry as JSON.
71
+ * @param entry - Log entry to format
72
+ * @param pretty - Whether to pretty-print the JSON
73
+ * @returns JSON string with newline
74
+ */
75
+ jsonLine(entry, pretty = true) {
76
+ const jsonEntry = {
77
+ client: this.client,
78
+ timestamp: this.isoDate(new Date()),
79
+ level: entry.level,
80
+ code: entry.code,
81
+ caller: entry.caller,
82
+ message: entry.message,
83
+ };
84
+ return JSON.stringify(jsonEntry) + "\n";
85
+ }
86
+ /**
87
+ * Creates a separator line for log file initialization.
88
+ * @param message - Optional message to include
89
+ * @returns Formatted separator with message
90
+ */
91
+ separator() {
92
+ const separator = "\n" + "_".repeat(50) + "\n\n";
93
+ const timestamp = this.date();
94
+ return `${separator}[${this.client}] [${timestamp}] [INIT] : VLoggo initialized successfully \n`;
95
+ }
96
+ /**
97
+ * Creates a JSON separator for log file initialization.
98
+ * @returns JSON formatted initialization entry
99
+ */
100
+ jsonSeparator() {
101
+ const initEntry = {
102
+ client: this.client,
103
+ timestamp: this.isoDate(new Date()),
104
+ level: "INIT",
105
+ message: "VLoggo initialized successfully",
106
+ };
107
+ return JSON.stringify(initEntry) + "\n";
108
+ }
109
+ /**
110
+ * Gets caller location as "file.ts:line"
111
+ * @param skip - Number of stack frames to skip (default: 0)
112
+ * @returns Formatted string like "server.ts:123" or empty string if failed
113
+ */
114
+ caller(skip = 0) {
115
+ const err = new Error();
116
+ const stack = err.stack;
117
+ if (!stack) {
118
+ return "(unknown:0)";
119
+ }
120
+ const lines = stack.split("\n");
121
+ const targetLine = lines[skip + 2];
122
+ if (!targetLine) {
123
+ return "(unknown:0)";
124
+ }
125
+ const match = targetLine.match(/\((.+?):(\d+):\d+\)/) ||
126
+ targetLine.match(/at\s+(.+?):(\d+):\d+/);
127
+ if (!match) {
128
+ return "(unknown:0)";
129
+ }
130
+ const [, filepath, line] = match;
131
+ const filename = filepath.split(/[/\\]/).pop() || filepath;
132
+ return `${filename}:${line}`;
133
+ }
134
+ }
135
+ export default FormatService;