node-logy 0.1.0 → 0.1.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.
@@ -0,0 +1,414 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResponseEncoder = exports.RequestEncoder = exports.ProtocolError = exports.VALID_LOG_LEVELS = exports.LOG_LEVEL = exports.VALID_METHODS = exports.METHOD = void 0;
4
+ /**
5
+ * Contains all methods a request / response can have
6
+ */
7
+ exports.METHOD = {
8
+ /**
9
+ * Indicates log information
10
+ */
11
+ LOG: 0x01,
12
+ /**
13
+ * Indicates that it needs flushing i.e write the remaining stuff
14
+ */
15
+ FLUSH: 0x02,
16
+ /**
17
+ * Indicates that the stream opened needs to be closed / re opened typically used for file rotation
18
+ */
19
+ RELOAD: 0x03,
20
+ /**
21
+ * Close the child process
22
+ */
23
+ SHUTDOWN: 0x04,
24
+ };
25
+ /**
26
+ * Contains a set of valid methods
27
+ */
28
+ exports.VALID_METHODS = new Set(Object.values(exports.METHOD));
29
+ /**
30
+ * Contains all the levels logs can be indicating there importance
31
+ */
32
+ exports.LOG_LEVEL = {
33
+ /**
34
+ * Used for information
35
+ */
36
+ INFO: 0x01,
37
+ /**
38
+ * Used for warning
39
+ */
40
+ WARN: 0x02,
41
+ /**
42
+ * Used for errors
43
+ */
44
+ ERROR: 0x03,
45
+ /**
46
+ * Used for debug
47
+ */
48
+ DEBUG: 0x04,
49
+ /**
50
+ * Used for fatal
51
+ */
52
+ FATAL: 0x05,
53
+ };
54
+ /**
55
+ * Contains a set of valid log levels
56
+ */
57
+ exports.VALID_LOG_LEVELS = new Set(Object.values(exports.LOG_LEVEL));
58
+ /**
59
+ * Error thrown when encoding/decoding fails
60
+ */
61
+ class ProtocolError extends Error {
62
+ constructor(message) {
63
+ super(message);
64
+ this.name = "ProtocolError";
65
+ }
66
+ }
67
+ exports.ProtocolError = ProtocolError;
68
+ /**
69
+ * Used to encode the request messages to the buffer protocol encoding
70
+ */
71
+ class RequestEncoder {
72
+ static HEADER_SIZE = 8;
73
+ static MAX_ID = 0xffffffff;
74
+ static MAX_PAYLOAD_LENGTH = 0xffff;
75
+ validMethods;
76
+ validLevels;
77
+ constructor(validMethods = exports.VALID_METHODS, validLevels = exports.VALID_LOG_LEVELS) {
78
+ this.validMethods = validMethods;
79
+ this.validLevels = validLevels;
80
+ }
81
+ /**
82
+ * Validates that a buffer contains a complete, valid request binary protocol
83
+ * without actually decoding the content. Checks:
84
+ * - Buffer has complete header (8 bytes)
85
+ * - Buffer has complete message (header + payload)
86
+ * - Payload length is within valid range (0 to 65535)
87
+ *
88
+ * @param buffer The buffer to validate
89
+ * @returns true if buffer is a valid complete request, false otherwise
90
+ */
91
+ static isValid(buffer) {
92
+ // Check complete header exists
93
+ if (!RequestEncoder.hasCompleteHeader(buffer)) {
94
+ return false;
95
+ }
96
+ // Check payload length is valid
97
+ const payloadLength = RequestEncoder.getPayloadLength(buffer);
98
+ // Check complete message exists
99
+ if (buffer.length !== RequestEncoder.HEADER_SIZE + payloadLength) {
100
+ return false;
101
+ }
102
+ return true;
103
+ }
104
+ /**
105
+ * Instance method to validate with method/level checking
106
+ * Validates that a buffer contains a complete, valid request with valid method and level values
107
+ */
108
+ isValidInstance(buffer) {
109
+ // First do static validation
110
+ if (!RequestEncoder.isValid(buffer)) {
111
+ return false;
112
+ }
113
+ // Check method is valid
114
+ const method = RequestEncoder.getMethod(buffer);
115
+ if (!this.validMethods.has(method)) {
116
+ return false;
117
+ }
118
+ // Check level is valid
119
+ const level = RequestEncoder.getLevel(buffer);
120
+ if (!this.validLevels.has(level)) {
121
+ return false;
122
+ }
123
+ return true;
124
+ }
125
+ /**
126
+ * Get the ID from a buffer (4 bytes, uint32 at offset 0)
127
+ */
128
+ static getId(buffer) {
129
+ return buffer.readUInt32BE(0);
130
+ }
131
+ /**
132
+ * Get the method from a buffer (1 byte at offset 4)
133
+ */
134
+ static getMethod(buffer) {
135
+ return buffer[4];
136
+ }
137
+ /**
138
+ * Get the level from a buffer (1 byte at offset 5)
139
+ */
140
+ static getLevel(buffer) {
141
+ return buffer[5];
142
+ }
143
+ /**
144
+ * Get the payload length from a buffer (2 bytes, uint16 at offset 6)
145
+ */
146
+ static getPayloadLength(buffer) {
147
+ return buffer.readUInt16BE(6);
148
+ }
149
+ /**
150
+ * Get the payload as a Buffer from a buffer (starting at offset 8)
151
+ */
152
+ static getPayloadBuffer(buffer) {
153
+ const payloadLength = RequestEncoder.getPayloadLength(buffer);
154
+ return buffer.subarray(RequestEncoder.HEADER_SIZE, RequestEncoder.HEADER_SIZE + payloadLength);
155
+ }
156
+ /**
157
+ * Get the payload as a UTF-8 string from a buffer
158
+ */
159
+ static getPayloadString(buffer) {
160
+ return RequestEncoder.getPayloadBuffer(buffer).toString("utf-8");
161
+ }
162
+ /**
163
+ * Check if buffer has complete header (8 bytes)
164
+ */
165
+ static hasCompleteHeader(buffer) {
166
+ return buffer.length >= RequestEncoder.HEADER_SIZE;
167
+ }
168
+ /**
169
+ * Check if buffer has complete message (header + payload)
170
+ */
171
+ static hasCompleteMessage(buffer) {
172
+ if (!RequestEncoder.hasCompleteHeader(buffer))
173
+ return false;
174
+ const payloadLength = RequestEncoder.getPayloadLength(buffer);
175
+ return buffer.length >= RequestEncoder.HEADER_SIZE + payloadLength;
176
+ }
177
+ /**
178
+ * Get total message size (header + payload)
179
+ */
180
+ static getTotalMessageSize(buffer) {
181
+ if (!RequestEncoder.hasCompleteHeader(buffer))
182
+ return RequestEncoder.HEADER_SIZE;
183
+ return RequestEncoder.HEADER_SIZE + RequestEncoder.getPayloadLength(buffer);
184
+ }
185
+ /**
186
+ * Encode a request to the binary protocol
187
+ */
188
+ encode(request) {
189
+ if (!Number.isInteger(request.id) ||
190
+ request.id < 0 ||
191
+ request.id > RequestEncoder.MAX_ID) {
192
+ throw new ProtocolError(`Invalid ID: ${request.id}`);
193
+ }
194
+ if (!this.validMethods.has(request.method)) {
195
+ throw new ProtocolError(`Invalid method: ${request.method}`);
196
+ }
197
+ if (!this.validLevels.has(request.level)) {
198
+ throw new ProtocolError(`Invalid level: ${request.level}`);
199
+ }
200
+ const payloadBytes = Buffer.from(request.payload, "utf-8");
201
+ if (payloadBytes.length > RequestEncoder.MAX_PAYLOAD_LENGTH) {
202
+ throw new ProtocolError(`Payload too large: ${payloadBytes.length} bytes`);
203
+ }
204
+ const buffer = Buffer.allocUnsafe(RequestEncoder.HEADER_SIZE + payloadBytes.length);
205
+ buffer.writeUInt32BE(request.id, 0);
206
+ buffer[4] = request.method;
207
+ buffer[5] = request.level;
208
+ buffer.writeUInt16BE(payloadBytes.length, 6);
209
+ payloadBytes.copy(buffer, 8);
210
+ return buffer;
211
+ }
212
+ /**
213
+ * Decode a binary protocol buffer to a request object
214
+ */
215
+ decode(buffer) {
216
+ if (!RequestEncoder.hasCompleteHeader(buffer)) {
217
+ throw new ProtocolError(`Buffer too small: ${buffer.length} bytes, minimum ${RequestEncoder.HEADER_SIZE} bytes required`);
218
+ }
219
+ const id = RequestEncoder.getId(buffer);
220
+ const method = RequestEncoder.getMethod(buffer);
221
+ const level = RequestEncoder.getLevel(buffer);
222
+ const payloadLength = RequestEncoder.getPayloadLength(buffer);
223
+ if (buffer.length !== RequestEncoder.HEADER_SIZE + payloadLength) {
224
+ throw new ProtocolError(`Buffer size mismatch: expected ${RequestEncoder.HEADER_SIZE + payloadLength} bytes, got ${buffer.length} bytes`);
225
+ }
226
+ if (!this.validMethods.has(method)) {
227
+ throw new ProtocolError(`Invalid method: ${method}`);
228
+ }
229
+ if (!this.validLevels.has(level)) {
230
+ throw new ProtocolError(`Invalid level: ${level}`);
231
+ }
232
+ const payload = RequestEncoder.getPayloadString(buffer);
233
+ return {
234
+ id,
235
+ method: method,
236
+ level: level,
237
+ payload,
238
+ };
239
+ }
240
+ static getHeaderSize() {
241
+ return RequestEncoder.HEADER_SIZE;
242
+ }
243
+ }
244
+ exports.RequestEncoder = RequestEncoder;
245
+ /**
246
+ * Used to encode the response messages to the buffer protocol encoding
247
+ */
248
+ class ResponseEncoder {
249
+ static HEADER_SIZE = 8;
250
+ static MAX_ID = 0xffffffff;
251
+ validMethods;
252
+ validLevels;
253
+ constructor(validMethods = exports.VALID_METHODS, validLevels = exports.VALID_LOG_LEVELS) {
254
+ this.validMethods = validMethods;
255
+ this.validLevels = validLevels;
256
+ }
257
+ /**
258
+ * Validates that a buffer contains a valid response binary protocol
259
+ * without actually decoding the content. Checks:
260
+ * - Buffer has complete header (8 bytes)
261
+ * - Reserved byte is 0x00
262
+ * - Success byte is 0 or 1
263
+ *
264
+ * @param buffer The buffer to validate
265
+ * @returns true if buffer is a valid response, false otherwise
266
+ */
267
+ static isValid(buffer) {
268
+ // Check complete header exists (responses are fixed 8 bytes)
269
+ if (buffer.length !== ResponseEncoder.HEADER_SIZE) {
270
+ return false;
271
+ }
272
+ // Check reserved byte is 0x00
273
+ if (buffer[7] !== 0x00) {
274
+ return false;
275
+ }
276
+ // Check success byte is valid (0 or 1)
277
+ const successByte = buffer[6];
278
+ if (successByte !== 0 && successByte !== 1) {
279
+ return false;
280
+ }
281
+ return true;
282
+ }
283
+ /**
284
+ * Instance method to validate with method/level checking
285
+ * Validates that a buffer contains a valid response with valid method and level values
286
+ */
287
+ isValidInstance(buffer) {
288
+ // First do static validation
289
+ if (!ResponseEncoder.isValid(buffer)) {
290
+ return false;
291
+ }
292
+ // Check method is valid
293
+ const method = ResponseEncoder.getMethod(buffer);
294
+ if (!this.validMethods.has(method)) {
295
+ return false;
296
+ }
297
+ // Check level is valid
298
+ const level = ResponseEncoder.getLevel(buffer);
299
+ if (!this.validLevels.has(level)) {
300
+ return false;
301
+ }
302
+ return true;
303
+ }
304
+ /**
305
+ * Get the ID from a buffer (4 bytes, uint32 at offset 0)
306
+ */
307
+ static getId(buffer) {
308
+ return buffer.readUInt32BE(0);
309
+ }
310
+ /**
311
+ * Get the method from a buffer (1 byte at offset 4)
312
+ */
313
+ static getMethod(buffer) {
314
+ return buffer[4];
315
+ }
316
+ /**
317
+ * Get the level from a buffer (1 byte at offset 5)
318
+ */
319
+ static getLevel(buffer) {
320
+ return buffer[5];
321
+ }
322
+ /**
323
+ * Get the success flag from a buffer (1 byte at offset 6)
324
+ * @returns boolean indicating success
325
+ */
326
+ static getSuccess(buffer) {
327
+ const successByte = buffer[6];
328
+ return successByte === 1;
329
+ }
330
+ /**
331
+ * Get the reserved byte from a buffer (1 byte at offset 7)
332
+ */
333
+ static getReserved(buffer) {
334
+ return buffer[7];
335
+ }
336
+ /**
337
+ * Check if buffer has complete header (8 bytes)
338
+ * For responses, this means the buffer is exactly 8 bytes
339
+ */
340
+ static hasCompleteHeader(buffer) {
341
+ return buffer.length >= ResponseEncoder.HEADER_SIZE;
342
+ }
343
+ /**
344
+ * Check if buffer is a complete response message (exactly 8 bytes)
345
+ */
346
+ static hasCompleteMessage(buffer) {
347
+ return buffer.length === ResponseEncoder.HEADER_SIZE;
348
+ }
349
+ /**
350
+ * Get total message size (always 8 bytes for responses)
351
+ */
352
+ static getTotalMessageSize() {
353
+ return ResponseEncoder.HEADER_SIZE;
354
+ }
355
+ /**
356
+ * Encode a response to the binary protocol
357
+ * @param response The JSON response object
358
+ * @returns Binary protocol buffer (exactly 8 bytes)
359
+ */
360
+ encode(response) {
361
+ if (!Number.isInteger(response.id) ||
362
+ response.id < 0 ||
363
+ response.id > ResponseEncoder.MAX_ID) {
364
+ throw new ProtocolError(`Invalid ID: ${response.id}`);
365
+ }
366
+ if (!this.validMethods.has(response.method)) {
367
+ throw new ProtocolError(`Invalid method: ${response.method}`);
368
+ }
369
+ if (!this.validLevels.has(response.level)) {
370
+ throw new ProtocolError(`Invalid level: ${response.level}`);
371
+ }
372
+ const buffer = Buffer.allocUnsafe(ResponseEncoder.HEADER_SIZE);
373
+ buffer.writeUInt32BE(response.id, 0);
374
+ buffer[4] = response.method;
375
+ buffer[5] = response.level;
376
+ buffer[6] = response.success ? 1 : 0;
377
+ buffer[7] = 0x00; // reserved padding
378
+ return buffer;
379
+ }
380
+ /**
381
+ * Decode a binary protocol buffer to a response object
382
+ * @param buffer The binary protocol buffer
383
+ * @returns The decoded response object
384
+ */
385
+ decode(buffer) {
386
+ if (buffer.length !== ResponseEncoder.HEADER_SIZE) {
387
+ throw new ProtocolError(`Invalid buffer size: expected ${ResponseEncoder.HEADER_SIZE} bytes, got ${buffer.length} bytes`);
388
+ }
389
+ const id = ResponseEncoder.getId(buffer);
390
+ const method = ResponseEncoder.getMethod(buffer);
391
+ const level = ResponseEncoder.getLevel(buffer);
392
+ const success = ResponseEncoder.getSuccess(buffer);
393
+ if (buffer[7] !== 0x00) {
394
+ throw new ProtocolError(`Invalid reserved byte: expected 0x00, got 0x${buffer[7]?.toString(16).padStart(2, "0")}`);
395
+ }
396
+ if (!this.validMethods.has(method)) {
397
+ throw new ProtocolError(`Invalid method: ${method}`);
398
+ }
399
+ if (!this.validLevels.has(level)) {
400
+ throw new ProtocolError(`Invalid level: ${level}`);
401
+ }
402
+ return {
403
+ id,
404
+ method: method,
405
+ level: level,
406
+ success,
407
+ };
408
+ }
409
+ static getHeaderSize() {
410
+ return ResponseEncoder.HEADER_SIZE;
411
+ }
412
+ }
413
+ exports.ResponseEncoder = ResponseEncoder;
414
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * This is a self contained script that runs as the server process which accepts the binary protocol and then performs actions
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/dist/server.js ADDED
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ /**
3
+ * This is a self contained script that runs as the server process which accepts the binary protocol and then performs actions
4
+ */
5
+ var __importDefault = (this && this.__importDefault) || function (mod) {
6
+ return (mod && mod.__esModule) ? mod : { "default": mod };
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ const node_path_1 = __importDefault(require("node:path"));
10
+ const protocol_1 = require("./protocol");
11
+ const node_fs_1 = __importDefault(require("node:fs"));
12
+ /**
13
+ * Used for sucess exits
14
+ */
15
+ const EXIT_SUCCESS = 0;
16
+ /**
17
+ * Holds the stream for the log file
18
+ */
19
+ let fileStream = null;
20
+ /**
21
+ * Holds the base path of where to save the log files
22
+ */
23
+ let basePath = "./logs";
24
+ /**
25
+ * Holds stdin buffer
26
+ */
27
+ let stdinBuffer = Buffer.alloc(0);
28
+ /**
29
+ * Holds the array of buffer data we will write to the log file
30
+ */
31
+ let fileWriteBufferArray = [];
32
+ /**
33
+ * How long we wait until we flush unless the buffer gets full
34
+ */
35
+ const FLUSH_MS = 130;
36
+ /**
37
+ * How many buffers can accumulate before we have to flush
38
+ */
39
+ const FILE_WRITE_BUFFER_FLUSH_COUNT = 100;
40
+ /**
41
+ * Holds the timeout for flush
42
+ */
43
+ let flushTimeout = null;
44
+ /**
45
+ * Used to encode and decode response binary protocol data
46
+ */
47
+ const responseEncoder = new protocol_1.ResponseEncoder();
48
+ /**
49
+ * Newline buffer for efficient concatenation
50
+ */
51
+ const NEWLINE_BUFFER = Buffer.from("\n");
52
+ /**
53
+ * Clears the pending flush timeout
54
+ */
55
+ const clearFlushTimeout = () => {
56
+ if (flushTimeout) {
57
+ clearTimeout(flushTimeout);
58
+ flushTimeout = null;
59
+ }
60
+ };
61
+ /**
62
+ * Flushes the buffer array to the file and resets it
63
+ */
64
+ const flush = () => {
65
+ if (fileWriteBufferArray.length === 0 || !fileStream) {
66
+ return;
67
+ }
68
+ const joinedBuffer = Buffer.concat([
69
+ Buffer.concat(fileWriteBufferArray.map((buf, index) => index < fileWriteBufferArray.length - 1
70
+ ? Buffer.concat([buf, NEWLINE_BUFFER])
71
+ : buf)),
72
+ NEWLINE_BUFFER,
73
+ ]);
74
+ fileStream.write(joinedBuffer, (err) => {
75
+ if (err) {
76
+ console.error(`Write error: ${err.message}`);
77
+ }
78
+ });
79
+ fileWriteBufferArray = [];
80
+ clearFlushTimeout();
81
+ };
82
+ /**
83
+ * Starts the delayed flush timer if not already running
84
+ */
85
+ const startFlush = () => {
86
+ if (flushTimeout !== null) {
87
+ return;
88
+ }
89
+ flushTimeout = setTimeout(() => {
90
+ flush();
91
+ }, FLUSH_MS);
92
+ };
93
+ /**
94
+ * Used to send response to the parent
95
+ * @param response The response
96
+ */
97
+ const sendResponse = (response) => {
98
+ process.stdout.write(responseEncoder.encode(response));
99
+ };
100
+ /**
101
+ * Handle the request decoded
102
+ * @param request The request that was buffer bytes extracted
103
+ */
104
+ const requestHandler = (request) => {
105
+ const requestMethod = protocol_1.RequestEncoder.getMethod(request);
106
+ const requestId = protocol_1.RequestEncoder.getId(request);
107
+ const requestLevel = protocol_1.RequestEncoder.getLevel(request);
108
+ switch (requestMethod) {
109
+ case protocol_1.METHOD.LOG: {
110
+ const payload = protocol_1.RequestEncoder.getPayloadBuffer(request);
111
+ fileWriteBufferArray.push(payload);
112
+ if (fileWriteBufferArray.length >= FILE_WRITE_BUFFER_FLUSH_COUNT) {
113
+ flush();
114
+ }
115
+ else {
116
+ startFlush();
117
+ }
118
+ sendResponse({
119
+ id: requestId,
120
+ level: requestLevel,
121
+ method: requestMethod,
122
+ success: true,
123
+ });
124
+ break;
125
+ }
126
+ case protocol_1.METHOD.FLUSH:
127
+ flush();
128
+ if (fileStream?.writableNeedDrain) {
129
+ fileStream.once("drain", () => {
130
+ sendResponse({
131
+ id: requestId,
132
+ level: requestLevel,
133
+ method: requestMethod,
134
+ success: true,
135
+ });
136
+ });
137
+ }
138
+ else {
139
+ sendResponse({
140
+ id: requestId,
141
+ level: requestLevel,
142
+ method: requestMethod,
143
+ success: true,
144
+ });
145
+ }
146
+ break;
147
+ case protocol_1.METHOD.RELOAD:
148
+ flush();
149
+ fileStream?.end(() => {
150
+ fileStream = null;
151
+ createStream();
152
+ sendResponse({
153
+ id: requestId,
154
+ level: requestLevel,
155
+ method: requestMethod,
156
+ success: true,
157
+ });
158
+ });
159
+ return;
160
+ case protocol_1.METHOD.SHUTDOWN:
161
+ flush();
162
+ fileStream?.end(() => {
163
+ sendResponse({
164
+ id: requestId,
165
+ level: requestLevel,
166
+ method: requestMethod,
167
+ success: true,
168
+ });
169
+ setImmediate(() => {
170
+ process.exit(EXIT_SUCCESS);
171
+ });
172
+ });
173
+ return;
174
+ default:
175
+ process.stderr.write(`request unhandled method ${requestMethod}`);
176
+ sendResponse({
177
+ id: requestId,
178
+ level: requestLevel,
179
+ method: requestMethod,
180
+ success: false,
181
+ });
182
+ break;
183
+ }
184
+ };
185
+ /**
186
+ * Parses the buffer and moves it along with backpressure handling
187
+ */
188
+ function parseBuffer() {
189
+ const HEADER_SIZE = protocol_1.RequestEncoder.getHeaderSize();
190
+ while (stdinBuffer.length >= HEADER_SIZE) {
191
+ const payloadLength = protocol_1.RequestEncoder.getPayloadLength(stdinBuffer);
192
+ const totalMessageSize = HEADER_SIZE + payloadLength;
193
+ if (stdinBuffer.length < totalMessageSize) {
194
+ break;
195
+ }
196
+ const messageBuffer = stdinBuffer.subarray(0, totalMessageSize);
197
+ requestHandler(messageBuffer);
198
+ stdinBuffer = stdinBuffer.subarray(totalMessageSize);
199
+ }
200
+ if (stdinBuffer.length >= protocol_1.RequestEncoder.getHeaderSize()) {
201
+ setImmediate(parseBuffer);
202
+ }
203
+ }
204
+ /**
205
+ * Generates a log filename based on current date
206
+ * @returns Filename in format YYYY-MM-DD.log
207
+ */
208
+ const getLogFileName = () => {
209
+ const date = new Date();
210
+ const year = date.getFullYear();
211
+ const month = String(date.getMonth() + 1).padStart(2, "0");
212
+ const day = String(date.getDate()).padStart(2, "0");
213
+ return `${year}-${month}-${day}.log`;
214
+ };
215
+ /**
216
+ * Creates a stream to the file in append mode for today's log file.
217
+ * Closes existing stream if one is already open.
218
+ */
219
+ const createStream = () => {
220
+ fileStream = null;
221
+ const fileName = getLogFileName();
222
+ const filePath = node_path_1.default.join(basePath, fileName);
223
+ fileStream = node_fs_1.default.createWriteStream(filePath, { flags: "a" });
224
+ fileStream.on("error", (err) => {
225
+ console.error(`Stream error: ${err.message}`);
226
+ });
227
+ };
228
+ /**
229
+ * Graceful shutdown handler
230
+ */
231
+ const shutdown = () => {
232
+ clearFlushTimeout();
233
+ flush();
234
+ fileStream?.end(() => {
235
+ process.exit(EXIT_SUCCESS);
236
+ });
237
+ };
238
+ process.on("SIGINT", shutdown);
239
+ process.on("SIGTERM", shutdown);
240
+ /**
241
+ * Main entry point
242
+ */
243
+ async function main() {
244
+ basePath = process.env["BASE_PATH"] ? process.env["BASE_PATH"] : "./logs";
245
+ basePath = node_path_1.default.normalize(node_path_1.default.resolve(basePath));
246
+ await node_fs_1.default.promises.mkdir(basePath, { recursive: true });
247
+ createStream();
248
+ process.stdin.on("data", (chunk) => {
249
+ stdinBuffer = Buffer.concat([stdinBuffer, chunk]);
250
+ parseBuffer();
251
+ });
252
+ process.stdin.on("end", () => {
253
+ shutdown();
254
+ });
255
+ }
256
+ main();
257
+ //# sourceMappingURL=server.js.map