prodboard 0.2.1 → 0.2.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.
- package/CHANGELOG.md +6 -0
- package/README.md +1 -0
- package/package.json +1 -1
- package/src/commands/daemon.ts +1 -29
- package/src/commands/install.ts +1 -19
- package/src/config.ts +51 -2
- package/src/index.ts +12 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# prodboard
|
|
2
2
|
|
|
3
|
+
## 0.2.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`62ef4b0`](https://github.com/G4brym/prodboard/commit/62ef4b0a1f6969e3d06f549635ebfd337b84403c) Thanks [@G4brym](https://github.com/G4brym)! - Show config warnings (tmux availability, webui dependencies) on every CLI command. Improved webui dependency messages with actionable install commands.
|
|
8
|
+
|
|
3
9
|
## 0.2.1
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -166,6 +166,7 @@ prodboard schedule stats --days 7 # Statistics
|
|
|
166
166
|
prodboard daemon # Start (foreground)
|
|
167
167
|
prodboard daemon --dry-run # Preview schedules
|
|
168
168
|
prodboard daemon status # Check if running
|
|
169
|
+
prodboard daemon restart # Restart via systemd
|
|
169
170
|
```
|
|
170
171
|
|
|
171
172
|
### Other
|
package/package.json
CHANGED
package/src/commands/daemon.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as fs from "fs";
|
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import * as os from "os";
|
|
4
4
|
import { ensureDb } from "../db.ts";
|
|
5
|
-
import { loadConfig,
|
|
5
|
+
import { loadConfig, PRODBOARD_DIR } from "../config.ts";
|
|
6
6
|
import { listSchedules } from "../queries/schedules.ts";
|
|
7
7
|
import { getNextFire } from "../cron.ts";
|
|
8
8
|
import { formatDate } from "../format.ts";
|
|
@@ -114,34 +114,6 @@ export async function daemonStatus(args: string[]): Promise<void> {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
export async function daemonRestart(_args: string[]): Promise<void> {
|
|
117
|
-
// Validate config
|
|
118
|
-
let config;
|
|
119
|
-
try {
|
|
120
|
-
const { config: cfg, rawParsed } = loadConfigRaw();
|
|
121
|
-
config = cfg;
|
|
122
|
-
const { errors, warnings } = validateConfig(rawParsed);
|
|
123
|
-
for (const e of errors) {
|
|
124
|
-
console.error(`✗ Config: ${e}`);
|
|
125
|
-
}
|
|
126
|
-
if (errors.length > 0) {
|
|
127
|
-
process.exit(1);
|
|
128
|
-
}
|
|
129
|
-
for (const w of warnings) {
|
|
130
|
-
console.warn(`⚠ Config: ${w}`);
|
|
131
|
-
}
|
|
132
|
-
} catch (err: any) {
|
|
133
|
-
console.error(`Config error: ${err.message}`);
|
|
134
|
-
process.exit(1);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Check webui dependencies
|
|
138
|
-
if (config.webui.enabled) {
|
|
139
|
-
const depWarnings = await checkWebuiDependencies();
|
|
140
|
-
for (const w of depWarnings) {
|
|
141
|
-
console.warn(`⚠ ${w}`);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
117
|
// Check systemd availability
|
|
146
118
|
if (!(await systemctlAvailable())) {
|
|
147
119
|
console.error("systemd is not available. daemon restart requires systemd.");
|
package/src/commands/install.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
2
|
import * as path from "path";
|
|
3
3
|
import * as os from "os";
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
|
|
6
6
|
const SERVICE_NAME = "prodboard";
|
|
7
7
|
const SERVICE_DIR = path.join(os.homedir(), ".config", "systemd", "user");
|
|
@@ -63,24 +63,6 @@ WantedBy=default.target
|
|
|
63
63
|
export async function install(args: string[]): Promise<void> {
|
|
64
64
|
const { flags } = parseArgs(args);
|
|
65
65
|
|
|
66
|
-
// Validate config before proceeding
|
|
67
|
-
try {
|
|
68
|
-
const { config, rawParsed } = loadConfigRaw();
|
|
69
|
-
const { warnings } = validateConfig(rawParsed);
|
|
70
|
-
for (const w of warnings) {
|
|
71
|
-
console.warn(`⚠ Config: ${w}`);
|
|
72
|
-
}
|
|
73
|
-
if (config.webui.enabled) {
|
|
74
|
-
const depWarnings = await checkWebuiDependencies();
|
|
75
|
-
for (const w of depWarnings) {
|
|
76
|
-
console.warn(`⚠ ${w}`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
} catch (err: any) {
|
|
80
|
-
console.error(`Config error: ${err.message}`);
|
|
81
|
-
process.exit(1);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
66
|
if (!(await systemctlAvailable())) {
|
|
85
67
|
console.error("systemd is not available on this system.");
|
|
86
68
|
console.error("The install command requires systemd (Linux).");
|
package/src/config.ts
CHANGED
|
@@ -240,15 +240,64 @@ export async function checkWebuiDependencies(): Promise<string[]> {
|
|
|
240
240
|
try {
|
|
241
241
|
await import("hono");
|
|
242
242
|
} catch {
|
|
243
|
-
warnings.push(
|
|
243
|
+
warnings.push(
|
|
244
|
+
"webui is enabled but 'hono' is not installed. " +
|
|
245
|
+
"Run: bun install hono (or bun install -g hono if prodboard is installed globally)"
|
|
246
|
+
);
|
|
247
|
+
return warnings; // skip JSX check if hono itself is missing
|
|
244
248
|
}
|
|
245
249
|
try {
|
|
246
250
|
await import("hono/jsx/jsx-runtime");
|
|
247
251
|
} catch {
|
|
248
252
|
warnings.push(
|
|
249
253
|
"webui is enabled but the Hono JSX runtime could not be loaded. " +
|
|
250
|
-
"
|
|
254
|
+
"Run: bun install hono (or bun install -g hono if prodboard is installed globally)"
|
|
251
255
|
);
|
|
252
256
|
}
|
|
253
257
|
return warnings;
|
|
254
258
|
}
|
|
259
|
+
|
|
260
|
+
export async function checkTmuxAvailable(): Promise<string | null> {
|
|
261
|
+
try {
|
|
262
|
+
const proc = Bun.spawn(["tmux", "-V"], { stdout: "ignore", stderr: "ignore" });
|
|
263
|
+
const code = await proc.exited;
|
|
264
|
+
if (code !== 0) {
|
|
265
|
+
return "daemon.useTmux is enabled but tmux is not installed. Install it (e.g. apt install tmux) or set useTmux to false.";
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
} catch {
|
|
269
|
+
return "daemon.useTmux is enabled but tmux is not installed. Install it (e.g. apt install tmux) or set useTmux to false.";
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export async function printConfigWarnings(): Promise<void> {
|
|
274
|
+
let config: Config;
|
|
275
|
+
let rawParsed: any;
|
|
276
|
+
try {
|
|
277
|
+
const result = loadConfigRaw();
|
|
278
|
+
config = result.config;
|
|
279
|
+
rawParsed = result.rawParsed;
|
|
280
|
+
} catch (err: any) {
|
|
281
|
+
console.warn(`⚠ Config: ${err.message}`);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
const { warnings } = validateConfig(rawParsed);
|
|
286
|
+
for (const w of warnings) {
|
|
287
|
+
console.warn(`⚠ Config: ${w}`);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (config.daemon.useTmux) {
|
|
291
|
+
const tmuxWarning = await checkTmuxAvailable();
|
|
292
|
+
if (tmuxWarning) {
|
|
293
|
+
console.warn(`⚠ ${tmuxWarning}`);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (config.webui.enabled) {
|
|
298
|
+
const depWarnings = await checkWebuiDependencies();
|
|
299
|
+
for (const w of depWarnings) {
|
|
300
|
+
console.warn(`⚠ ${w}`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync } from "fs";
|
|
2
|
-
import { PRODBOARD_DIR } from "./config.ts";
|
|
2
|
+
import { PRODBOARD_DIR, printConfigWarnings } from "./config.ts";
|
|
3
3
|
|
|
4
4
|
export class NotInitializedError extends Error {
|
|
5
5
|
constructor() {
|
|
@@ -36,6 +36,17 @@ export async function main(): Promise<void> {
|
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
+
// Show config warnings for commands that use the config
|
|
40
|
+
const skipWarnings = ["init", "mcp", "version", "--version", "help", "--help", "uninstall"];
|
|
41
|
+
if (!skipWarnings.includes(command)) {
|
|
42
|
+
try {
|
|
43
|
+
ensureInitialized();
|
|
44
|
+
await printConfigWarnings();
|
|
45
|
+
} catch {
|
|
46
|
+
// ensureInitialized will throw again inside the switch if needed
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
39
50
|
try {
|
|
40
51
|
switch (command) {
|
|
41
52
|
case "init": {
|