@shetty4l/core 0.1.17 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/cli.ts +68 -0
- package/src/daemon.ts +19 -3
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -40,6 +40,74 @@ export function formatUptime(seconds: number): string {
|
|
|
40
40
|
return `${hours}h ${mins}m`;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// --- Log file tail ---
|
|
44
|
+
|
|
45
|
+
export interface LogsCommandOpts {
|
|
46
|
+
/** Absolute path to the log file. */
|
|
47
|
+
logFile: string;
|
|
48
|
+
/** Default number of lines when no count is specified. */
|
|
49
|
+
defaultCount?: number;
|
|
50
|
+
/** Message to display when the log file does not exist or is empty. */
|
|
51
|
+
emptyMessage?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Create a `logs` command handler that tails a log file.
|
|
56
|
+
*
|
|
57
|
+
* Supports a positional count argument (`logs 50`) and the standard `--json` flag.
|
|
58
|
+
* Returns exit code 0 on success, 1 on error.
|
|
59
|
+
*/
|
|
60
|
+
export function createLogsCommand(opts: LogsCommandOpts): CommandHandler {
|
|
61
|
+
const {
|
|
62
|
+
logFile,
|
|
63
|
+
defaultCount = 20,
|
|
64
|
+
emptyMessage = "No log entries yet.",
|
|
65
|
+
} = opts;
|
|
66
|
+
|
|
67
|
+
return async (args: string[], json: boolean): Promise<number> => {
|
|
68
|
+
const count = args.length > 0 ? Number.parseInt(args[0], 10) : defaultCount;
|
|
69
|
+
if (Number.isNaN(count) || count <= 0) {
|
|
70
|
+
console.error(`Invalid count: ${args[0]}`);
|
|
71
|
+
return 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const file = Bun.file(logFile);
|
|
75
|
+
if (!(await file.exists())) {
|
|
76
|
+
if (json) {
|
|
77
|
+
console.log(JSON.stringify({ lines: [], file: logFile }));
|
|
78
|
+
} else {
|
|
79
|
+
console.log(emptyMessage);
|
|
80
|
+
}
|
|
81
|
+
return 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const text = await file.text();
|
|
85
|
+
const allLines = text.split("\n").filter((l) => l.length > 0);
|
|
86
|
+
|
|
87
|
+
if (allLines.length === 0) {
|
|
88
|
+
if (json) {
|
|
89
|
+
console.log(JSON.stringify({ lines: [], file: logFile }));
|
|
90
|
+
} else {
|
|
91
|
+
console.log(emptyMessage);
|
|
92
|
+
}
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const lines = allLines.slice(-count);
|
|
97
|
+
|
|
98
|
+
if (json) {
|
|
99
|
+
console.log(
|
|
100
|
+
JSON.stringify({ lines, file: logFile, total: allLines.length }),
|
|
101
|
+
);
|
|
102
|
+
} else {
|
|
103
|
+
for (const line of lines) {
|
|
104
|
+
console.log(line);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return 0;
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
43
111
|
// --- Command dispatch ---
|
|
44
112
|
|
|
45
113
|
export type CommandHandler = (
|
package/src/daemon.ts
CHANGED
|
@@ -7,7 +7,14 @@
|
|
|
7
7
|
* No console output — returns structured results for the caller to log.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
closeSync,
|
|
12
|
+
existsSync,
|
|
13
|
+
mkdirSync,
|
|
14
|
+
openSync,
|
|
15
|
+
readFileSync,
|
|
16
|
+
unlinkSync,
|
|
17
|
+
} from "fs";
|
|
11
18
|
import { join } from "path";
|
|
12
19
|
import type { Result } from "./result";
|
|
13
20
|
import { err, ok } from "./result";
|
|
@@ -153,12 +160,21 @@ export function createDaemonManager(opts: DaemonManagerOpts): DaemonManager {
|
|
|
153
160
|
mkdirSync(configDir, { recursive: true });
|
|
154
161
|
}
|
|
155
162
|
|
|
163
|
+
// Open log file in append mode so previous content is preserved
|
|
164
|
+
// and ongoing console.error output from the child is captured.
|
|
165
|
+
// Bun.file() opens with O_WRONLY|O_CREAT (no append, no truncate)
|
|
166
|
+
// which writes from offset 0 and corrupts logs.
|
|
167
|
+
const logFd = openSync(logFile, "a");
|
|
168
|
+
|
|
156
169
|
const proc = Bun.spawn(["bun", "run", cliPath, serveCommand], {
|
|
157
|
-
stdout:
|
|
158
|
-
stderr:
|
|
170
|
+
stdout: logFd,
|
|
171
|
+
stderr: logFd,
|
|
159
172
|
stdin: "ignore",
|
|
160
173
|
});
|
|
161
174
|
|
|
175
|
+
// Child inherits its own copy of the fd; parent can close safely.
|
|
176
|
+
closeSync(logFd);
|
|
177
|
+
|
|
162
178
|
writePid(pidFile, proc.pid);
|
|
163
179
|
|
|
164
180
|
if (healthUrl) {
|