@graphty/remote-logger 0.0.1 → 1.1.1

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.
Files changed (48) hide show
  1. package/README.md +636 -28
  2. package/bin/remote-log-server.js +3 -0
  3. package/dist/client/RemoteLogClient.d.ts +114 -0
  4. package/dist/client/RemoteLogClient.d.ts.map +1 -0
  5. package/dist/client/RemoteLogClient.js +238 -0
  6. package/dist/client/RemoteLogClient.js.map +1 -0
  7. package/dist/client/index.d.ts +7 -0
  8. package/dist/client/index.d.ts.map +1 -0
  9. package/dist/client/index.js +6 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/client/types.d.ts +47 -0
  12. package/dist/client/types.d.ts.map +1 -0
  13. package/dist/client/types.js +6 -0
  14. package/dist/client/types.js.map +1 -0
  15. package/dist/index.d.ts +22 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +23 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/server/index.d.ts +8 -0
  20. package/dist/server/index.d.ts.map +1 -0
  21. package/dist/server/index.js +8 -0
  22. package/dist/server/index.js.map +1 -0
  23. package/dist/server/log-server.d.ts +75 -0
  24. package/dist/server/log-server.d.ts.map +1 -0
  25. package/dist/server/log-server.js +453 -0
  26. package/dist/server/log-server.js.map +1 -0
  27. package/dist/server/self-signed-cert.d.ts +30 -0
  28. package/dist/server/self-signed-cert.d.ts.map +1 -0
  29. package/dist/server/self-signed-cert.js +83 -0
  30. package/dist/server/self-signed-cert.js.map +1 -0
  31. package/dist/ui/ConsoleCaptureUI.d.ts +118 -0
  32. package/dist/ui/ConsoleCaptureUI.d.ts.map +1 -0
  33. package/dist/ui/ConsoleCaptureUI.js +571 -0
  34. package/dist/ui/ConsoleCaptureUI.js.map +1 -0
  35. package/dist/ui/index.d.ts +15 -0
  36. package/dist/ui/index.d.ts.map +1 -0
  37. package/dist/ui/index.js +15 -0
  38. package/dist/ui/index.js.map +1 -0
  39. package/package.json +80 -7
  40. package/src/client/RemoteLogClient.ts +280 -0
  41. package/src/client/index.ts +7 -0
  42. package/src/client/types.ts +49 -0
  43. package/src/index.ts +28 -0
  44. package/src/server/index.ts +17 -0
  45. package/src/server/log-server.ts +571 -0
  46. package/src/server/self-signed-cert.ts +93 -0
  47. package/src/ui/ConsoleCaptureUI.ts +649 -0
  48. package/src/ui/index.ts +15 -0
@@ -0,0 +1,453 @@
1
+ /**
2
+ * Remote Log Server - A standalone HTTP/HTTPS log server for remote debugging.
3
+ *
4
+ * Features:
5
+ * - HTTPS with auto-generated self-signed certs or custom certs
6
+ * - Receives logs from browser via POST /log
7
+ * - Pretty terminal output with colors
8
+ * - REST API for querying logs
9
+ * - Optional file logging for Claude Code to read
10
+ *
11
+ * Usage:
12
+ * npx remote-log-server --port 9080
13
+ * npx remote-log-server --cert /path/to/cert.crt --key /path/to/key.key
14
+ */
15
+ import * as fs from "fs";
16
+ import * as http from "http";
17
+ import * as https from "https";
18
+ import { URL } from "url";
19
+ import { certFilesExist, generateSelfSignedCert, readCertFiles } from "./self-signed-cert.js";
20
+ // ANSI color codes for terminal output
21
+ const colors = {
22
+ reset: "\x1b[0m",
23
+ bright: "\x1b[1m",
24
+ dim: "\x1b[2m",
25
+ red: "\x1b[31m",
26
+ green: "\x1b[32m",
27
+ yellow: "\x1b[33m",
28
+ blue: "\x1b[34m",
29
+ magenta: "\x1b[35m",
30
+ cyan: "\x1b[36m",
31
+ white: "\x1b[37m",
32
+ bgRed: "\x1b[41m",
33
+ bgYellow: "\x1b[43m",
34
+ };
35
+ // Store for remote logs by session
36
+ const remoteLogs = new Map();
37
+ // File stream for log file
38
+ let logFileStream = null;
39
+ /**
40
+ * Clear all stored logs.
41
+ * Useful for testing.
42
+ */
43
+ export function clearLogs() {
44
+ remoteLogs.clear();
45
+ }
46
+ /**
47
+ * Format log level for terminal output with colors.
48
+ * @param level - The log level string
49
+ * @returns Colored and formatted log level string
50
+ */
51
+ function formatLogLevel(level) {
52
+ switch (level.toUpperCase()) {
53
+ case "ERROR":
54
+ return `${colors.bgRed}${colors.white} ERROR ${colors.reset}`;
55
+ case "WARN":
56
+ case "WARNING":
57
+ return `${colors.bgYellow}${colors.bright} WARN ${colors.reset}`;
58
+ case "INFO":
59
+ return `${colors.blue} INFO ${colors.reset}`;
60
+ case "DEBUG":
61
+ return `${colors.cyan} DEBUG ${colors.reset}`;
62
+ case "TRACE":
63
+ return `${colors.dim} TRACE ${colors.reset}`;
64
+ case "LOG":
65
+ default:
66
+ return `${colors.green} LOG ${colors.reset}`;
67
+ }
68
+ }
69
+ /**
70
+ * Display a log entry in the terminal.
71
+ * @param sessionId - The session ID for this log entry
72
+ * @param log - The log entry to display
73
+ * @param quiet - If true, suppress terminal output
74
+ */
75
+ function displayLog(sessionId, log, quiet) {
76
+ if (!quiet) {
77
+ const time = new Date(log.time).toLocaleTimeString();
78
+ const level = formatLogLevel(log.level);
79
+ const session = `${colors.cyan}[${sessionId.substring(0, 12)}]${colors.reset}`;
80
+ // Truncate very long messages for display
81
+ let { message } = log;
82
+ if (message.length > 1000) {
83
+ message = `${message.substring(0, 1000)}... [truncated]`;
84
+ }
85
+ // eslint-disable-next-line no-console
86
+ console.log(`${time} ${session} ${level} ${message}`);
87
+ }
88
+ // Write to log file if configured
89
+ if (logFileStream) {
90
+ const logLine = JSON.stringify({
91
+ time: log.time,
92
+ sessionId,
93
+ level: log.level,
94
+ message: log.message,
95
+ });
96
+ logFileStream.write(`${logLine}\n`);
97
+ }
98
+ }
99
+ /**
100
+ * Handle incoming HTTP request.
101
+ * @param req - The incoming HTTP request
102
+ * @param res - The HTTP response object
103
+ * @param host - The server hostname
104
+ * @param port - The server port number
105
+ * @param useHttps - Whether HTTPS is being used
106
+ * @param quiet - If true, suppress terminal output
107
+ */
108
+ function handleRequest(req, res, host, port, useHttps, quiet) {
109
+ // CORS headers
110
+ res.setHeader("Access-Control-Allow-Origin", "*");
111
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
112
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type");
113
+ if (req.method === "OPTIONS") {
114
+ res.writeHead(204);
115
+ res.end();
116
+ return;
117
+ }
118
+ const url = req.url ?? "/";
119
+ const protocol = useHttps ? "https" : "http";
120
+ // Handle log endpoint - receive logs from browser
121
+ if (url === "/log" && req.method === "POST") {
122
+ let body = "";
123
+ req.on("data", (chunk) => {
124
+ body += chunk.toString();
125
+ });
126
+ req.on("end", () => {
127
+ try {
128
+ const data = JSON.parse(body);
129
+ const { sessionId, logs } = data;
130
+ // Initialize session if new
131
+ if (!remoteLogs.has(sessionId)) {
132
+ remoteLogs.set(sessionId, []);
133
+ if (!quiet) {
134
+ // eslint-disable-next-line no-console
135
+ console.log(`\n${colors.bright}${colors.magenta}═══════════════════════════════════════════════════════════${colors.reset}`);
136
+ // eslint-disable-next-line no-console
137
+ console.log(`${colors.bright}${colors.magenta} NEW SESSION: ${sessionId}${colors.reset}`);
138
+ // eslint-disable-next-line no-console
139
+ console.log(`${colors.bright}${colors.magenta}═══════════════════════════════════════════════════════════${colors.reset}\n`);
140
+ }
141
+ }
142
+ const sessionLogs = remoteLogs.get(sessionId);
143
+ if (!sessionLogs) {
144
+ // Should not happen since we just set it above, but satisfy TypeScript
145
+ res.writeHead(500, { "Content-Type": "application/json" });
146
+ res.end(JSON.stringify({ error: "Internal error" }));
147
+ return;
148
+ }
149
+ // Display and store each log
150
+ for (const log of logs) {
151
+ sessionLogs.push(log);
152
+ displayLog(sessionId, log, quiet);
153
+ }
154
+ res.writeHead(200, { "Content-Type": "application/json" });
155
+ res.end(JSON.stringify({ success: true }));
156
+ }
157
+ catch (error) {
158
+ if (!quiet) {
159
+ console.error("Error parsing log data:", error);
160
+ }
161
+ res.writeHead(400, { "Content-Type": "application/json" });
162
+ res.end(JSON.stringify({ error: "Invalid JSON" }));
163
+ }
164
+ });
165
+ return;
166
+ }
167
+ // Handle logs viewer endpoint - GET all logs
168
+ if (url === "/logs" && req.method === "GET") {
169
+ const allLogs = {};
170
+ for (const [sessionId, logs] of remoteLogs) {
171
+ allLogs[sessionId] = logs;
172
+ }
173
+ res.writeHead(200, { "Content-Type": "application/json" });
174
+ res.end(JSON.stringify(allLogs, null, 2));
175
+ return;
176
+ }
177
+ // Handle recent logs endpoint - GET last N logs across all sessions
178
+ if (url.startsWith("/logs/recent") && req.method === "GET") {
179
+ const urlObj = new URL(url, `${protocol}://${host}:${port}`);
180
+ const count = parseInt(urlObj.searchParams.get("n") ?? "50", 10);
181
+ const errorsOnly = urlObj.searchParams.get("errors") === "true";
182
+ // Collect all logs with session info
183
+ const allLogs = [];
184
+ for (const [sessionId, logs] of remoteLogs) {
185
+ for (const log of logs) {
186
+ if (!errorsOnly || log.level.toUpperCase() === "ERROR") {
187
+ allLogs.push({ sessionId, ...log });
188
+ }
189
+ }
190
+ }
191
+ // Sort by time descending and take last N
192
+ allLogs.sort((a, b) => new Date(b.time).getTime() - new Date(a.time).getTime());
193
+ const recentLogs = allLogs.slice(0, count).reverse(); // Reverse to show oldest first
194
+ res.writeHead(200, { "Content-Type": "application/json" });
195
+ res.end(JSON.stringify({
196
+ total: allLogs.length,
197
+ showing: recentLogs.length,
198
+ logs: recentLogs,
199
+ }, null, 2));
200
+ return;
201
+ }
202
+ // Handle errors-only endpoint
203
+ if (url === "/logs/errors" && req.method === "GET") {
204
+ const errorLogs = [];
205
+ for (const [sessionId, logs] of remoteLogs) {
206
+ for (const log of logs) {
207
+ if (log.level.toUpperCase() === "ERROR") {
208
+ errorLogs.push({ sessionId, ...log });
209
+ }
210
+ }
211
+ }
212
+ errorLogs.sort((a, b) => new Date(a.time).getTime() - new Date(b.time).getTime());
213
+ res.writeHead(200, { "Content-Type": "application/json" });
214
+ res.end(JSON.stringify({
215
+ total: errorLogs.length,
216
+ logs: errorLogs,
217
+ }, null, 2));
218
+ return;
219
+ }
220
+ // Handle clear logs endpoint
221
+ if (url === "/logs/clear" && req.method === "POST") {
222
+ remoteLogs.clear();
223
+ if (!quiet) {
224
+ // eslint-disable-next-line no-console
225
+ console.log(`\n${colors.yellow}Logs cleared${colors.reset}\n`);
226
+ }
227
+ res.writeHead(200, { "Content-Type": "application/json" });
228
+ res.end(JSON.stringify({ success: true }));
229
+ return;
230
+ }
231
+ // Health check endpoint
232
+ if (url === "/health" && req.method === "GET") {
233
+ res.writeHead(200, { "Content-Type": "application/json" });
234
+ res.end(JSON.stringify({ status: "ok", sessions: remoteLogs.size }));
235
+ return;
236
+ }
237
+ // Default: 404
238
+ res.writeHead(404, { "Content-Type": "application/json" });
239
+ res.end(JSON.stringify({ error: "Not found" }));
240
+ }
241
+ /**
242
+ * Print startup banner.
243
+ * @param host - The server hostname
244
+ * @param port - The server port number
245
+ * @param useHttps - Whether HTTPS is being used
246
+ */
247
+ function printBanner(host, port, useHttps) {
248
+ const protocol = useHttps ? "https" : "http";
249
+ // eslint-disable-next-line no-console
250
+ console.log("");
251
+ // eslint-disable-next-line no-console
252
+ console.log(`${colors.bright}${colors.cyan}════════════════════════════════════════════════════════════${colors.reset}`);
253
+ // eslint-disable-next-line no-console
254
+ console.log(`${colors.bright}${colors.cyan} Remote Log Server${colors.reset}`);
255
+ // eslint-disable-next-line no-console
256
+ console.log(`${colors.bright}${colors.cyan}════════════════════════════════════════════════════════════${colors.reset}`);
257
+ // eslint-disable-next-line no-console
258
+ console.log("");
259
+ // eslint-disable-next-line no-console
260
+ console.log(`${colors.green}Server running at:${colors.reset} ${colors.bright}${protocol}://${host}:${port}/${colors.reset}`);
261
+ // eslint-disable-next-line no-console
262
+ console.log("");
263
+ // eslint-disable-next-line no-console
264
+ console.log(`${colors.yellow}API Endpoints:${colors.reset}`);
265
+ // eslint-disable-next-line no-console
266
+ console.log(` ${colors.cyan}POST /log ${colors.reset} - Receive logs from browser`);
267
+ // eslint-disable-next-line no-console
268
+ console.log(` ${colors.cyan}GET /logs ${colors.reset} - Get all logs as JSON`);
269
+ // eslint-disable-next-line no-console
270
+ console.log(` ${colors.cyan}GET /logs/recent ${colors.reset} - Get last 50 logs (?n=100 for more)`);
271
+ // eslint-disable-next-line no-console
272
+ console.log(` ${colors.cyan}GET /logs/errors ${colors.reset} - Get only error logs`);
273
+ // eslint-disable-next-line no-console
274
+ console.log(` ${colors.cyan}POST /logs/clear ${colors.reset} - Clear all logs`);
275
+ // eslint-disable-next-line no-console
276
+ console.log(` ${colors.cyan}GET /health ${colors.reset} - Health check`);
277
+ // eslint-disable-next-line no-console
278
+ console.log("");
279
+ // eslint-disable-next-line no-console
280
+ console.log(`${colors.dim}Remote logs will appear below:${colors.reset}`);
281
+ // eslint-disable-next-line no-console
282
+ console.log(`${colors.cyan}────────────────────────────────────────────────────────────${colors.reset}`);
283
+ }
284
+ /**
285
+ * Start the log server.
286
+ * @param options - Server configuration options
287
+ * @returns The HTTP or HTTPS server instance
288
+ */
289
+ export function startLogServer(options = {}) {
290
+ const port = options.port ?? 9080;
291
+ const host = options.host ?? "localhost";
292
+ const useHttp = options.useHttp ?? false;
293
+ const quiet = options.quiet ?? false;
294
+ // Set up log file if specified
295
+ if (options.logFile) {
296
+ logFileStream = fs.createWriteStream(options.logFile, { flags: "a" });
297
+ if (!quiet) {
298
+ // eslint-disable-next-line no-console
299
+ console.log(`${colors.green}Writing logs to: ${options.logFile}${colors.reset}`);
300
+ }
301
+ }
302
+ // Determine SSL configuration
303
+ let server;
304
+ if (useHttp) {
305
+ // Plain HTTP server
306
+ server = http.createServer((req, res) => {
307
+ handleRequest(req, res, host, port, false, quiet);
308
+ });
309
+ }
310
+ else {
311
+ // HTTPS server
312
+ let cert;
313
+ let key;
314
+ if (options.certPath && options.keyPath && certFilesExist(options.certPath, options.keyPath)) {
315
+ // Use provided certificates
316
+ ({ cert, key } = readCertFiles(options.certPath, options.keyPath));
317
+ if (!quiet) {
318
+ // eslint-disable-next-line no-console
319
+ console.log(`${colors.green}Using SSL certificates from: ${options.certPath}${colors.reset}`);
320
+ }
321
+ }
322
+ else {
323
+ // Generate self-signed certificate
324
+ if (!quiet) {
325
+ // eslint-disable-next-line no-console
326
+ console.log(`${colors.yellow}Generating self-signed certificate for ${host}...${colors.reset}`);
327
+ }
328
+ ({ cert, key } = generateSelfSignedCert(host));
329
+ if (!quiet) {
330
+ // eslint-disable-next-line no-console
331
+ console.log(`${colors.yellow}Note: Browser will show certificate warning - this is expected for self-signed certs${colors.reset}`);
332
+ }
333
+ }
334
+ server = https.createServer({ cert, key }, (req, res) => {
335
+ handleRequest(req, res, host, port, true, quiet);
336
+ });
337
+ }
338
+ // Start listening
339
+ server.listen(port, host, () => {
340
+ if (!quiet) {
341
+ printBanner(host, port, !useHttp);
342
+ }
343
+ });
344
+ // Handle graceful shutdown
345
+ process.on("SIGINT", () => {
346
+ // eslint-disable-next-line no-console
347
+ console.log(`\n${colors.yellow}Shutting down...${colors.reset}`);
348
+ if (logFileStream) {
349
+ logFileStream.end();
350
+ }
351
+ server.close(() => {
352
+ process.exit(0);
353
+ });
354
+ });
355
+ return server;
356
+ }
357
+ /**
358
+ * Help text displayed when --help is passed.
359
+ */
360
+ export const HELP_TEXT = `
361
+ Remote Log Server - Remote logging for browser debugging
362
+
363
+ Usage:
364
+ npx remote-log-server [options]
365
+ npx @graphty/remote-logger [options]
366
+
367
+ Options:
368
+ --port, -p <port> Port to listen on (default: 9080)
369
+ --host, -h <host> Hostname to bind to (default: localhost)
370
+ --cert, -c <path> Path to SSL certificate file
371
+ --key, -k <path> Path to SSL private key file
372
+ --log-file, -l <path> Write logs to file
373
+ --http Use HTTP instead of HTTPS
374
+ --quiet, -q Suppress startup banner
375
+ --help Show this help message
376
+
377
+ Examples:
378
+ npx remote-log-server # Start with defaults (port 9080, self-signed cert)
379
+ npx remote-log-server --port 9085 # Custom port
380
+ npx remote-log-server --http # Use HTTP instead of HTTPS
381
+ npx remote-log-server --cert cert.crt --key key.key # Custom SSL certs
382
+ npx remote-log-server --log-file ./tmp/logs.jsonl # Also write to file
383
+ `;
384
+ /**
385
+ * Parse command line arguments into LogServerOptions.
386
+ * This is separated from main() to enable testing.
387
+ * @param args - Array of command line arguments (excluding node and script name)
388
+ * @returns ParseArgsResult with options, help flag, or error
389
+ */
390
+ export function parseArgs(args) {
391
+ const options = {};
392
+ for (let i = 0; i < args.length; i++) {
393
+ const arg = args[i];
394
+ const nextArg = args[i + 1];
395
+ switch (arg) {
396
+ case "--port":
397
+ case "-p":
398
+ options.port = parseInt(nextArg, 10);
399
+ i++;
400
+ break;
401
+ case "--host":
402
+ case "-h":
403
+ options.host = nextArg;
404
+ i++;
405
+ break;
406
+ case "--cert":
407
+ case "-c":
408
+ options.certPath = nextArg;
409
+ i++;
410
+ break;
411
+ case "--key":
412
+ case "-k":
413
+ options.keyPath = nextArg;
414
+ i++;
415
+ break;
416
+ case "--log-file":
417
+ case "-l":
418
+ options.logFile = nextArg;
419
+ i++;
420
+ break;
421
+ case "--http":
422
+ options.useHttp = true;
423
+ break;
424
+ case "--quiet":
425
+ case "-q":
426
+ options.quiet = true;
427
+ break;
428
+ case "--help":
429
+ return { options, showHelp: true };
430
+ default:
431
+ return { options, showHelp: false, error: `Unknown option: ${arg}` };
432
+ }
433
+ }
434
+ return { options, showHelp: false };
435
+ }
436
+ /**
437
+ * Parse command line arguments and start the server.
438
+ */
439
+ export function main() {
440
+ const args = process.argv.slice(2);
441
+ const result = parseArgs(args);
442
+ if (result.showHelp) {
443
+ // eslint-disable-next-line no-console
444
+ console.log(HELP_TEXT);
445
+ process.exit(0);
446
+ }
447
+ if (result.error) {
448
+ console.error(result.error);
449
+ process.exit(1);
450
+ }
451
+ startLogServer(result.options);
452
+ }
453
+ //# sourceMappingURL=log-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-server.js","sourceRoot":"","sources":["../../src/server/log-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Self-signed certificate generation for the log server.
3
+ * Uses the 'selfsigned' npm package to generate proper X.509 certificates.
4
+ */
5
+ export interface GeneratedCert {
6
+ cert: string;
7
+ key: string;
8
+ }
9
+ /**
10
+ * Generate a self-signed certificate for HTTPS.
11
+ * The certificate is valid for localhost and common local development hostnames.
12
+ * @param hostname - Optional hostname to include in the certificate (default: localhost)
13
+ * @returns Object containing PEM-encoded certificate and private key
14
+ */
15
+ export declare function generateSelfSignedCert(hostname?: string): GeneratedCert;
16
+ /**
17
+ * Check if certificate files exist and are readable.
18
+ * @param certPath - Path to the certificate file
19
+ * @param keyPath - Path to the private key file
20
+ * @returns true if both files exist and are readable
21
+ */
22
+ export declare function certFilesExist(certPath: string, keyPath: string): boolean;
23
+ /**
24
+ * Read certificate and key from files.
25
+ * @param certPath - Path to the certificate file
26
+ * @param keyPath - Path to the private key file
27
+ * @returns Object containing PEM-encoded certificate and private key
28
+ */
29
+ export declare function readCertFiles(certPath: string, keyPath: string): GeneratedCert;
30
+ //# sourceMappingURL=self-signed-cert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-signed-cert.d.ts","sourceRoot":"","sources":["../../src/server/self-signed-cert.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,SAAc,GAAG,aAAa,CA4C5E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAQzE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAK9E"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Self-signed certificate generation for the log server.
3
+ * Uses the 'selfsigned' npm package to generate proper X.509 certificates.
4
+ */
5
+ import * as fs from "fs";
6
+ import selfsigned from "selfsigned";
7
+ /**
8
+ * Generate a self-signed certificate for HTTPS.
9
+ * The certificate is valid for localhost and common local development hostnames.
10
+ * @param hostname - Optional hostname to include in the certificate (default: localhost)
11
+ * @returns Object containing PEM-encoded certificate and private key
12
+ */
13
+ export function generateSelfSignedCert(hostname = "localhost") {
14
+ const attrs = [
15
+ { name: "commonName", value: hostname },
16
+ { name: "organizationName", value: "Remote Log Server" },
17
+ { name: "countryName", value: "US" },
18
+ ];
19
+ const options = {
20
+ keySize: 2048,
21
+ days: 365,
22
+ algorithm: "sha256",
23
+ extensions: [
24
+ {
25
+ name: "basicConstraints",
26
+ cA: false,
27
+ },
28
+ {
29
+ name: "keyUsage",
30
+ keyCertSign: false,
31
+ digitalSignature: true,
32
+ keyEncipherment: true,
33
+ },
34
+ {
35
+ name: "extKeyUsage",
36
+ serverAuth: true,
37
+ },
38
+ {
39
+ name: "subjectAltName",
40
+ altNames: [
41
+ { type: 2, value: hostname }, // DNS name
42
+ { type: 2, value: "localhost" },
43
+ { type: 7, ip: "127.0.0.1" }, // IP address
44
+ { type: 7, ip: "::1" }, // IPv6 localhost
45
+ ],
46
+ },
47
+ ],
48
+ };
49
+ const pems = selfsigned.generate(attrs, options);
50
+ return {
51
+ cert: pems.cert,
52
+ key: pems.private,
53
+ };
54
+ }
55
+ /**
56
+ * Check if certificate files exist and are readable.
57
+ * @param certPath - Path to the certificate file
58
+ * @param keyPath - Path to the private key file
59
+ * @returns true if both files exist and are readable
60
+ */
61
+ export function certFilesExist(certPath, keyPath) {
62
+ try {
63
+ fs.accessSync(certPath, fs.constants.R_OK);
64
+ fs.accessSync(keyPath, fs.constants.R_OK);
65
+ return true;
66
+ }
67
+ catch {
68
+ return false;
69
+ }
70
+ }
71
+ /**
72
+ * Read certificate and key from files.
73
+ * @param certPath - Path to the certificate file
74
+ * @param keyPath - Path to the private key file
75
+ * @returns Object containing PEM-encoded certificate and private key
76
+ */
77
+ export function readCertFiles(certPath, keyPath) {
78
+ return {
79
+ cert: fs.readFileSync(certPath, "utf-8"),
80
+ key: fs.readFileSync(keyPath, "utf-8"),
81
+ };
82
+ }
83
+ //# sourceMappingURL=self-signed-cert.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-signed-cert.js","sourceRoot":"","sources":["../../src/server/self-signed-cert.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,UAAU,MAAM,YAAY,CAAC;AAOpC;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAQ,GAAG,WAAW;IACzD,MAAM,KAAK,GAAG;QACV,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE;QACvC,EAAE,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,mBAAmB,EAAE;QACxD,EAAE,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,EAAE;KACvC,CAAC;IAEF,MAAM,OAAO,GAAG;QACZ,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,GAAG;QACT,SAAS,EAAE,QAAiB;QAC5B,UAAU,EAAE;YACR;gBACI,IAAI,EAAE,kBAAkB;gBACxB,EAAE,EAAE,KAAK;aACZ;YACD;gBACI,IAAI,EAAE,UAAU;gBAChB,WAAW,EAAE,KAAK;gBAClB,gBAAgB,EAAE,IAAI;gBACtB,eAAe,EAAE,IAAI;aACxB;YACD;gBACI,IAAI,EAAE,aAAa;gBACnB,UAAU,EAAE,IAAI;aACnB;YACD;gBACI,IAAI,EAAE,gBAAgB;gBACtB,QAAQ,EAAE;oBACN,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,WAAW;oBACzC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE;oBAC/B,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,aAAa;oBAC3C,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,iBAAiB;iBAC5C;aACJ;SACJ;KACJ,CAAC;IAEF,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IAEjD,OAAO;QACH,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,GAAG,EAAE,IAAI,CAAC,OAAO;KACpB,CAAC;AACN,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB,EAAE,OAAe;IAC5D,IAAI,CAAC;QACD,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC3C,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC1C,OAAO,IAAI,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,KAAK,CAAC;IACjB,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,OAAe;IAC3D,OAAO;QACH,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;QACxC,GAAG,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC;KACzC,CAAC;AACN,CAAC"}