@lifeaitools/clauth 0.7.4 → 0.7.6
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/cli/commands/serve.js +76 -28
- package/package.json +1 -1
package/cli/commands/serve.js
CHANGED
|
@@ -154,6 +154,16 @@ function dashboardHtml(port, whitelist) {
|
|
|
154
154
|
.btn-tunnel-stop{background:#1e293b;color:#f87171;border:1px solid #334155;padding:6px 12px;font-size:.8rem;border-radius:6px;cursor:pointer;font-weight:500}
|
|
155
155
|
.btn-tunnel-stop:hover{background:#2d1f1f;border-color:#f87171}
|
|
156
156
|
.tunnel-err{font-size:.78rem;color:#f87171;width:100%;margin-top:4px}
|
|
157
|
+
.build-panel{background:#0f1a2d;border:1px solid #1e3a5f;border-radius:8px;padding:1rem 1.25rem;margin-bottom:1.25rem;display:flex;align-items:center;gap:12px;flex-wrap:wrap}
|
|
158
|
+
.build-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
|
|
159
|
+
.build-dot.idle{background:#64748b}
|
|
160
|
+
.build-dot.building{background:#3b82f6;animation:pulse 1s infinite}
|
|
161
|
+
.build-dot.succeeded{background:#22c55e}
|
|
162
|
+
.build-dot.failed{background:#ef4444}
|
|
163
|
+
.build-dot.timeout{background:#f59e0b}
|
|
164
|
+
.build-label{font-size:.85rem;color:#94a3b8;flex:1}
|
|
165
|
+
.build-label strong{color:#e2e8f0}
|
|
166
|
+
.build-meta{font-family:'Courier New',monospace;font-size:.75rem;color:#64748b}
|
|
157
167
|
.mcp-setup{background:#0f1d2d;border:1px solid #1e3a5f;border-radius:8px;padding:1rem 1.25rem;margin-bottom:1.25rem;display:none}
|
|
158
168
|
.mcp-setup.open{display:block}
|
|
159
169
|
.mcp-setup-title{font-size:.85rem;font-weight:600;color:#e2e8f0;margin-bottom:.75rem}
|
|
@@ -216,6 +226,15 @@ function dashboardHtml(port, whitelist) {
|
|
|
216
226
|
<div>Services: <span id="s-services">${whitelist ? whitelist.join(", ") : "all"}</span></div>
|
|
217
227
|
<div>Failures: <span id="s-fails">—</span></div>
|
|
218
228
|
</div>
|
|
229
|
+
<div class="build-panel" id="build-panel">
|
|
230
|
+
<div class="build-dot idle" id="build-dot"></div>
|
|
231
|
+
<div class="build-label" id="build-label">
|
|
232
|
+
<strong>Deploy</strong> — idle
|
|
233
|
+
</div>
|
|
234
|
+
<span id="build-sha" style="font-family:'Courier New',monospace;font-size:.72rem;color:#60a5fa;background:#0a0f1a;border:1px solid #1e3a5f;border-radius:4px;padding:2px 8px;letter-spacing:.3px"></span>
|
|
235
|
+
<div class="build-meta" id="build-meta" style="width:100%;margin-top:4px"></div>
|
|
236
|
+
</div>
|
|
237
|
+
|
|
219
238
|
<div class="toolbar">
|
|
220
239
|
<button class="btn-refresh" onclick="loadServices()">↻ Refresh</button>
|
|
221
240
|
<button class="btn-add" onclick="toggleAddService()">+ Add Service</button>
|
|
@@ -413,6 +432,7 @@ function showMain(ping) {
|
|
|
413
432
|
ping.failures + "/" + (ping.failures + ping.failures_remaining);
|
|
414
433
|
}
|
|
415
434
|
pollTunnel();
|
|
435
|
+
updateBuildStatus();
|
|
416
436
|
}
|
|
417
437
|
|
|
418
438
|
// ── Unlock ──────────────────────────────────
|
|
@@ -1001,6 +1021,42 @@ function copyMcp(elId) {
|
|
|
1001
1021
|
}).catch(() => {});
|
|
1002
1022
|
}
|
|
1003
1023
|
|
|
1024
|
+
// ── Build Status ──────────────────────────────────
|
|
1025
|
+
async function updateBuildStatus() {
|
|
1026
|
+
try {
|
|
1027
|
+
const data = await fetch(BASE + "/builds").then(r => r.json());
|
|
1028
|
+
const dot = document.getElementById("build-dot");
|
|
1029
|
+
const label = document.getElementById("build-label");
|
|
1030
|
+
const meta = document.getElementById("build-meta");
|
|
1031
|
+
const sha = document.getElementById("build-sha");
|
|
1032
|
+
|
|
1033
|
+
// Update dot class
|
|
1034
|
+
dot.className = "build-dot " + (data.status || "idle");
|
|
1035
|
+
|
|
1036
|
+
// Update label
|
|
1037
|
+
const statusText = {
|
|
1038
|
+
idle: "idle", building: "building…", succeeded: "deployed", failed: "FAILED", timeout: "timeout"
|
|
1039
|
+
}[data.status] || data.status || "idle";
|
|
1040
|
+
label.innerHTML = "<strong>Deploy</strong> — " + statusText;
|
|
1041
|
+
|
|
1042
|
+
// Update SHA badge
|
|
1043
|
+
sha.textContent = data.commit ? data.commit.slice(0, 7) : "";
|
|
1044
|
+
|
|
1045
|
+
// Update meta
|
|
1046
|
+
const parts = [];
|
|
1047
|
+
if (data.message) parts.push(data.message.slice(0, 60));
|
|
1048
|
+
if (data.finished_at) {
|
|
1049
|
+
const ago = Math.floor((Date.now() - new Date(data.finished_at).getTime()) / 60000);
|
|
1050
|
+
parts.push(ago < 1 ? "just now" : ago < 60 ? ago + "m ago" : Math.floor(ago/60) + "h ago");
|
|
1051
|
+
} else if (data.started_at) {
|
|
1052
|
+
const ago = Math.floor((Date.now() - new Date(data.started_at).getTime()) / 60000);
|
|
1053
|
+
parts.push(ago < 1 ? "just started" : ago + "m");
|
|
1054
|
+
}
|
|
1055
|
+
meta.textContent = parts.join(" · ");
|
|
1056
|
+
} catch {}
|
|
1057
|
+
}
|
|
1058
|
+
setInterval(updateBuildStatus, 10000);
|
|
1059
|
+
|
|
1004
1060
|
boot();
|
|
1005
1061
|
</script>
|
|
1006
1062
|
</body>
|
|
@@ -1226,39 +1282,31 @@ function createServer(initPassword, whitelist, port, tunnelHostname = null) {
|
|
|
1226
1282
|
// ── Build status (populated via Supabase Realtime) ─────────
|
|
1227
1283
|
let buildStatus = { active: false, status: "idle", apps: [], updated_at: null };
|
|
1228
1284
|
|
|
1229
|
-
|
|
1285
|
+
// Poll Supabase REST API for build status (no extra deps needed)
|
|
1286
|
+
async function fetchBuildStatus() {
|
|
1230
1287
|
try {
|
|
1231
1288
|
const sbUrl = (api.getBaseUrl() || "").replace("/functions/v1/auth-vault", "");
|
|
1232
1289
|
const sbKey = api.getAnonKey();
|
|
1233
1290
|
if (!sbUrl || !sbKey) return;
|
|
1234
1291
|
|
|
1235
|
-
const
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
.
|
|
1245
|
-
(
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
.subscribe();
|
|
1254
|
-
|
|
1255
|
-
const logMsg = `[${new Date().toISOString()}] Build status: Realtime subscription active\n`;
|
|
1256
|
-
try { fs.appendFileSync(LOG_FILE, logMsg); } catch {}
|
|
1257
|
-
} catch (err) {
|
|
1258
|
-
const logMsg = `[${new Date().toISOString()}] Build status subscription failed: ${err.message}\n`;
|
|
1259
|
-
try { fs.appendFileSync(LOG_FILE, logMsg); } catch {}
|
|
1260
|
-
}
|
|
1261
|
-
})();
|
|
1292
|
+
const r = await fetch(
|
|
1293
|
+
`${sbUrl}/rest/v1/prt_storage?key=eq.build_status&select=value`,
|
|
1294
|
+
{ headers: { apikey: sbKey, Authorization: `Bearer ${sbKey}` }, signal: AbortSignal.timeout(5000) }
|
|
1295
|
+
);
|
|
1296
|
+
if (!r.ok) return;
|
|
1297
|
+
const rows = await r.json();
|
|
1298
|
+
if (rows.length > 0 && rows[0].value) {
|
|
1299
|
+
const prev = buildStatus.status;
|
|
1300
|
+
buildStatus = typeof rows[0].value === "string" ? JSON.parse(rows[0].value) : rows[0].value;
|
|
1301
|
+
if (buildStatus.status !== prev) {
|
|
1302
|
+
const logMsg = `[${new Date().toISOString()}] Build status: ${buildStatus.status} (${buildStatus.commit?.slice(0,8) || "?"})\n`;
|
|
1303
|
+
try { fs.appendFileSync(LOG_FILE, logMsg); } catch {}
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
} catch {}
|
|
1307
|
+
}
|
|
1308
|
+
fetchBuildStatus();
|
|
1309
|
+
setInterval(fetchBuildStatus, 15000);
|
|
1262
1310
|
|
|
1263
1311
|
const server = http.createServer(async (req, res) => {
|
|
1264
1312
|
const remote = req.socket.remoteAddress;
|