diff --git a/src/lib.rs b/src/lib.rs index 3bb3232..9f26d50 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ use std::rc::Rc; -use axum::{extract::Path, routing::get, Json, Router}; +use axum::{extract::Path, http::{self, Response}, response::{AppendHeaders, Html, IntoResponse}, routing::get, Json, Router}; use datamodel::Reference; mod datamodel; @@ -63,6 +63,13 @@ async fn dummy_object(Path(addr): Path) -> String { format!("I am object {}", addr) } +async fn get_client_js() -> impl IntoResponse { + ( + [(http::header::CONTENT_TYPE, "application/javascript")], + include_str!("../static/client.js"), + ) +} + pub fn endpoints() -> Router { Router::new().nest( "/api/v1", @@ -78,6 +85,8 @@ pub fn endpoints() -> Router { .route("/{addr}", get(dummy_object)) ), ) + .route("/lib/client.js", get(get_client_js)) + .route("/ui/", get(|| async { Html(include_str!("../static/index.html")).into_response() })) } // TODO(jwall): Javascript test script diff --git a/static/client.js b/static/client.js new file mode 100644 index 0000000..a6f4a6f --- /dev/null +++ b/static/client.js @@ -0,0 +1,81 @@ +export { bootstrap }; +// 1. Record a start time. +// 2. Load the bootstrap document. +// 3. Load all the content_addresses from the bootstrap. +// 4. Record the end time. + +async function load_bootstrap() { + let response = await fetch("/api/v1/ref/all/username"); + if (!response.ok) { + throw new Error("Network response was not ok: " + response.statusText); + } + return await response.json(); +} + +/** + * @param {String} dbName + * @param {Array} storeNames + * @returns {Promise} + */ +async function openDatabase(dbName, storeNames) { + return await new Promise((resolve, reject) => { + const request = indexedDB.open(dbName, 1); + + request.onupgradeneeded = (event) => { + const db = event.target.result; + for (var storeName of storeNames) { + // Create the object store if it doesn't exist + if (!db.objectStoreNames.contains(storeName)) { + db.createObjectStore(storeName); + } + } + }; + + request.onsuccess = (event) => { + const db = event.target.result; + resolve(db); + }; + + request.onerror = (event) => { + reject(event.target.error); + }; + }); +} + +/** + * @param {IDBObjectStore} store + * @param {Object} reference +*/ +function load_reference_paths(store, reference) { + let root_path = reference.path; + return new Promise(async (resolve, reject) => { + if (reference.dependents) { + for (var dep of reference.dependents) { + await load_reference_paths(store, dep); + } + } + + const request = store.put(JSON.stringify(reference), root_path); + request.onerror = (evt) => { + reject(evt.target.error); + console.log("Failed to store object", evt); + }; + request.onsuccess = (evt) => { + resolve(evt.target.result); + }; + }); +} + +async function bootstrap() { + const refStoreName = "references" + const objectStoreName = "objects" + const databaseName = "MerkleStore"; + const start = new Date().getTime(); + let root = await load_bootstrap(); + let db = await openDatabase(databaseName, [refStoreName, objectStoreName]); + const transaction = db.transaction([refStoreName], "readwrite"); + const store = transaction.objectStore(refStoreName); + load_reference_paths(store, root); + var end = new Date().getTime(); + return end - start; +} diff --git a/static/index.html b/static/index.html new file mode 100644 index 0000000..321d1a4 --- /dev/null +++ b/static/index.html @@ -0,0 +1,26 @@ + + + + + + Bootstrap Time Display + + +

Bootstrap Time

+
Loading...
+ + + + +