@codigoconelmer/driftwatch 1.1.5 โ 1.2.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.
- package/README.md +120 -78
- package/dist/checker.d.ts +2 -0
- package/dist/checker.d.ts.map +1 -1
- package/dist/checker.js +66 -26
- package/dist/checker.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +11 -0
- package/dist/config.js.map +1 -1
- package/dist/daemon.d.ts +7 -0
- package/dist/daemon.d.ts.map +1 -0
- package/dist/daemon.js +50 -0
- package/dist/daemon.js.map +1 -0
- package/dist/history.d.ts +10 -0
- package/dist/history.d.ts.map +1 -0
- package/dist/history.js +28 -0
- package/dist/history.js.map +1 -0
- package/dist/index.js +109 -21
- package/dist/index.js.map +1 -1
- package/dist/notifier.d.ts +6 -0
- package/dist/notifier.d.ts.map +1 -0
- package/dist/notifier.js +67 -0
- package/dist/notifier.js.map +1 -0
- package/dist/scheduler.d.ts.map +1 -1
- package/dist/scheduler.js +20 -4
- package/dist/scheduler.js.map +1 -1
- package/dist/snapshot.d.ts +1 -0
- package/dist/snapshot.d.ts.map +1 -1
- package/dist/snapshot.js +7 -0
- package/dist/snapshot.js.map +1 -1
- package/dist/status.d.ts +15 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +43 -0
- package/dist/status.js.map +1 -0
- package/dist/telegram.d.ts +2 -0
- package/dist/telegram.d.ts.map +1 -1
- package/dist/telegram.js +12 -0
- package/dist/telegram.js.map +1 -1
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/webui.d.ts +2 -0
- package/dist/webui.d.ts.map +1 -0
- package/dist/webui.js +124 -0
- package/dist/webui.js.map +1 -0
- package/package.json +7 -13
package/dist/webui.js
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import http from 'http';
|
|
2
|
+
import { readStatusData } from './status.js';
|
|
3
|
+
import { readHistory } from './history.js';
|
|
4
|
+
const PORT = 4573;
|
|
5
|
+
const HTML = `<!DOCTYPE html>
|
|
6
|
+
<html lang="en">
|
|
7
|
+
<head>
|
|
8
|
+
<meta charset="UTF-8">
|
|
9
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
10
|
+
<title>DriftWatch</title>
|
|
11
|
+
<style>
|
|
12
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
13
|
+
body { font-family: 'Courier New', monospace; background: #0d1117; color: #e6edf3; padding: 2rem; }
|
|
14
|
+
h1 { color: #58a6ff; font-size: 1.5rem; margin-bottom: 0.25rem; }
|
|
15
|
+
.subtitle { color: #8b949e; font-size: 0.85rem; margin-bottom: 2rem; }
|
|
16
|
+
h2 { font-size: 1rem; color: #8b949e; text-transform: uppercase; letter-spacing: 0.1em; margin: 2rem 0 1rem; }
|
|
17
|
+
table { width: 100%; border-collapse: collapse; }
|
|
18
|
+
th { text-align: left; color: #8b949e; font-size: 0.8rem; padding: 0.5rem 0.75rem; border-bottom: 1px solid #30363d; }
|
|
19
|
+
td { padding: 0.5rem 0.75rem; border-bottom: 1px solid #161b22; font-size: 0.9rem; }
|
|
20
|
+
tr:hover td { background: #161b22; }
|
|
21
|
+
.ok { color: #3fb950; }
|
|
22
|
+
.drift { color: #d29922; }
|
|
23
|
+
.down { color: #f85149; }
|
|
24
|
+
.first-run { color: #58a6ff; }
|
|
25
|
+
.history-card { background: #161b22; border: 1px solid #30363d; border-radius: 6px; padding: 1rem; margin-bottom: 0.75rem; }
|
|
26
|
+
.history-header { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.5rem; }
|
|
27
|
+
.history-name { font-weight: bold; color: #e6edf3; }
|
|
28
|
+
.history-time { color: #8b949e; font-size: 0.8rem; }
|
|
29
|
+
.diff-line { font-size: 0.85rem; padding: 0.15rem 0; }
|
|
30
|
+
.added { color: #3fb950; }
|
|
31
|
+
.removed { color: #f85149; }
|
|
32
|
+
.changed { color: #d29922; }
|
|
33
|
+
.empty-state { color: #8b949e; font-style: italic; padding: 1rem 0; }
|
|
34
|
+
.refresh { color: #8b949e; font-size: 0.75rem; }
|
|
35
|
+
</style>
|
|
36
|
+
</head>
|
|
37
|
+
<body>
|
|
38
|
+
<h1>๐ DriftWatch</h1>
|
|
39
|
+
<div class="subtitle">Refreshes every 30s ยท <span class="refresh" id="last-refresh">โ</span></div>
|
|
40
|
+
|
|
41
|
+
<h2>Endpoints</h2>
|
|
42
|
+
<table>
|
|
43
|
+
<thead><tr><th>Name</th><th>Status</th><th>Last Check</th><th>Reason</th></tr></thead>
|
|
44
|
+
<tbody id="endpoints-body"></tbody>
|
|
45
|
+
</table>
|
|
46
|
+
|
|
47
|
+
<h2>Drift History</h2>
|
|
48
|
+
<div id="history-list"></div>
|
|
49
|
+
|
|
50
|
+
<script>
|
|
51
|
+
const ICONS = { ok: 'โ
', drift: 'โ ๏ธ', down: '๐ด', 'first-run': '๐ต' };
|
|
52
|
+
|
|
53
|
+
async function load() {
|
|
54
|
+
const [status, history] = await Promise.all([
|
|
55
|
+
fetch('/api/status').then(r => r.json()),
|
|
56
|
+
fetch('/api/history').then(r => r.json()),
|
|
57
|
+
]);
|
|
58
|
+
|
|
59
|
+
const tbody = document.getElementById('endpoints-body');
|
|
60
|
+
const entries = Object.entries(status.endpoints || {});
|
|
61
|
+
tbody.innerHTML = entries.length === 0
|
|
62
|
+
? '<tr><td colspan="4" class="empty-state">No checks recorded yet.</td></tr>'
|
|
63
|
+
: entries.map(([name, e]) => \`
|
|
64
|
+
<tr>
|
|
65
|
+
<td>\${name}</td>
|
|
66
|
+
<td class="\${e.status}">\${ICONS[e.status] || 'โ'} \${e.status}</td>
|
|
67
|
+
<td>\${new Date(e.lastCheck).toLocaleString()}</td>
|
|
68
|
+
<td>\${e.reason || 'โ'}</td>
|
|
69
|
+
</tr>\`).join('');
|
|
70
|
+
|
|
71
|
+
const historyEl = document.getElementById('history-list');
|
|
72
|
+
if (!history.length) {
|
|
73
|
+
historyEl.innerHTML = '<p class="empty-state">No drift detected yet.</p>';
|
|
74
|
+
} else {
|
|
75
|
+
historyEl.innerHTML = [...history].reverse().map(e => \`
|
|
76
|
+
<div class="history-card">
|
|
77
|
+
<div class="history-header">
|
|
78
|
+
<span class="history-name">\${e.endpoint}</span>
|
|
79
|
+
<span class="history-time">\${new Date(e.timestamp).toLocaleString()}</span>
|
|
80
|
+
</div>
|
|
81
|
+
\${e.diff.added.map(d => \`<div class="diff-line added">+ \${d.path} (\${d.type})</div>\`).join('')}
|
|
82
|
+
\${e.diff.removed.map(d => \`<div class="diff-line removed">- \${d.path} (\${d.type})</div>\`).join('')}
|
|
83
|
+
\${e.diff.changed.map(d => \`<div class="diff-line changed">~ \${d.path}: \${d.from} โ \${d.to}</div>\`).join('')}
|
|
84
|
+
</div>\`).join('');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
document.getElementById('last-refresh').textContent = 'Last updated ' + new Date().toLocaleTimeString();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
load();
|
|
91
|
+
setInterval(load, 30000);
|
|
92
|
+
</script>
|
|
93
|
+
</body>
|
|
94
|
+
</html>`;
|
|
95
|
+
export function startWebUI(port = PORT) {
|
|
96
|
+
const server = http.createServer((req, res) => {
|
|
97
|
+
if (req.url === '/api/status') {
|
|
98
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
99
|
+
res.end(JSON.stringify(readStatusData()));
|
|
100
|
+
}
|
|
101
|
+
else if (req.url === '/api/history') {
|
|
102
|
+
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
103
|
+
res.end(JSON.stringify(readHistory()));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
|
|
107
|
+
res.end(HTML);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
server.on('error', (err) => {
|
|
111
|
+
if (err.code === 'EADDRINUSE') {
|
|
112
|
+
console.error(`[driftwatch] Port ${port} already in use. Try: driftwatch ui --port 4574`);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
console.error(`[driftwatch] Failed to start web UI: ${err.message}`);
|
|
116
|
+
}
|
|
117
|
+
process.exit(1);
|
|
118
|
+
});
|
|
119
|
+
server.listen(port, () => {
|
|
120
|
+
console.log(`[driftwatch] Web UI โ http://localhost:${port}`);
|
|
121
|
+
console.log('[driftwatch] Ctrl+C to stop.');
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=webui.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webui.js","sourceRoot":"","sources":["../src/webui.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,IAAI,GAAG,IAAI,CAAC;AAElB,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyFL,CAAC;AAET,MAAM,UAAU,UAAU,CAAC,IAAI,GAAG,IAAI;IACpC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QAC5C,IAAI,GAAG,CAAC,GAAG,KAAK,aAAa,EAAE,CAAC;YAC9B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC;aAAM,IAAI,GAAG,CAAC,GAAG,KAAK,cAAc,EAAE,CAAC;YACtC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC;YAC3D,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,0BAA0B,EAAE,CAAC,CAAC;YACnE,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;QAChD,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,qBAAqB,IAAI,iDAAiD,CAAC,CAAC;QAC5F,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,wCAAwC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QACvB,OAAO,CAAC,GAAG,CAAC,0CAA0C,IAAI,EAAE,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codigoconelmer/driftwatch",
|
|
3
|
-
"version": "1.1
|
|
4
|
-
"description": "External API schema drift detector with Telegram
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "External API schema drift detector with alerts via Telegram, Slack, and Discord",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"bin": {
|
|
8
8
|
"driftwatch": "./dist/index.js"
|
|
9
9
|
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"build": "tsc",
|
|
12
|
-
"dev": "tsx src/index.ts",
|
|
13
|
-
"start": "node dist/index.js",
|
|
14
|
-
"prepublishOnly": "pnpm build"
|
|
15
|
-
},
|
|
16
10
|
"files": [
|
|
17
11
|
"dist",
|
|
18
12
|
"README.md",
|
|
@@ -55,9 +49,9 @@
|
|
|
55
49
|
"engines": {
|
|
56
50
|
"node": ">=18"
|
|
57
51
|
},
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsc",
|
|
54
|
+
"dev": "tsx src/index.ts",
|
|
55
|
+
"start": "node dist/index.js"
|
|
62
56
|
}
|
|
63
|
-
}
|
|
57
|
+
}
|