Files
hemx/hemx-host/runtime/browser-host.js
T
slhx agent 2cc6c85e37 feat(host): add typed host capability boundary
Introduce hemx-host with typed capability manifests, calls, events, host-check failures, reusable browser/PWA and native-shell profiles, and a tiny optional browser adapter for haptics/share that returns host events without DOM mutation.

req: host/001

req: host/002

req: host/003

req: host/004

req: host/005
2026-06-11 19:35:20 +02:00

50 lines
1.9 KiB
JavaScript

(() => {
function variant(value) {
if (!value || typeof value !== "object") return null;
const keys = Object.keys(value);
return keys.length === 1 ? { kind: keys[0], data: value[keys[0]] || {} } : null;
}
function failure(id, message) {
return { Failed: { id: id || null, message: String(message) } };
}
async function haptic(data) {
if (!navigator.vibrate) return failure(data.id, "haptics unsupported");
const pattern = data.pattern === "Warning" || data.pattern === "Error" ? [30, 40, 30] : 20;
navigator.vibrate(pattern);
return { Acknowledged: { id: data.id } };
}
async function share(data) {
if (!navigator.share) return failure(data.id, "share unsupported");
const payload = data.payload || {};
const request = {};
if (payload.title) request.title = payload.title;
if (payload.text) request.text = payload.text;
if (payload.url) request.url = payload.url;
try {
await navigator.share(request);
return { ShareCompleted: { id: data.id, completed: true } };
} catch (error) {
if (error && error.name === "AbortError") return { ShareCompleted: { id: data.id, completed: false } };
return failure(data.id, error && error.message ? error.message : error);
}
}
function supports(capability, shape) {
return (capability === "haptics" && shape === "Fire" && !!navigator.vibrate)
|| (capability === "share" && shape === "Request" && !!navigator.share);
}
async function perform(call) {
const request = variant(call);
if (!request) return failure(null, "invalid host call");
if (request.kind === "Haptic") return haptic(request.data);
if (request.kind === "Share") return share(request.data);
return failure(request.data.id || null, `unsupported host call ${request.kind}`);
}
window.hemxBrowserHost = Object.freeze({ name: "browser-pwa", supports, perform });
})();