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
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
(() => {
|
||||
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 });
|
||||
})();
|
||||
Reference in New Issue
Block a user