Add device inventory refresh endpoint and auto-refresh UI
Build and Deploy Gateway / build-and-push (push) Successful in 14s
Build and Deploy Gateway / deploy (push) Successful in 7s

This commit is contained in:
2026-08-07 14:00:26 +03:00
parent 36c8438b7f
commit 3157e9e8f7
8 changed files with 215 additions and 17 deletions
+5
View File
@@ -617,6 +617,11 @@ async function handleApi(req, res) {
return sendJson(res, 200, deviceInventory.snapshot());
}
if (requestUrl.pathname === '/api/devices/refresh') {
if (!deviceInventory || req.method !== 'POST') throw new HarborError('ENDPOINT_NOT_FOUND');
return sendJson(res, 200, await deviceInventory.refresh());
}
const deviceMatch = requestUrl.pathname.match(/^\/api\/devices\/(dev_[a-f0-9]{16})$/);
if (deviceMatch && req.method === 'PUT') {
if (!deviceInventory) throw new HarborError('ENDPOINT_NOT_FOUND');
+12 -1
View File
@@ -66,6 +66,8 @@ function deviceStatus(lastSeenAt, now) {
}
export function createDeviceInventoryService({ store, observe, vendor = () => null, now = () => new Date() }) {
let refreshPromise = null;
function snapshot() {
const state = migrate(store.read());
const current = now();
@@ -89,7 +91,7 @@ export function createDeviceInventoryService({ store, observe, vendor = () => nu
};
}
async function refresh() {
async function performRefresh() {
let result;
try {
result = await observe();
@@ -138,6 +140,15 @@ export function createDeviceInventoryService({ store, observe, vendor = () => nu
return snapshot();
}
function refresh() {
if (!refreshPromise) {
refreshPromise = performRefresh().finally(() => {
refreshPromise = null;
});
}
return refreshPromise;
}
function update(id, patch, expectedRevision) {
if (!patch || typeof patch !== 'object' || Array.isArray(patch)) {
throw new HarborError('REQUEST_INVALID');