hosted-kernel/src/kernel.ts

167 lines
3.9 KiB
TypeScript

import {
downloadSmallObject,
maybeInitDefaultPortals,
savePortals,
savePortalSessions,
setActivePortalMasterKey,
} from "@lumeweb/libweb";
import { log, logErr, sendAuthUpdate } from "./util.js";
import {
defaultKernelLink,
setKernelLoaded,
setLoginComplete,
} from "./vars.js";
import { getStoredUserKey } from "./storage.js";
import { readableStreamToBlob } from "binconv";
import { addContextToErr } from "@lumeweb/libkernel";
let kernelLoadAttempt = false;
function testIndexedDBSupport() {
return new Promise((resolve, reject) => {
// Check for IndexedDB support
if (!("indexedDB" in window)) {
reject(new Error("IndexedDB is not supported by this browser."));
} else {
// Attempt to open an IndexedDB database
const request = indexedDB.open("test_db", 1);
request.onerror = function (event) {
// Error occurred, reject the promise
reject(
// @ts-ignore
new Error("IndexedDB test error: " + event?.target?.error?.code),
);
};
request.onsuccess = function (event) {
// Success, resolve the promise
// @ts-ignore
event?.target?.result.close(); // Close the DB when done
resolve(true);
};
request.onupgradeneeded = function (event: IDBVersionChangeEvent) {
// Database needs to be created or upgraded
// @ts-ignore
const db = event?.target?.result;
if (!db.objectStoreNames.contains("test_store")) {
// Create an object store
db.createObjectStore("test_store", { keyPath: "id" });
}
};
}
});
}
export async function boot() {
let userKey;
try {
await testIndexedDBSupport();
} catch {
setKernelLoaded("indexeddb_error");
sendAuthUpdate();
logErr("indexed db is not supported or is blocked");
return;
}
try {
userKey = getStoredUserKey();
} catch (e) {
logErr(addContextToErr(e, "user key could not be fetched"));
sendAuthUpdate();
return;
}
if (!userKey) {
sendAuthUpdate();
return;
}
log("user is already logged in, attempting to load kernel");
setActivePortalMasterKey(userKey);
setLoginComplete(true);
sendAuthUpdate();
loadKernel();
}
export async function loadKernel() {
if (kernelLoadAttempt) {
return;
}
kernelLoadAttempt = true;
try {
maybeInitDefaultPortals();
} catch (e) {
let err = addContextToErr(e, "unable to init portals");
setKernelLoaded(err);
logErr(err);
sendAuthUpdate();
return;
}
let kernelCode;
try {
kernelCode = await downloadDefaultKernel();
} catch (e) {
let extErr = addContextToErr(e, "unable to download kernel");
setKernelLoaded(extErr);
logErr(extErr);
sendAuthUpdate();
return;
}
savePortals();
savePortalSessions();
try {
await new Promise(async (resolve, reject) => {
const url = URL.createObjectURL(await readableStreamToBlob(kernelCode));
const el = document.createElement("script");
el.src = url;
el.onload = () => {
URL.revokeObjectURL(url);
resolve(null);
};
el.onerror = (
event: Event | string,
source?: string,
lineno?: number,
colno?: number,
error?: Error,
) => {
URL.revokeObjectURL(url);
reject(error);
};
document.head.appendChild(el);
});
setKernelLoaded("success");
sendAuthUpdate();
log("kernel successfully loaded");
return;
} catch (err: any) {
let extErr = addContextToErr(err, "unable to eval kernel");
setKernelLoaded(extErr);
logErr(extErr);
logErr(err.toString());
console.error(extErr);
console.error(err);
sendAuthUpdate();
return;
}
}
async function downloadKernel(kernelCid: string): Promise<ReadableStream> {
return await downloadSmallObject(kernelCid);
}
function downloadDefaultKernel(): Promise<ReadableStream> {
return downloadKernel(defaultKernelLink);
}