From 7aaf2ba9ac8ef1312a3cc4c9990c7dfe173a74d1 Mon Sep 17 00:00:00 2001
From: Juan Di Toro
dAMQaiH zm^r3v#$Q#2T=X>bsY#D%s!bhs^M9PMAcHbCc0FMHV{u-dwlL;a1eJ63v5U*?Q_8JO zT#50!RD619#j_Uf))0ooADz~*9&lN!bBDRUgE>Vud-i5ck%vT=r^yD*^?Mp@Q^v+V zG#-?gKlr}Eeqifb{|So?HM&g91P8|av8hQoCmQXkd?7wIJw b z_^v8bbg` SAn{I*4bH$u(RZ6*x UhuA~hc=8czK8SHEKTzSxgbwi~9(OqJB&gwb^l4+m`k*Q;_?>Y-APi1{k zAHQ)P)G)f|AyjSgcCFps)Fh6Bca*Xznq36!pV6Az&m{O8$wGFD? zY&O*3*J0;_EqM#jh6^gMQKpXV?#1?>$ml1xvh8nSN>-?H=V;nJIwB07YX$e6vLxH( zqYwQ>qxwR(i4f)DLd)-$P>T-no_c!LsN@)8`e;W@)-Hj0>nJ-}Kla4-ZdPJzI&Mce zv)V_j;(3ERN3_@I$N<^|4Lf`B;8n+bX@bHbcZTopEmDI*Jfl)-pFDvo6svPRoo@(x z);_{lY<;);XzT`dBFpRmGrr}z5u1=p C^ S-{ce6iXQlLGcItwJ^mZx{m$&DA_oEZ)B{_bYPq-HA zcH8WGoBG(aBU_j)vEy+_71T34@4dmSg!|M8Vf92Zj6WH7Q7t#OHQqWgFE3ARt+%!T z?oLovLVlnf?2c7pTc)~cc^($_8nyKwsN`RA-23ed3sdj(ys%pjjM+9JrctL;dy8a( z@en&CQmnV(()bu|Y%G1-4a(6x{aLytn$T-;(&{QIJB9vMox11U-1HpD@d(QkaJdEb zG{)+6Dos_L+O3NpWo^=gR?evp|CqEG?L&Ut#D*KLaRFOgOEK(Kq1@!EGcTfo+%A&I z=dLbB+d$u{sh?u)xP{PF8L%;YPPW53+@{>5W=Jt#wQpN;0_HYdw1{ksf_XhO4#2F= zyPx6Lx2<92L-;L5PD`zn6zwIH`Jk( $?Qw({erA$^bC;q33hv!d!>%wRhj# zal^hk+WGNg;rJtb-EB(?czvOM=H7dl=vblBwAv>}%1@{}mnpUznfq1cE^sgsL0*4I zJ##!*B?=vI_OEVis5o+_IwMIRrpQyT_Sq~ZU%oY7c5JMIADzpD!Upz9h@iWg_>>~j zOLS;wp^i$-E?4<_cp?RiS%Rd?i;f*mOz=~(&3lo<=@(nR!_Rqiprh@weZlL!t#NCc zO!QTcInq|%#>OVgobj{~ixEUec`E25zJ~*DofsQdzIa@5^nOXj2T;8O`l--(QyU ^$t?TGY^7#&FQ+2SS3B#qK*k3`ye?8jUYSajE5iBbJls75CCc(m3dk{t?- zopcER9{Z?TC)mk~gpi^kbbu>b-+a{m#8-y2^p$ka4n60w;Sc2}HMf<8JUvh CL0B&Btk)T`ctE$*qNW8L$`7!r^9T+>=<=2qaq-;ll2{`{Rg zc5a0ZUI$oG&j-qVOuKa=*v4aY#IsoM+1|c4Z)<}lEDvy;5huB@1RJPquU2U*U-;gu z=En2m+qjBzR#DEJDO`WU)hdd{Vj%^0V*KoyZ|5lzV87&g_j~NCjwv0uQVqXOb*QrQ zy|Qn`hxx(58c 70$E;L(X0uZZ72M1!6oeg)(cdKO ze0gDaTz+ohR-#d)NbAH4x{I(21yjwvBQfmpLu$)|m{XolbgF!pmsqJ#D}(ylp6uC> z{bqtcI#hT#HW=wl7>p!38sKsJ`r8}lt-q%Keqy%u(xk=yiIJiUw6|5IvkS+#?JTBl z8H5(Q?l#wzazujH!8o>1xtn8#_w+397* _cy8!pQGP%K(Ga3pAjsaTbbXJlQF_+m+-UpUUent@xM zg%jqLUExj~o^vQ3Gl*>wh=_gOr2*|U64_iXb+-111a H}$TjeajM+I20xw(((>fej-@CIz4S1pi$(#}P7`4({6QS2CaQS4NPENDp>sAqD z$bH4KGzXGffkJ7R>V>)>tC)uax{UsN*dbeNC*v}#8Y#OWYwL4t$ePR?VTyIs!wea+ z5Urmc)X|^`MG~*dS6pGSbU+gPJoq*^a=_>$n4|P^w$sMBBy@f*Z^Jg6?n5?oId6f{ z$LW4M|4m502z0t7g<#Bx%X;9<=)smFolV&(V^(7Cv2-sxbxopQ!)*#ZRhTBpx1)Fc zNm1T%bONzv6@#|dz(w02AH8OXe>kQ#1FMCzO}2J_mST)+ExmBr9cva-@?;wnmWMOk z{3_~EX_xadgJGv&H@zK_8{(x84`}+c?oSBX*Ge3VdfTt&F}yCpFP?CpW+BE^cWY0^ zb&uBN!Ja3UzYHK-CTyA5=L zEMW{l3Usky#ly=7px648W31UNV@K)&Ub&zP1c7%)`{);I4b0Q<)B}3;NMG2JH=X$U zfIW4)4n9ZM`-yRj67I)YSLDK)qfUJ_ij}a#aZN~9EXrh8eZY2&=uY%2N0UFF7<~%M zsB8=erOWZ>Ct_#^tHZ|*q`H;A)5;ycw*I cmVxi8_0Xk}aJA^ath+E;xg!x+As(M#0=)3!NJR6H&9+zd#iP(m0PIW8$ z1Y^VX`>jm`W!=WpF*{ioM?C9`yOR>@0q=u7o>BP-eSHqCgMDj!2anwH?s%i2p+Q7D zzszIf5XJpE)IG4;d_(La-xenmF(tgAxK`Y4sQ}BSJEPs6N_U2vI{8=0C_F?@7<(G; zo$~G=8p+076G;`}>{MQ>t>7cm=zGtfbdDXm6||jUU|?X?CaE?(<6bKDYKeHlz}DA8 zXT={X=yp_R;HfJ9h%?eWvQ!dRgz&Su*JfNt!Wu>|XfU &68iRikRrHRW|ZxzRR^`eIGt zIeiDgVS>IeExKVRWW8-= A= yA`}`)ZkWBrZD`hpWIxBGkh&f#ijr449~m`j6{4jiJ*C!oVA8ZC?$1RM#K(_b zL9TW)kN*Y4%^-qPpMP7d4)o?Nk#>aoYHT(*g)qmRUb?**F@pnNiy6Fv9rEiUqD(^O zzyS?nBrX63BTRYduaG(0VVG2yJRe%o&rVrLjbxTaAFTd8s;<<@Qs>u(<193R8>}2_ zuwp{7;H2a*X7_jryzriZXMg?bTuegABb^87@SsKkr2)0Gyiax8KQWstw^v #ix45EVrcEhr>!NMhprl $InQMzjSFH54x5k9qHc`@9uKQzvL4ihcq{^B zPrVR=o_ic%Y>6&rMN)hTZsI7I<3&`#(nl+3y3ys9A~ &^=4?PL&nd8)`OfG#n zwAMN$1&>K++c{^|7< 4P=2y(B{jJsQ0a#U;HTo4ZmWZYvI{+s;Td{Yzem%0*k#)vjpB zia;J&>}ICate44SFYY3vEelqStQWFihx%^vQ@Do(sOy7yR2@WNv7Y9I^yL=nZr3mb zXKV5t@=?-Sk|b{XMhA7ZGB@2hqsx}4xwCW!in#C zI@}sc Zlr3-NFJ@NFaJlhyfcw{k^vvtGl`N9xSo**rDW4S}i zM9{fMPWo%4wYDG~BZ18BD+}h|GQKc-g^{++3MY>}W_uq7jGHx{mwE9fZiPCoxN$+7 zrODGGJrOkcPQUB(FD5aoS4g~7#6NR^ma7-!>mHuJfY5kTe6PpNNKC9GGRiu^L31uG z$7v`*JknQHsYB!Tm_W{a32TM099djW%5e+j0Ve_ct}IM>XLF1Ap+YvcrLV=|CKo6S zb+ 9Nl3_YdKP6%Cxy@6TxZ>;4&nTneadr z_ES90ydCev)LV!dN=#(*f}|ZORFdvkYBni^aLbUk>BajeWIOcmHP#8S)*2U~QKI%S zyrLmtPqb&TphJ;>yAxri#;{uyk`JJqODDw%(Z=2 `1uc}br^V%>j!gS)D*q*f_-qf8&D;W1dJgQMlaH5er zN2U<%Smb7==vE}dDI8K7cKz!vs^73o9f>2sgiTzWcwY|BMYHH5%Vn7#kiw&eItCqa zIkR2~Q}>X=Ar8W|^Ms41Fm8o6IB2_j60eOeBB1Br!boW7JnoeX6Gs)?7rW0^5psc- zjS16yb>dFn>KPOF;imD}e!enuIniFzv}n$m2#gCCv4jM#ArwlzZ$7@9&XkFxZ4n!V zj3dyiwW4Ki2QG{@i>yuZXQizw_OkZI^-3otXC{!(lUpJF33gI60ak;Uqitp74|B6I zgg{b=Iz}WkhCGj1M =hu4#Aw173YxIVbISaoc z-nLZC*6Tgivd5V`K%GxhBsp@SUU60-rfc$=wb>zdJzXS&-5(NRRodFk;Kxk!S( O(a0e7oY=E( zAyS;Ow?6Q&XA+cnkCb{28_1N8H#?J!*$MmIwLq^*T_9-z^&UE@A(z9oGYtFy6EZef LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/public/next.svg b/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg new file mode 100644 index 0000000..d2f8422 --- /dev/null +++ b/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/clients.ts b/src/clients.ts deleted file mode 100644 index aff54f5..0000000 --- a/src/clients.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { createClient as createDnsClient } from "@lumeweb/kernel-dns-client"; -import { createClient as createIpfsClient } from "@lumeweb/kernel-ipfs-client"; -import { createClient as createSwarmClient } from "@lumeweb/kernel-swarm-client"; -import { createClient as createPeerDiscoveryClient } from "@lumeweb/kernel-peer-discovery-client"; -import { createClient as createNetworkRegistryClient } from "@lumeweb/kernel-network-registry-client"; -import { createClient as createHandshakeClient } from "@lumeweb/kernel-handshake-client"; -import { createClient as createEthClient } from "@lumeweb/kernel-eth-client"; - -const dnsClient = createDnsClient(); -const ipfsClient = createIpfsClient(); -const swarmClient = createSwarmClient(); -const peerDiscoveryClient = createPeerDiscoveryClient(); -const networkRegistryClient = createNetworkRegistryClient(); -const handshakeClient = createHandshakeClient(); -const ethClient = createEthClient(); - -export { - dnsClient, - ipfsClient, - swarmClient, - peerDiscoveryClient, - networkRegistryClient, - handshakeClient, - ethClient, -}; diff --git a/src/contentProcessor.ts b/src/contentProcessor.ts deleted file mode 100644 index d3f1f39..0000000 --- a/src/contentProcessor.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ContentFilter } from "./types.js"; - -export class ContentProcessor { - private filters: ContentFilter[] = []; - - registerFilter(filter: ContentFilter) { - this.filters.push(filter); - } - - async process(response: Response, mimeType: string): Promise { - let processedResponse = response; - - for (const filter of this.filters) { - processedResponse = await filter.process(processedResponse, mimeType); - } - - return processedResponse; - } -} diff --git a/src/filters/urlRewrite.ts b/src/filters/urlRewrite.ts deleted file mode 100644 index 6446322..0000000 --- a/src/filters/urlRewrite.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { ContentFilter } from "src/types.js"; -import { getTld } from "@lumeweb/libresolver"; -import tldEnum from "@lumeweb/tld-enum"; -import * as cheerio from "cheerio"; - -export default class URLRewriteFilter implements ContentFilter { - async process(response: Response, mimeType: string): Promise { - if (mimeType !== "text/html") { - return response; - } - - let html = await response.text(); - - const $ = cheerio.load(html); - ["a", "link", "script", "img"].forEach((tag) => { - $.root() - .find(tag) - .each((index, element) => { - let attrName = ["a", "link"].includes(tag) ? "href" : "src"; - let urlValue = $(element).attr(attrName); - - if (urlValue) { - if (!isICANN(urlValue)) { - if (urlValue.startsWith("/")) { - $(element).attr(attrName, `/browse${urlValue}`); - } else if (urlValue.startsWith("http")) { - $(element).attr(attrName, `/browse/${urlValue}`); - } - } - } - }); - }); - - return new Response($.html(), { - headers: response.headers, - }); - } -} - -function isICANN(url: string) { - try { - const parsedUrl = new URL(url); - const domain = parsedUrl.hostname; - return tldEnum.list.includes(getTld(domain)); - } catch (e) { - return false; - } -} diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 4525d6b..0000000 --- a/src/index.ts +++ /dev/null @@ -1,104 +0,0 @@ -import * as kernel from "@lumeweb/libkernel/kernel"; -import { - dnsClient, - ethClient, - handshakeClient, - ipfsClient, - networkRegistryClient, - peerDiscoveryClient, - swarmClient, -} from "./clients.js"; -import { ed25519 } from "@lumeweb/libkernel"; - -document.addEventListener("DOMContentLoaded", () => - document.getElementById("go-button")?.addEventListener("click", () => { - let input = ( - document.getElementById("address-bar") as HTMLInputElement - ).value.trim(); - - // If the input doesn't contain a protocol, assume it's http - if (!input.match(/^https?:\/\//)) { - input = `http://${input}`; - } - - try { - // Try to parse it as a URL - const url = new URL(input); - - // Update the iframe's src attribute - const iframe = document.getElementById( - "web-content", - ) as HTMLIFrameElement; - iframe.src = `/browse/${url.hostname}${url.pathname}${url.search}${url.hash}`; - } catch (e) { - // Handle invalid URLs here, if needed - console.error("Invalid URL:", e); - } - }), -); - -let BOOT_FUNCTIONS: (() => Promise )[] = []; - -async function boot() { - await kernel.init(); - await kernel.login(ed25519.utils.randomPrivateKey()); - - const reg = await navigator.serviceWorker.register("/sw.js"); - await reg.update(); - - await kernel.serviceWorkerReady(); - - BOOT_FUNCTIONS.push( - async () => - await swarmClient.addRelay( - "2d7ae1517caf4aae4de73c6d6f400765d2dd00b69d65277a29151437ef1c7d1d", - ), - ); - - // IRC - BOOT_FUNCTIONS.push( - async () => - await peerDiscoveryClient.register( - "zdiN5eJ3RfHpZHTYorGxBt1GCsrGJYV9GprwVWkj8snGsjWSrptFm8BtQX", - ), - ); - BOOT_FUNCTIONS.push( - async () => await networkRegistryClient.registerType("content"), - ); - BOOT_FUNCTIONS.push( - async () => await networkRegistryClient.registerType("blockchain"), - ); - BOOT_FUNCTIONS.push(async () => await handshakeClient.register()); - BOOT_FUNCTIONS.push(async () => await ethClient.register()); - BOOT_FUNCTIONS.push(async () => await ipfsClient.register()); - - const resolvers = [ - "zdiJdDdBJWAdYFTcRa9So5TQQ9f1pYMiMy4dqYcKp9imomQtR11LJUyJyV", // CID - "zdiKvnZYNjDqXaM8uF3pGEs7Tt6jqGc7t7M4eqbvJwpkTnrZymncfUW9Cj", // ENS - "zrjEH3iojPLr7986o7iCn9THBmJmHiuDWmS1G6oT8DnfuFM", // HNS - ]; - - for (const resolver of resolvers) { - BOOT_FUNCTIONS.push(async () => dnsClient.registerResolver(resolver)); - } - - await bootup(); - - await Promise.all([ - ethClient.ready(), - handshakeClient.ready(), - ipfsClient.ready(), - ]); - - document.getElementById("booting")!.style.display = "none"; - (document.getElementById("address-bar") as HTMLInputElement).disabled = false; - (document.getElementById("go-button") as HTMLButtonElement).disabled = false; -} - -async function bootup() { - for (const entry of Object.entries(BOOT_FUNCTIONS)) { - await entry[1](); - } -} - -document.addEventListener("DOMContentLoaded", boot); diff --git a/src/messages.ts b/src/messages.ts deleted file mode 100644 index 642fb27..0000000 --- a/src/messages.ts +++ /dev/null @@ -1,123 +0,0 @@ -import exchangeCommunicationKeys from "./messages/exchangeCommunicationKeys.js"; -import { - deleteQuery, - getAuthStatus, - getAuthStatusKnown, - getLoggedInDefer, - getQueries, - getQuery, - resetLoggedInDefer, - setAuthStatus, - setAuthStatusKnown, - getAuthStatusDefer, -} from "./vars.js"; -const kernelMessageHandlers = { - exchangeCommunicationKeys, -}; - -export async function handleIncomingMessage(event: MessageEvent) { - if (event.source === null) { - return; - } - if (event.source === window) { - return; - } - - const data = event.data?.data; - if (event.data.method === "log") { - if (data?.isErr === false) { - console.log(data.message); - return; - } - console.error(data.message); - } - - if (event.data.method === "kernelAuthStatus") { - setAuthStatus(data); - if (!getAuthStatusKnown()) { - getAuthStatusDefer().resolve(); - setAuthStatusKnown(true); - console.log("bootloader is now initialized"); - if (!getAuthStatus().loginComplete) { - console.log("user is not logged in: waiting until login is confirmed"); - } else { - getLoggedInDefer().resolve(); - } - if (getAuthStatus().logoutComplete) { - resetLoggedInDefer(); - setAuthStatusKnown(false); - } - } - return; - } - - if (!("nonce" in event.data)) { - (event.source as WindowProxy).postMessage( - { - nonce: "N/A", - method: "response", - err: "message sent to kernel with no nonce", - }, - event.origin, - ); - return; - } - - if (!("method" in event.data)) { - (event.source as WindowProxy).postMessage( - { - nonce: event.data.nonce, - method: "response", - err: "message sent to kernel with no method", - }, - event.origin, - ); - return; - } - - if (event.data.method in kernelMessageHandlers) { - let response; - - try { - response = await kernelMessageHandlers[event.data.method]( - event.data.data, - ); - } catch (e: any) { - response = { err: (e as Error).message }; - } - - (event.source as WindowProxy).postMessage( - { - nonce: event.data.nonce, - data: response, - }, - event.origin, - ); - return; - } - if (!(event.data.nonce in getQueries())) { - return; - } - - let receiveResult = getQuery(event.data.nonce); - if (event.data.method === "response") { - deleteQuery(event.data.nonce); - } - - receiveResult?.(event.data); - - if (["moduleCall", "response"].includes(event.data.method)) { - return; - } - - (event.source as WindowProxy).postMessage( - { - nonce: event.data.nonce, - method: "response", - err: - "unrecognized method (user may need to log in): " + event.data.method, - }, - event.origin, - ); - return; -} diff --git a/src/messages/exchangeCommunicationKeys.ts b/src/messages/exchangeCommunicationKeys.ts deleted file mode 100644 index ca1a7b2..0000000 --- a/src/messages/exchangeCommunicationKeys.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { bytesToHex, hexToBytes } from "@lumeweb/libweb"; -import { - getCommunicationPubKey, - setFrontendCommunicationPubkey, -} from "../vars.js"; - -export default function (data: any) { - setFrontendCommunicationPubkey(hexToBytes(data)); - - return bytesToHex(getCommunicationPubKey()); -} diff --git a/src/mimes.ts b/src/mimes.ts deleted file mode 100644 index a49866d..0000000 --- a/src/mimes.ts +++ /dev/null @@ -1,10 +0,0 @@ -const extToMimes = new Map( - Object.entries({ - html: "text/html", - xhtml: "application/xhtml+xml", - xml: "application/xml", - }) -); -Object.freeze(extToMimes); - -export default extToMimes; diff --git a/src/providerManager.ts b/src/providerManager.ts deleted file mode 100644 index e6f8af7..0000000 --- a/src/providerManager.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { ContentProcessor } from "./contentProcessor.js"; -import { ContentProvider } from "./types.js"; -import { DNSRecord, DNSResult } from "@lumeweb/libresolver"; -import { URL } from "url"; - -export class ProviderManager { - private providers: ContentProvider[] = []; - - private _processor = new ContentProcessor(); - - get processor(): ContentProcessor { - return this._processor; - } - - register(provider: ContentProvider) { - this.providers.push(provider); - } - - async fetch(dnsResult: DNSResult, path: string): Promise { - for (const record of dnsResult.records) { - for (const provider of this.providers) { - if (provider.supports(record.value)) { - const content = await provider.fetchContent(record.value, path); - - if (content.headers.get("Content-Type")) { - return this._processor.process( - content, - content.headers.get("Content-Type")!, - ); - } - - return content; - } - } - } - - throw new Error("No suitable provider found."); - } -} diff --git a/src/providers/ipfs.ts b/src/providers/ipfs.ts deleted file mode 100644 index 325a54b..0000000 --- a/src/providers/ipfs.ts +++ /dev/null @@ -1,141 +0,0 @@ -import { ContentProvider } from "src/types.js"; -import { ipfsPath, ipnsPath, path as checkPath } from "is-ipfs"; -import { createClient } from "@lumeweb/kernel-ipfs-client"; -import { CID } from "multiformats/cid"; -import type { UnixFSStats } from "@helia/unixfs"; -import * as nodePath from "path"; -import { fileTypeFromBuffer } from "file-type"; -import extToMimes from "../mimes.js"; -import { URL } from "url"; - -export default class IPFSProvider implements ContentProvider { - private _client = createClient(); - async fetchContent( - uri: string, - path: string, - query?: string, - ): Promise { - let cid = translatePath(uri); - let stat: UnixFSStats | null = null; - let urlPath = path; - const parsedPath = nodePath.parse(urlPath); - let err; - try { - if (ipnsPath(cid)) { - const cidHash = cid.replace("/ipns/", ""); - cid = await this._client.ipns(cidHash); - cid = `/ipfs/${cid}`; - } - - if (ipfsPath(cid)) { - cid = CID.parse(cid.replace("/ipfs/", "")).toV1().toString(); - stat = await this._client.stat(cid); - } - } catch (e) { - err = (e as Error).message; - } - - if (!err && stat?.type === "directory") { - if (!parsedPath.base.length || !parsedPath.ext.length) { - let found = false; - for (const indexFile of ["index.html", "index.htm"]) { - try { - const subPath = nodePath.join(urlPath, indexFile); - await this._client.stat(cid, { - path: subPath, - }); - urlPath = subPath; - found = true; - break; - } catch {} - } - - if (!found) { - err = "404"; - } - } else { - try { - await this._client.stat(cid, { - path: urlPath, - }); - } catch { - err = "404"; - } - } - - if (err) { - throw new Error(err); - } - } - - let bufferRead = 0; - const fileTypeBufferLength = 4100; - const mimeBuffer: Uint8Array[] = []; - let reader = await this._client.cat(cid, { path: urlPath }); - - for await (const chunk of reader.iterable()) { - if (bufferRead < fileTypeBufferLength) { - if (chunk.length >= fileTypeBufferLength) { - mimeBuffer.push(chunk.slice(0, fileTypeBufferLength)); - bufferRead += fileTypeBufferLength; - } else { - mimeBuffer.push(chunk); - bufferRead += chunk.length; - } - - if (bufferRead >= fileTypeBufferLength) { - reader.abort(); - break; - } - } else { - reader.abort(); - break; - } - } - - let mime; - - if (bufferRead >= fileTypeBufferLength) { - const totalLength = mimeBuffer.reduce((acc, val) => acc + val.length, 0); - const concatenated = new Uint8Array(totalLength); - let offset = 0; - for (const chunk of mimeBuffer) { - concatenated.set(chunk, offset); - offset += chunk.length; - } - mime = await fileTypeFromBuffer(concatenated); - - if (!mime) { - const ext = nodePath.parse(urlPath).ext.replace(".", ""); - if (extToMimes.has(ext)) { - mime = extToMimes.get(ext); - } - } - } - - reader = await this._client.cat(cid, { path: urlPath }); - - const stream = new ReadableStream({ - async start(controller) { - for await (const chunk of reader.iterable()) { - controller.enqueue(chunk); - } - controller.close(); - }, - }); - - return new Response(stream, { - headers: { - "Content-Type": mime ?? undefined, - }, - }); - } - - supports(uri: string): boolean { - return checkPath(translatePath(uri)); - } -} - -function translatePath(uri: string) { - return uri.replace(/:\/\//, "/").replace(/^/, "/"); -} diff --git a/src/sw.ts b/src/sw.ts deleted file mode 100644 index 55c841f..0000000 --- a/src/sw.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { createClient as createDnsClient } from "@lumeweb/kernel-dns-client"; -import { ProviderManager } from "./providerManager.js"; -import IPFSProvider from "./providers/ipfs.js"; -import URLRewriteFilter from "./filters/urlRewrite.js"; - -const dnsClient = createDnsClient(); - -const providerManager = new ProviderManager(); -providerManager.register(new IPFSProvider()); -providerManager.processor.registerFilter(new URLRewriteFilter()); - -globalThis.postMessage = async (...args) => { - // @ts-ignore - let ret = await clients.matchAll({ includeUncontrolled: true }); - ret.forEach((item) => item.postMessage(...args)); - - if (!ret.length) { - const cb = (event) => { - // @ts-ignore - postMessage(...args); - self.removeEventListener("activate", cb); - }; - self.addEventListener("activate", cb); - } -}; - -self.addEventListener("activate", (event) => { - // @ts-ignore - event.waitUntil( - (async () => { - // @ts-ignore - await clients.claim(); - // @ts-ignore - })(), - ); -}); - -addEventListener("fetch", (event: any) => { - event.respondWith( - (async () => { - const req = event.request; - const url = new URL(req.url); - - if ( - ["/index.html", "/index.js", "/"].includes(url.pathname) || - !url.pathname.startsWith("/browse/") - ) { - return fetch(event.request).then((response: any) => { - response.redirectToFinalURL = true; - return response; - }); - } - - let realUrl = url.pathname.replace(/^\/browse\//, "").replace(/\/$/, ""); - - if (!realUrl.match(/^https?:\/\//)) { - realUrl = `http://${realUrl}`; - } - // Use your existing communication framework to resolve DNS. - const dnsResult = await dnsClient.resolve(new URL(realUrl).hostname); - - if (!dnsResult.error && dnsResult.records.length > 0) { - return providerManager.fetch(dnsResult, new URL(realUrl).pathname); - } - - return new Response("Sorry, that is not a valid web3 website."); - })(), - ); -}); diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 5ee1294..0000000 --- a/src/types.ts +++ /dev/null @@ -1,12 +0,0 @@ -export interface ContentProvider { - supports: (uri: string) => boolean; - fetchContent: ( - uri: string, - path: string, - query?: string, - ) => Promise ; -} - -export interface ContentFilter { - process: (response: Response, mineType: string) => Promise ; -} diff --git a/src/util.ts b/src/util.ts deleted file mode 100644 index 630a675..0000000 --- a/src/util.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { - getKernelLoaded, - getLoginComplete, - getLogoutComplete, -} from "./vars.js"; -import { objAsString } from "@lumeweb/libkernel"; - -export function sendAuthUpdate() { - window.parent.postMessage( - { - method: "kernelAuthStatus", - data: { - loginComplete: getLoginComplete(), - kernelLoaded: getKernelLoaded(), - logoutComplete: getLogoutComplete(), - }, - }, - "*", - ); -} - -function bootloaderWLog(isErr: boolean, ...inputs: any) { - // Build the message, each item gets its own line. We do this because items - // are often full objects. - let message = "[lumeweb-kernel-bootloader]"; - for (let i = 0; i < inputs.length; i++) { - message += "\n"; - message += objAsString(inputs[i]); - } - - // Create the log by sending it to the parent. - window.parent.postMessage( - { - method: "log", - data: { - isErr, - message, - }, - }, - "*", - ); -} - -export function log(...inputs: any) { - bootloaderWLog(false, ...inputs); -} -export function logErr(...inputs: any) { - bootloaderWLog(true, ...inputs); -} - -export function reloadKernel() { - window.location.reload(); -} diff --git a/src/vars.ts b/src/vars.ts deleted file mode 100644 index 5611c69..0000000 --- a/src/vars.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { x25519 } from "@noble/curves/ed25519"; -import { defer } from "@lumeweb/libkernel/module"; -import { KernelAuthStatus } from "@lumeweb/libkernel"; - -let queriesNonce = 1; -let queries: any = {}; -let authStatus: KernelAuthStatus; -let authStatusKnown = false; -let authStatusDefer = defer(); -let loggedInDefer = defer(); - -const store = new Map ( - Object.entries({ - loginComplete: false, - logoutComplete: false, - kernelLoaded: "not yet", - communicationKey: null, - frontendCommunicationPubKey: null, - }), -); - -export function setLoginComplete(status: boolean) { - store.set("loginComplete", status); -} -export function getLoginComplete(): boolean { - return store.get("loginComplete"); -} -export function setLogoutComplete(status: boolean) { - store.set("logoutComplete", status); -} -export function getLogoutComplete(): boolean { - return store.get("logoutComplete"); -} -export function setKernelLoaded(status: string) { - store.set("kernelLoaded", status); -} - -export function getKernelLoaded(): string { - return store.get("kernelLoaded"); -} - -export function getCommunicationKey(): Uint8Array { - if (!store.get("communicationKey")) { - store.set("communicationKey", x25519.utils.randomPrivateKey()); - } - - return store.get("communicationKey"); -} - -export function getCommunicationPubKey() { - return x25519.getPublicKey(getCommunicationKey()); -} - -export function getFrontendCommunicationPubkey(): Uint8Array { - return store.get("frontendCommunicationPubKey"); -} - -export function setFrontendCommunicationPubkey(key: Uint8Array) { - store.set("frontendCommunicationPubKey", key); -} -export function getAuthStatusDefer() { - return authStatusDefer; -} -export function getQueriesNonce(): number { - return queriesNonce; -} -export function addQuery(nonce: any, func: Function) { - queries[nonce] = func; -} - -export function increaseQueriesNonce() { - queriesNonce++; -} -export function setAuthStatus(status: KernelAuthStatus) { - authStatus = status; -} - -export function getAuthStatusKnown() { - return authStatusKnown; -} -export function setAuthStatusKnown(status: boolean) { - authStatusKnown = status; -} -export function getAuthStatus(): KernelAuthStatus { - return authStatus; -} -export function getLoggedInDefer() { - return loggedInDefer; -} -export function resetLoggedInDefer() { - loggedInDefer = defer(); -} -export function getQueries() { - return queries; -} - -export function getQuery(nonce: any) { - return queries[nonce]; -} - -export function deleteQuery(nonce: any) { - delete queries[nonce]; -} diff --git a/styles/globals.css b/styles/globals.css new file mode 100644 index 0000000..cf071ec --- /dev/null +++ b/styles/globals.css @@ -0,0 +1,76 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --primary: 113 49% 55%; + --primary-foreground: black; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --muted: 0 0% 32%; + --muted-foreground: 0 0% 32%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + + --border: 0 0% 32%; + --input: 0 0% 32%; + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/tailwind.config.ts b/tailwind.config.ts new file mode 100644 index 0000000..0377ea1 --- /dev/null +++ b/tailwind.config.ts @@ -0,0 +1,76 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + darkMode: ["class"], + content: [ + './pages/**/*.{ts,tsx}', + './components/**/*.{ts,tsx}', + './app/**/*.{ts,tsx}', + './src/**/*.{ts,tsx}', + ], + theme: { + container: { + center: true, + padding: "2rem", + screens: { + "2xl": "1400px", + }, + }, + extend: { + colors: { + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + keyframes: { + "accordion-down": { + from: { height: 0 }, + to: { height: "var(--radix-accordion-content-height)" }, + }, + "accordion-up": { + from: { height: "var(--radix-accordion-content-height)" }, + to: { height: 0 }, + }, + }, + animation: { + "accordion-down": "accordion-down 0.2s ease-out", + "accordion-up": "accordion-up 0.2s ease-out", + }, + }, + }, + plugins: [require("tailwindcss-animate")], +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..670224f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "exclude": ["node_modules"] +}