@jonit-dev/night-watch-cli 1.3.0 → 1.4.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.
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +21 -10
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/serve.d.ts +7 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +27 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +3 -0
- package/dist/constants.js.map +1 -1
- package/dist/server/index.d.ts +23 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +470 -0
- package/dist/server/index.js.map +1 -0
- package/dist/utils/checks.d.ts +55 -0
- package/dist/utils/checks.d.ts.map +1 -0
- package/dist/utils/checks.js +246 -0
- package/dist/utils/checks.js.map +1 -0
- package/dist/utils/registry.d.ts +39 -0
- package/dist/utils/registry.d.ts.map +1 -0
- package/dist/utils/registry.js +97 -0
- package/dist/utils/registry.js.map +1 -0
- package/package.json +12 -3
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP API Server for Night Watch CLI
|
|
3
|
+
* Provides REST API endpoints for the Web UI
|
|
4
|
+
* Supports both single-project and global (multi-project) modes
|
|
5
|
+
*/
|
|
6
|
+
import express, { Router } from "express";
|
|
7
|
+
import cors from "cors";
|
|
8
|
+
import { execSync, spawn } from "child_process";
|
|
9
|
+
import * as fs from "fs";
|
|
10
|
+
import * as path from "path";
|
|
11
|
+
import { dirname } from "path";
|
|
12
|
+
import { fileURLToPath } from "url";
|
|
13
|
+
import { CONFIG_FILE_NAME, LOG_DIR } from "../constants.js";
|
|
14
|
+
import { loadConfig } from "../config.js";
|
|
15
|
+
import { validateWebhook } from "../commands/doctor.js";
|
|
16
|
+
import { collectPrInfo, collectPrdInfo, fetchStatusSnapshot, getLastLogLines } from "../utils/status-data.js";
|
|
17
|
+
import { saveConfig } from "../utils/config-writer.js";
|
|
18
|
+
import { loadRegistry, validateRegistry } from "../utils/registry.js";
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
20
|
+
const __dirname = dirname(__filename);
|
|
21
|
+
// Track spawned processes
|
|
22
|
+
const spawnedProcesses = new Map();
|
|
23
|
+
/**
|
|
24
|
+
* Error handler middleware
|
|
25
|
+
*/
|
|
26
|
+
function errorHandler(err, _req, res, _next) {
|
|
27
|
+
console.error("API Error:", err);
|
|
28
|
+
res.status(500).json({ error: err.message });
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Validate PRD name to prevent path traversal
|
|
32
|
+
*/
|
|
33
|
+
function validatePrdName(name) {
|
|
34
|
+
return /^[a-zA-Z0-9_-]+(\.md)?$/.test(name) && !name.includes("..");
|
|
35
|
+
}
|
|
36
|
+
// ==================== Extracted Route Handlers ====================
|
|
37
|
+
function handleGetStatus(projectDir, config, _req, res) {
|
|
38
|
+
try {
|
|
39
|
+
const snapshot = fetchStatusSnapshot(projectDir, config);
|
|
40
|
+
res.json(snapshot);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function handleGetPrds(projectDir, config, _req, res) {
|
|
47
|
+
try {
|
|
48
|
+
const prds = collectPrdInfo(projectDir, config.prdDir, config.maxRuntime);
|
|
49
|
+
const prdsWithContent = prds.map((prd) => {
|
|
50
|
+
const prdPath = path.join(projectDir, config.prdDir, `${prd.name}.md`);
|
|
51
|
+
let content = "";
|
|
52
|
+
if (fs.existsSync(prdPath)) {
|
|
53
|
+
try {
|
|
54
|
+
content = fs.readFileSync(prdPath, "utf-8");
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
content = "";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { ...prd, content };
|
|
61
|
+
});
|
|
62
|
+
res.json(prdsWithContent);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function handleGetPrdByName(projectDir, config, req, res) {
|
|
69
|
+
try {
|
|
70
|
+
const { name } = req.params;
|
|
71
|
+
if (!validatePrdName(name)) {
|
|
72
|
+
res.status(400).json({ error: "Invalid PRD name" });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const nameStr = name;
|
|
76
|
+
const filename = nameStr.endsWith(".md") ? nameStr : `${nameStr}.md`;
|
|
77
|
+
const prdPath = path.join(projectDir, config.prdDir, filename);
|
|
78
|
+
if (!fs.existsSync(prdPath)) {
|
|
79
|
+
res.status(404).json({ error: "PRD not found" });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const content = fs.readFileSync(prdPath, "utf-8");
|
|
83
|
+
res.json({ name: filename.replace(/\.md$/, ""), content });
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function handleGetPrs(projectDir, config, _req, res) {
|
|
90
|
+
try {
|
|
91
|
+
const prs = collectPrInfo(projectDir, config.branchPatterns);
|
|
92
|
+
res.json(prs);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function handleGetLogs(projectDir, _config, req, res) {
|
|
99
|
+
try {
|
|
100
|
+
const { name } = req.params;
|
|
101
|
+
const validNames = ["executor", "reviewer"];
|
|
102
|
+
if (!validNames.includes(name)) {
|
|
103
|
+
res.status(400).json({ error: `Invalid log name. Must be one of: ${validNames.join(", ")}` });
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const linesParam = req.query.lines;
|
|
107
|
+
const lines = typeof linesParam === "string" ? parseInt(linesParam, 10) : 200;
|
|
108
|
+
const linesToRead = isNaN(lines) || lines < 1 ? 200 : Math.min(lines, 10000);
|
|
109
|
+
const logPath = path.join(projectDir, LOG_DIR, `${name}.log`);
|
|
110
|
+
const logLines = getLastLogLines(logPath, linesToRead);
|
|
111
|
+
res.json({ name, lines: logLines });
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function handleGetConfig(config, _req, res) {
|
|
118
|
+
try {
|
|
119
|
+
res.json(config);
|
|
120
|
+
}
|
|
121
|
+
catch (error) {
|
|
122
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
function handlePutConfig(projectDir, getConfig, reloadConfig, req, res) {
|
|
126
|
+
try {
|
|
127
|
+
const changes = req.body;
|
|
128
|
+
if (typeof changes !== "object" || changes === null) {
|
|
129
|
+
res.status(400).json({ error: "Invalid request body" });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (changes.provider !== undefined) {
|
|
133
|
+
const validProviders = ["claude", "codex"];
|
|
134
|
+
if (!validProviders.includes(changes.provider)) {
|
|
135
|
+
res.status(400).json({ error: `Invalid provider. Must be one of: ${validProviders.join(", ")}` });
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (changes.reviewerEnabled !== undefined) {
|
|
140
|
+
if (typeof changes.reviewerEnabled !== "boolean") {
|
|
141
|
+
res.status(400).json({ error: "reviewerEnabled must be a boolean" });
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
if (changes.maxRuntime !== undefined) {
|
|
146
|
+
if (typeof changes.maxRuntime !== "number" || changes.maxRuntime < 60) {
|
|
147
|
+
res.status(400).json({ error: "maxRuntime must be a number >= 60" });
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
if (changes.reviewerMaxRuntime !== undefined) {
|
|
152
|
+
if (typeof changes.reviewerMaxRuntime !== "number" || changes.reviewerMaxRuntime < 60) {
|
|
153
|
+
res.status(400).json({ error: "reviewerMaxRuntime must be a number >= 60" });
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (changes.minReviewScore !== undefined) {
|
|
158
|
+
if (typeof changes.minReviewScore !== "number" || changes.minReviewScore < 0 || changes.minReviewScore > 100) {
|
|
159
|
+
res.status(400).json({ error: "minReviewScore must be a number between 0 and 100" });
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (changes.maxLogSize !== undefined) {
|
|
164
|
+
if (typeof changes.maxLogSize !== "number" || changes.maxLogSize < 0) {
|
|
165
|
+
res.status(400).json({ error: "maxLogSize must be a positive number" });
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (changes.branchPatterns !== undefined) {
|
|
170
|
+
if (!Array.isArray(changes.branchPatterns) || !changes.branchPatterns.every((p) => typeof p === "string")) {
|
|
171
|
+
res.status(400).json({ error: "branchPatterns must be an array of strings" });
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (changes.prdPriority !== undefined) {
|
|
176
|
+
if (!Array.isArray(changes.prdPriority) || !changes.prdPriority.every((p) => typeof p === "string")) {
|
|
177
|
+
res.status(400).json({ error: "prdPriority must be an array of strings" });
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (changes.cronSchedule !== undefined) {
|
|
182
|
+
if (typeof changes.cronSchedule !== "string" || changes.cronSchedule.trim().length === 0) {
|
|
183
|
+
res.status(400).json({ error: "cronSchedule must be a non-empty string" });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (changes.reviewerSchedule !== undefined) {
|
|
188
|
+
if (typeof changes.reviewerSchedule !== "string" || changes.reviewerSchedule.trim().length === 0) {
|
|
189
|
+
res.status(400).json({ error: "reviewerSchedule must be a non-empty string" });
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
if (changes.notifications?.webhooks !== undefined) {
|
|
194
|
+
if (!Array.isArray(changes.notifications.webhooks)) {
|
|
195
|
+
res.status(400).json({ error: "notifications.webhooks must be an array" });
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
for (const webhook of changes.notifications.webhooks) {
|
|
199
|
+
const issues = validateWebhook(webhook);
|
|
200
|
+
if (issues.length > 0) {
|
|
201
|
+
res.status(400).json({ error: `Invalid webhook: ${issues.join(", ")}` });
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const result = saveConfig(projectDir, changes);
|
|
207
|
+
if (!result.success) {
|
|
208
|
+
res.status(500).json({ error: result.error });
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
reloadConfig();
|
|
212
|
+
res.json(getConfig());
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
function handleGetDoctor(projectDir, config, _req, res) {
|
|
219
|
+
try {
|
|
220
|
+
const checks = [];
|
|
221
|
+
try {
|
|
222
|
+
execSync("git rev-parse --is-inside-work-tree", { cwd: projectDir, stdio: "pipe" });
|
|
223
|
+
checks.push({ name: "git", status: "pass", detail: "Git repository detected" });
|
|
224
|
+
}
|
|
225
|
+
catch {
|
|
226
|
+
checks.push({ name: "git", status: "fail", detail: "Not a git repository" });
|
|
227
|
+
}
|
|
228
|
+
try {
|
|
229
|
+
execSync(`which ${config.provider}`, { stdio: "pipe" });
|
|
230
|
+
checks.push({ name: "provider", status: "pass", detail: `Provider CLI found: ${config.provider}` });
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
checks.push({ name: "provider", status: "fail", detail: `Provider CLI not found: ${config.provider}` });
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
const { getEntries, getProjectEntries, generateMarker } = require("../utils/crontab.js");
|
|
237
|
+
const projectName = path.basename(projectDir);
|
|
238
|
+
const marker = generateMarker(projectName);
|
|
239
|
+
const crontabEntries = [...getEntries(marker), ...getProjectEntries(projectDir)];
|
|
240
|
+
if (crontabEntries.length > 0) {
|
|
241
|
+
checks.push({
|
|
242
|
+
name: "crontab",
|
|
243
|
+
status: "pass",
|
|
244
|
+
detail: `${crontabEntries.length} crontab entr(y/ies) installed`,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
checks.push({ name: "crontab", status: "warn", detail: "No crontab entries installed" });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
catch (_error) {
|
|
252
|
+
checks.push({ name: "crontab", status: "fail", detail: "Failed to check crontab" });
|
|
253
|
+
}
|
|
254
|
+
const configPath = path.join(projectDir, CONFIG_FILE_NAME);
|
|
255
|
+
if (fs.existsSync(configPath)) {
|
|
256
|
+
checks.push({ name: "config", status: "pass", detail: "Config file exists" });
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
checks.push({ name: "config", status: "warn", detail: "Config file not found (using defaults)" });
|
|
260
|
+
}
|
|
261
|
+
const prdDir = path.join(projectDir, config.prdDir);
|
|
262
|
+
if (fs.existsSync(prdDir)) {
|
|
263
|
+
const prds = fs.readdirSync(prdDir).filter((f) => f.endsWith(".md") && f !== "NIGHT-WATCH-SUMMARY.md");
|
|
264
|
+
checks.push({ name: "prdDir", status: "pass", detail: `PRD directory exists (${prds.length} PRDs)` });
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
checks.push({ name: "prdDir", status: "warn", detail: `PRD directory not found: ${config.prdDir}` });
|
|
268
|
+
}
|
|
269
|
+
res.json(checks);
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
function handleSpawnAction(projectDir, command, _req, res) {
|
|
276
|
+
try {
|
|
277
|
+
const child = spawn("night-watch", command, {
|
|
278
|
+
detached: true,
|
|
279
|
+
stdio: "ignore",
|
|
280
|
+
cwd: projectDir,
|
|
281
|
+
});
|
|
282
|
+
child.unref();
|
|
283
|
+
if (child.pid !== undefined) {
|
|
284
|
+
spawnedProcesses.set(child.pid, child);
|
|
285
|
+
res.json({ started: true, pid: child.pid });
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
res.status(500).json({ error: "Failed to spawn process: no PID assigned" });
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// ==================== Static Files + SPA Fallback ====================
|
|
296
|
+
function setupStaticFiles(app) {
|
|
297
|
+
const webDistPath = path.join(__dirname, "../../web/dist");
|
|
298
|
+
if (fs.existsSync(webDistPath)) {
|
|
299
|
+
app.use(express.static(webDistPath));
|
|
300
|
+
}
|
|
301
|
+
app.use((req, res, next) => {
|
|
302
|
+
if (req.path.startsWith("/api/")) {
|
|
303
|
+
next();
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
const indexPath = path.join(webDistPath, "index.html");
|
|
307
|
+
if (fs.existsSync(indexPath)) {
|
|
308
|
+
res.sendFile(indexPath);
|
|
309
|
+
}
|
|
310
|
+
else {
|
|
311
|
+
next();
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
// ==================== Single-Project Mode ====================
|
|
316
|
+
/**
|
|
317
|
+
* Create and configure the Express application (single-project mode)
|
|
318
|
+
*/
|
|
319
|
+
export function createApp(projectDir) {
|
|
320
|
+
const app = express();
|
|
321
|
+
app.use(cors());
|
|
322
|
+
app.use(express.json());
|
|
323
|
+
let config = loadConfig(projectDir);
|
|
324
|
+
const reloadConfig = () => {
|
|
325
|
+
config = loadConfig(projectDir);
|
|
326
|
+
};
|
|
327
|
+
// API Routes
|
|
328
|
+
app.get("/api/status", (req, res) => handleGetStatus(projectDir, config, req, res));
|
|
329
|
+
app.get("/api/prds", (req, res) => handleGetPrds(projectDir, config, req, res));
|
|
330
|
+
app.get("/api/prds/:name", (req, res) => handleGetPrdByName(projectDir, config, req, res));
|
|
331
|
+
app.get("/api/prs", (req, res) => handleGetPrs(projectDir, config, req, res));
|
|
332
|
+
app.get("/api/logs/:name", (req, res) => handleGetLogs(projectDir, config, req, res));
|
|
333
|
+
app.get("/api/config", (req, res) => handleGetConfig(config, req, res));
|
|
334
|
+
app.put("/api/config", (req, res) => handlePutConfig(projectDir, () => config, reloadConfig, req, res));
|
|
335
|
+
app.get("/api/doctor", (req, res) => handleGetDoctor(projectDir, config, req, res));
|
|
336
|
+
app.post("/api/actions/run", (req, res) => handleSpawnAction(projectDir, ["run"], req, res));
|
|
337
|
+
app.post("/api/actions/review", (req, res) => handleSpawnAction(projectDir, ["review"], req, res));
|
|
338
|
+
app.post("/api/actions/install-cron", (req, res) => handleSpawnAction(projectDir, ["install"], req, res));
|
|
339
|
+
app.post("/api/actions/uninstall-cron", (req, res) => handleSpawnAction(projectDir, ["uninstall"], req, res));
|
|
340
|
+
setupStaticFiles(app);
|
|
341
|
+
app.use(errorHandler);
|
|
342
|
+
return app;
|
|
343
|
+
}
|
|
344
|
+
// ==================== Global (Multi-Project) Mode ====================
|
|
345
|
+
/**
|
|
346
|
+
* Middleware that resolves a project from the registry by :projectId param
|
|
347
|
+
*/
|
|
348
|
+
function resolveProject(req, res, next) {
|
|
349
|
+
const projectId = req.params.projectId;
|
|
350
|
+
const decodedId = decodeURIComponent(projectId);
|
|
351
|
+
const entries = loadRegistry();
|
|
352
|
+
const entry = entries.find((e) => e.name === decodedId);
|
|
353
|
+
if (!entry) {
|
|
354
|
+
res.status(404).json({ error: `Project not found: ${decodedId}` });
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
if (!fs.existsSync(entry.path) || !fs.existsSync(path.join(entry.path, CONFIG_FILE_NAME))) {
|
|
358
|
+
res.status(404).json({ error: `Project path invalid or missing config: ${entry.path}` });
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
req.projectDir = entry.path;
|
|
362
|
+
req.projectConfig = loadConfig(entry.path);
|
|
363
|
+
next();
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Create a router with all project-scoped endpoints
|
|
367
|
+
*/
|
|
368
|
+
function createProjectRouter() {
|
|
369
|
+
const router = Router({ mergeParams: true });
|
|
370
|
+
const dir = (req) => req.projectDir;
|
|
371
|
+
const cfg = (req) => req.projectConfig;
|
|
372
|
+
router.get("/status", (req, res) => handleGetStatus(dir(req), cfg(req), req, res));
|
|
373
|
+
router.get("/prds", (req, res) => handleGetPrds(dir(req), cfg(req), req, res));
|
|
374
|
+
router.get("/prds/:name", (req, res) => handleGetPrdByName(dir(req), cfg(req), req, res));
|
|
375
|
+
router.get("/prs", (req, res) => handleGetPrs(dir(req), cfg(req), req, res));
|
|
376
|
+
router.get("/logs/:name", (req, res) => handleGetLogs(dir(req), cfg(req), req, res));
|
|
377
|
+
router.get("/config", (req, res) => handleGetConfig(cfg(req), req, res));
|
|
378
|
+
router.put("/config", (req, res) => {
|
|
379
|
+
const projectDir = dir(req);
|
|
380
|
+
let config = cfg(req);
|
|
381
|
+
handlePutConfig(projectDir, () => config, () => { config = loadConfig(projectDir); }, req, res);
|
|
382
|
+
});
|
|
383
|
+
router.get("/doctor", (req, res) => handleGetDoctor(dir(req), cfg(req), req, res));
|
|
384
|
+
router.post("/actions/run", (req, res) => handleSpawnAction(dir(req), ["run"], req, res));
|
|
385
|
+
router.post("/actions/review", (req, res) => handleSpawnAction(dir(req), ["review"], req, res));
|
|
386
|
+
router.post("/actions/install-cron", (req, res) => handleSpawnAction(dir(req), ["install"], req, res));
|
|
387
|
+
router.post("/actions/uninstall-cron", (req, res) => handleSpawnAction(dir(req), ["uninstall"], req, res));
|
|
388
|
+
return router;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Create the Express application for global (multi-project) mode
|
|
392
|
+
*/
|
|
393
|
+
export function createGlobalApp() {
|
|
394
|
+
const app = express();
|
|
395
|
+
app.use(cors());
|
|
396
|
+
app.use(express.json());
|
|
397
|
+
// List all registered projects
|
|
398
|
+
app.get("/api/projects", (_req, res) => {
|
|
399
|
+
try {
|
|
400
|
+
const entries = loadRegistry();
|
|
401
|
+
const { invalid } = validateRegistry();
|
|
402
|
+
const invalidPaths = new Set(invalid.map((e) => e.path));
|
|
403
|
+
res.json(entries.map((e) => ({
|
|
404
|
+
name: e.name,
|
|
405
|
+
path: e.path,
|
|
406
|
+
valid: !invalidPaths.has(e.path),
|
|
407
|
+
})));
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
// Project-scoped routes
|
|
414
|
+
app.use("/api/projects/:projectId", resolveProject, createProjectRouter());
|
|
415
|
+
setupStaticFiles(app);
|
|
416
|
+
app.use(errorHandler);
|
|
417
|
+
return app;
|
|
418
|
+
}
|
|
419
|
+
// ==================== Server Startup ====================
|
|
420
|
+
/**
|
|
421
|
+
* Graceful shutdown handler
|
|
422
|
+
*/
|
|
423
|
+
function setupGracefulShutdown(server) {
|
|
424
|
+
process.on("SIGTERM", () => {
|
|
425
|
+
console.log("SIGTERM received, shutting down server...");
|
|
426
|
+
server.close(() => {
|
|
427
|
+
console.log("Server closed");
|
|
428
|
+
process.exit(0);
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
process.on("SIGINT", () => {
|
|
432
|
+
console.log("\nSIGINT received, shutting down server...");
|
|
433
|
+
server.close(() => {
|
|
434
|
+
console.log("Server closed");
|
|
435
|
+
process.exit(0);
|
|
436
|
+
});
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Start the HTTP server (single-project mode)
|
|
441
|
+
*/
|
|
442
|
+
export function startServer(projectDir, port) {
|
|
443
|
+
const app = createApp(projectDir);
|
|
444
|
+
const server = app.listen(port, () => {
|
|
445
|
+
console.log(`Night Watch UI running at http://localhost:${port}`);
|
|
446
|
+
});
|
|
447
|
+
setupGracefulShutdown(server);
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Start the HTTP server (global multi-project mode)
|
|
451
|
+
*/
|
|
452
|
+
export function startGlobalServer(port) {
|
|
453
|
+
const entries = loadRegistry();
|
|
454
|
+
if (entries.length === 0) {
|
|
455
|
+
console.error("No projects registered. Run 'night-watch init' in a project first.");
|
|
456
|
+
process.exit(1);
|
|
457
|
+
}
|
|
458
|
+
const { valid, invalid } = validateRegistry();
|
|
459
|
+
if (invalid.length > 0) {
|
|
460
|
+
console.warn(`Warning: ${invalid.length} registered project(s) have invalid paths and will be skipped.`);
|
|
461
|
+
}
|
|
462
|
+
console.log(`Managing ${valid.length} project(s):`);
|
|
463
|
+
valid.forEach((p) => console.log(` - ${p.name} (${p.path})`));
|
|
464
|
+
const app = createGlobalApp();
|
|
465
|
+
const server = app.listen(port, () => {
|
|
466
|
+
console.log(`Night Watch Global UI running at http://localhost:${port}`);
|
|
467
|
+
});
|
|
468
|
+
setupGracefulShutdown(server);
|
|
469
|
+
}
|
|
470
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared validation utilities for Night Watch CLI
|
|
3
|
+
* Used by init, doctor, and other commands that need to verify environment
|
|
4
|
+
*/
|
|
5
|
+
import { Provider } from "../types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Result of an environment check
|
|
8
|
+
*/
|
|
9
|
+
export interface ICheckResult {
|
|
10
|
+
passed: boolean;
|
|
11
|
+
message: string;
|
|
12
|
+
fixable: boolean;
|
|
13
|
+
fix?: () => void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Check if directory is a git repository
|
|
17
|
+
*/
|
|
18
|
+
export declare function checkGitRepo(cwd: string): ICheckResult;
|
|
19
|
+
/**
|
|
20
|
+
* Check if GitHub CLI is authenticated
|
|
21
|
+
*/
|
|
22
|
+
export declare function checkGhCli(): ICheckResult;
|
|
23
|
+
/**
|
|
24
|
+
* Check if a specific provider CLI is available
|
|
25
|
+
*/
|
|
26
|
+
export declare function checkProviderCli(provider: Provider): ICheckResult;
|
|
27
|
+
/**
|
|
28
|
+
* Detect which AI provider CLIs are installed
|
|
29
|
+
*/
|
|
30
|
+
export declare function detectProviders(): Provider[];
|
|
31
|
+
/**
|
|
32
|
+
* Check if Node.js version meets minimum requirement
|
|
33
|
+
*/
|
|
34
|
+
export declare function checkNodeVersion(minMajor: number): ICheckResult;
|
|
35
|
+
/**
|
|
36
|
+
* Check if config file exists and is valid JSON
|
|
37
|
+
*/
|
|
38
|
+
export declare function checkConfigFile(projectDir: string): ICheckResult;
|
|
39
|
+
/**
|
|
40
|
+
* Check if PRD directory exists
|
|
41
|
+
*/
|
|
42
|
+
export declare function checkPrdDirectory(projectDir: string, prdDir: string): ICheckResult;
|
|
43
|
+
/**
|
|
44
|
+
* Check if logs directory exists
|
|
45
|
+
*/
|
|
46
|
+
export declare function checkLogsDirectory(projectDir: string): ICheckResult;
|
|
47
|
+
/**
|
|
48
|
+
* Check if crontab is accessible
|
|
49
|
+
*/
|
|
50
|
+
export declare function checkCrontabAccess(): ICheckResult;
|
|
51
|
+
/**
|
|
52
|
+
* Run all environment checks and return results
|
|
53
|
+
*/
|
|
54
|
+
export declare function runAllChecks(projectDir: string, prdDir: string): ICheckResult[];
|
|
55
|
+
//# sourceMappingURL=checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../../src/utils/checks.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,YAAY,CAOtD;AAED;;GAEG;AACH,wBAAgB,UAAU,IAAI,YAAY,CAkBzC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,YAAY,CAkBjE;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,QAAQ,EAAE,CAc5C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAsB/D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,CA4BhE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,YAAY,CA0Bd;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,YAAY,CAmBnE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CAoBjD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,GACb,YAAY,EAAE,CAuChB"}
|