Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: remove unused helia, use verified fetch, and simplify code #89

Merged
merged 10 commits into from
Mar 9, 2024
53 changes: 3 additions & 50 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 1 addition & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,11 @@
}
},
"dependencies": {
"@helia/block-brokers": "^2.0.1",
"@helia/http": "^1.0.0",
"@helia/interface": "^4.0.0",
"@helia/ipns": "^6.0.0",
"@helia/routers": "^1.0.0",
"@helia/ipns": "^6.0.1",
"@helia/verified-fetch": "^1.1.0",
"@libp2p/logger": "^4.0.6",
"@sgtpooki/file-type": "^1.0.1",
"blockstore-idb": "^1.1.8",
"datastore-idb": "^2.1.8",
"debug": "^4.3.4",
"mime-types": "^2.1.35",
"multiformats": "^11.0.2",
"react": "^18.2.0",
"react-dom": "^18.2.0"
Expand Down
14 changes: 9 additions & 5 deletions src/components/config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { ConfigContext } from '../context/config-context.tsx'
import { HeliaServiceWorkerCommsChannel } from '../lib/channel.ts'
import { getConfig, loadConfigFromLocalStorage } from '../lib/config-db.ts'
import { LOCAL_STORAGE_KEYS } from '../lib/local-storage.ts'
import { Collapsible } from './collapsible'
import { trace } from '../lib/logger.ts'
import { Collapsible } from './collapsible.tsx'
import LocalStorageInput from './local-storage-input.tsx'
import { LocalStorageToggle } from './local-storage-toggle'
import { ServiceWorkerReadyButton } from './sw-ready-button.tsx'
Expand Down Expand Up @@ -45,15 +46,16 @@ export default (): JSX.Element | null => {
}
// we get the iframe origin from a query parameter called 'origin', if this is loaded in an iframe
// TODO: why we need this origin here? where is targetOrigin used?
const targetOrigin = decodeURIComponent(window.location.search.split('origin=')[1])
const targetOrigin = decodeURIComponent(window.location.hash.split('@origin=')[1])
const config = await getConfig()

trace('config-page: postMessage config to origin ', config, origin)
/**
* The reload page in the parent window is listening for this message, and then it passes a RELOAD_CONFIG message to the service worker
*/
window.parent?.postMessage({ source: 'helia-sw-config-iframe', target: 'PARENT', action: 'RELOAD_CONFIG', config }, {
targetOrigin
})
trace('config-page: RELOAD_CONFIG sent to parent window')
}, [])

useEffect(() => {
Expand All @@ -66,9 +68,11 @@ export default (): JSX.Element | null => {
const saveConfig = useCallback(async () => {
try {
await loadConfigFromLocalStorage()
trace('config-page: sending RELOAD_CONFIG to service worker')
// update the BASE_URL service worker
// TODO: use channel.messageAndWaitForResponse to ensure that the config is loaded before proceeding.
channel.postMessage({ target: 'SW', action: 'RELOAD_CONFIG' })
await channel.messageAndWaitForResponse('SW', { target: 'SW', action: 'RELOAD_CONFIG' })
// base_domain service worker is updated
trace('config-page: RELOAD_CONFIG_SUCCESS for %s', window.location.origin)
// update the <subdomain>.<namespace>.BASE_URL service worker
await postFromIframeToParentSw()
setConfigExpanded(false)
Expand Down
36 changes: 13 additions & 23 deletions src/get-helia.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,20 @@
import { trustlessGateway } from '@helia/block-brokers'
import { createHeliaHTTP } from '@helia/http'
import { delegatedHTTPRouting } from '@helia/routers'
import { IDBBlockstore } from 'blockstore-idb'
import { IDBDatastore } from 'datastore-idb'
import { dnsJsonOverHttps } from '@helia/ipns/dns-resolvers'
import { createVerifiedFetch, type VerifiedFetch } from '@helia/verified-fetch'
import { getConfig } from './lib/config-db.ts'
import { trace } from './lib/logger.ts'
import type { Helia } from '@helia/interface'
import { contentTypeParser } from './lib/content-type-parser.ts'
import { log } from './lib/logger.ts'

export async function getHelia (): Promise<Helia> {
export async function getVerifiedFetch (): Promise<VerifiedFetch> {
const config = await getConfig()
trace(`config-debug: got config for sw location ${self.location.origin}`, config)
const blockstore = new IDBBlockstore('./helia-sw/blockstore')
const datastore = new IDBDatastore('./helia-sw/datastore')
await blockstore.open()
await datastore.open()
log(`config-debug: got config for sw location ${self.location.origin}`, config)

const helia = await createHeliaHTTP({
blockstore,
datastore,
blockBrokers: [
trustlessGateway({
gateways: [...config.gateways, 'https://trustless-gateway.link']
})
],
routers: [...config.routers, 'https://delegated-ipfs.dev'].map(rUrl => delegatedHTTPRouting(rUrl))
const verifiedFetch = await createVerifiedFetch({
gateways: config.gateways ?? ['https://trustless-gateway.link'],
routers: config.routers ?? ['https://delegated-ipfs.dev'],
dnsResolvers: ['https://delegated-ipfs.dev/dns-query'].map(dnsJsonOverHttps)
}, {
contentTypeParser
})

return helia
return verifiedFetch
}
1 change: 1 addition & 0 deletions src/lib/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export enum COLORS {

export enum ChannelActions {
RELOAD_CONFIG = 'RELOAD_CONFIG',
RELOAD_CONFIG_SUCCESS = 'RELOAD_CONFIG_SUCCESS'
}
13 changes: 7 additions & 6 deletions src/lib/config-db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ export async function loadConfigFromLocalStorage (): Promise<void> {
if (typeof globalThis.localStorage !== 'undefined') {
const db = await openDatabase()
const localStorage = globalThis.localStorage
const localStorageGatewaysString = localStorage.getItem(LOCAL_STORAGE_KEYS.config.gateways) ?? '[]'
const localStorageRoutersString = localStorage.getItem(LOCAL_STORAGE_KEYS.config.routers) ?? '[]'
const localStorageGatewaysString = localStorage.getItem(LOCAL_STORAGE_KEYS.config.gateways) ?? '["https://trustless-gateway.link"]'
const localStorageRoutersString = localStorage.getItem(LOCAL_STORAGE_KEYS.config.routers) ?? '["https://delegated-ipfs.dev"]'
const autoReload = localStorage.getItem(LOCAL_STORAGE_KEYS.config.autoReload) === 'true'
const debug = localStorage.getItem(LOCAL_STORAGE_KEYS.config.debug) ?? ''
const gateways = JSON.parse(localStorageGatewaysString)
Expand All @@ -71,8 +71,9 @@ export async function loadConfigFromLocalStorage (): Promise<void> {
}

export async function setConfig (config: ConfigDb): Promise<void> {
log('config-debug: setting config', config)
debugLib.enable(config.debug ?? '')
debugLib.enable(config.debug ?? '') // set debug level first.
log('config-debug: setting config %O for domain %s', config, window.location.origin)

const db = await openDatabase()
await setInDatabase(db, 'gateways', config.gateways)
await setInDatabase(db, 'routers', config.routers)
Expand All @@ -84,8 +85,8 @@ export async function setConfig (config: ConfigDb): Promise<void> {
export async function getConfig (): Promise<ConfigDb> {
const db = await openDatabase()

const gateways = await getFromDatabase(db, 'gateways') ?? []
const routers = await getFromDatabase(db, 'routers') ?? []
const gateways = await getFromDatabase(db, 'gateways') ?? ['https://trustless-gateway.link']
const routers = await getFromDatabase(db, 'routers') ?? ['https://delegated-ipfs.dev']
const autoReload = await getFromDatabase(db, 'autoReload') ?? false
const debug = await getFromDatabase(db, 'debug') ?? ''
debugLib.enable(debug)
Expand Down
47 changes: 47 additions & 0 deletions src/lib/content-type-parser.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { type ContentTypeParser } from '@helia/verified-fetch'
import { fileTypeFromBuffer } from '@sgtpooki/file-type'

// default from verified-fetch is application/octect-stream, which forces a download. This is not what we want for MANY file types.
export const defaultMimeType = 'text/html'

export const contentTypeParser: ContentTypeParser = async (bytes, fileName) => {
const detectedType = (await fileTypeFromBuffer(bytes))?.mime
if (detectedType != null) {
return detectedType
}
if (fileName == null) {
// no other way to determine file-type.
return defaultMimeType
}

// no need to include file-types listed at https://github.com/SgtPooki/file-type#supported-file-types
switch (fileName.split('.').pop()) {
case 'css':
return 'text/css'
case 'html':
return 'text/html'
case 'js':
return 'application/javascript'
case 'json':
return 'application/json'
case 'txt':
return 'text/plain'
case 'woff2':
return 'font/woff2'
// see bottom of https://github.com/SgtPooki/file-type#supported-file-types
case 'svg':
return 'image/svg+xml'
case 'csv':
return 'text/csv'
case 'doc':
return 'application/msword'
case 'xls':
return 'application/vnd.ms-excel'
case 'ppt':
return 'application/vnd.ms-powerpoint'
case 'msi':
return 'application/x-msdownload'
default:
return defaultMimeType
}
}
Loading
Loading