From 6b5e2628a93ec976d4b23a4bdf351fa9f14d604b Mon Sep 17 00:00:00 2001 From: Daniel N <2color@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:29:44 +0100 Subject: [PATCH 01/23] feat: add helia/verified-fetch browser example --- .../.gitignore | 24 ++++++ .../README.md | 36 ++++++++ .../index.html | 13 +++ .../package.json | 32 +++++++ .../postcss.config.js | 6 ++ .../src/App.tsx | 83 +++++++++++++++++++ .../src/constants.ts | 20 +++++ .../src/index.css | 3 + .../src/main.tsx | 9 ++ .../src/vite-env.d.ts | 1 + .../tailwind.config.js | 8 ++ .../tsconfig.json | 25 ++++++ .../tsconfig.node.json | 10 +++ .../vite.config.ts | 7 ++ 14 files changed, 277 insertions(+) create mode 100644 examples/helia-browser-react-verified-fetch/.gitignore create mode 100644 examples/helia-browser-react-verified-fetch/README.md create mode 100644 examples/helia-browser-react-verified-fetch/index.html create mode 100644 examples/helia-browser-react-verified-fetch/package.json create mode 100644 examples/helia-browser-react-verified-fetch/postcss.config.js create mode 100644 examples/helia-browser-react-verified-fetch/src/App.tsx create mode 100644 examples/helia-browser-react-verified-fetch/src/constants.ts create mode 100644 examples/helia-browser-react-verified-fetch/src/index.css create mode 100644 examples/helia-browser-react-verified-fetch/src/main.tsx create mode 100644 examples/helia-browser-react-verified-fetch/src/vite-env.d.ts create mode 100644 examples/helia-browser-react-verified-fetch/tailwind.config.js create mode 100644 examples/helia-browser-react-verified-fetch/tsconfig.json create mode 100644 examples/helia-browser-react-verified-fetch/tsconfig.node.json create mode 100644 examples/helia-browser-react-verified-fetch/vite.config.ts diff --git a/examples/helia-browser-react-verified-fetch/.gitignore b/examples/helia-browser-react-verified-fetch/.gitignore new file mode 100644 index 00000000..a547bf36 --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/examples/helia-browser-react-verified-fetch/README.md b/examples/helia-browser-react-verified-fetch/README.md new file mode 100644 index 00000000..0cb5d8eb --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/README.md @@ -0,0 +1,36 @@ +

+ + Helia logo + +

+ +

Browser Verified Retrieval with @helia/verified-fetch

+ +

+ +
+ Explore the docs + ยท + + ยท + Report Bug + ยท + Request Feature/Example +

+ + +## Table of Contents + +- [Getting Started](#getting-started) + - [Installation and Running example](#installation-and-running-example) +- [Usage](#usage) + + +## Getting Started + +### Installation and Running example + +```console +npm install +npm run dev +``` diff --git a/examples/helia-browser-react-verified-fetch/index.html b/examples/helia-browser-react-verified-fetch/index.html new file mode 100644 index 00000000..04bcec5c --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/index.html @@ -0,0 +1,13 @@ + + + + + + + Verified Retrieval with @helia/verified-fetch + + +
+ + + diff --git a/examples/helia-browser-react-verified-fetch/package.json b/examples/helia-browser-react-verified-fetch/package.json new file mode 100644 index 00000000..bcf1b89c --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/package.json @@ -0,0 +1,32 @@ +{ + "name": "helia-browser-react-verified-fetch", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc && vite build", + "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview" + }, + "dependencies": { + "@helia/verified-fetch": "^0.0.0-6c88ee1", + "react": "^18.2.0", + "react-dom": "^18.2.0" + }, + "devDependencies": { + "@types/react": "^18.2.43", + "@types/react-dom": "^18.2.17", + "@typescript-eslint/eslint-plugin": "^6.14.0", + "@typescript-eslint/parser": "^6.14.0", + "@vitejs/plugin-react": "^4.2.1", + "autoprefixer": "^10.4.17", + "eslint": "^8.55.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.5", + "postcss": "^8.4.34", + "tailwindcss": "^3.4.1", + "typescript": "^5.2.2", + "vite": "^5.0.8" + } +} diff --git a/examples/helia-browser-react-verified-fetch/postcss.config.js b/examples/helia-browser-react-verified-fetch/postcss.config.js new file mode 100644 index 00000000..2e7af2b7 --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/examples/helia-browser-react-verified-fetch/src/App.tsx b/examples/helia-browser-react-verified-fetch/src/App.tsx new file mode 100644 index 00000000..85867b30 --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/src/App.tsx @@ -0,0 +1,83 @@ +import { useCallback, useState } from 'react' +import { verifiedFetch } from '@helia/verified-fetch' +import { helpText } from './constants' + +function App() { + const [path, setPath] = useState('') + const [output, setOutput] = useState('') + const [err, setErr] = useState('') + + const onFetchJson = useCallback(async () => { + if (!path) { + setErr('Invalid path') + return + } + const resp = await verifiedFetch(path) + const json = await resp.json() + + setOutput(json) + }, [path]) + + const onFetchImage = useCallback(async () => {}, [path]) + const onFetchFile = useCallback(async () => {}, [path]) + + return ( +
+
+
+ {/* Left */} +
+

+ Verified Retrieval with @helia/verified-fetch +

+ + setPath(e.target.value)} + value={path} + /> + + + + +
{helpText}
+
+ {/* Left */} + + {/* Right */} +
+ {output && ( +
+                
+              
+ )} +
+
+
+
+ ) +} + +export default App diff --git a/examples/helia-browser-react-verified-fetch/src/constants.ts b/examples/helia-browser-react-verified-fetch/src/constants.ts new file mode 100644 index 00000000..64631a1b --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/src/constants.ts @@ -0,0 +1,20 @@ +export const helpText = `Example Paths +========= +IPNS name ๐Ÿ‘‡ +ipns://k51qzi5uqu5dhp48cti0590jyvwgxssrii0zdf19pyfsxwoqomqvfg6bg8qj3s + +DNSLink ๐Ÿ‘‡ +ipns://tokens.uniswap.org + +JSON ๐Ÿ‘‡ +ipfs://bagaaieracglt4ey6qsxtvzqsgwnsw3b6p2tb7nmx5wdgxur2zia7q6nnzh7q + +UnixFS JSON ๐Ÿ‘‡ +ipfs://bafybeia5ci747h54m2ybc4rf6yqdtm6nzdisxv57pk66fgubjsnnja6wq4 + +UnixFS image ๐Ÿ‘‡ +ipfs://bafybeicklkqcnlvtiscr2hzkubjwnwjinvskffn4xorqeduft3wq7vm5u4 + +UnixFS video ๐Ÿ‘‡ +ipfs://bafybeicq6y27fphdisjtxaybzxold7dczhvxiiyn3bvkyht7b36lveerrm +` \ No newline at end of file diff --git a/examples/helia-browser-react-verified-fetch/src/index.css b/examples/helia-browser-react-verified-fetch/src/index.css new file mode 100644 index 00000000..b5c61c95 --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/src/index.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/examples/helia-browser-react-verified-fetch/src/main.tsx b/examples/helia-browser-react-verified-fetch/src/main.tsx new file mode 100644 index 00000000..e63eef4a --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/src/main.tsx @@ -0,0 +1,9 @@ +import React from 'react' +import ReactDOM from 'react-dom/client' +import App from './App.tsx' + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/examples/helia-browser-react-verified-fetch/src/vite-env.d.ts b/examples/helia-browser-react-verified-fetch/src/vite-env.d.ts new file mode 100644 index 00000000..11f02fe2 --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/helia-browser-react-verified-fetch/tailwind.config.js b/examples/helia-browser-react-verified-fetch/tailwind.config.js new file mode 100644 index 00000000..7141e452 --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], + theme: { + extend: {}, + }, + plugins: [], +} diff --git a/examples/helia-browser-react-verified-fetch/tsconfig.json b/examples/helia-browser-react-verified-fetch/tsconfig.json new file mode 100644 index 00000000..a7fc6fbf --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/examples/helia-browser-react-verified-fetch/tsconfig.node.json b/examples/helia-browser-react-verified-fetch/tsconfig.node.json new file mode 100644 index 00000000..42872c59 --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/examples/helia-browser-react-verified-fetch/vite.config.ts b/examples/helia-browser-react-verified-fetch/vite.config.ts new file mode 100644 index 00000000..5a33944a --- /dev/null +++ b/examples/helia-browser-react-verified-fetch/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) From 72f3d59bc4f55ee934b3871dfeb6fb7735c84d2b Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Thu, 8 Feb 2024 04:42:02 -0800 Subject: [PATCH 02/23] feat(verified-fetch): improve UX (#286) --- .../package.json | 3 +- .../src/App.tsx | 196 ++++++++++++++++-- 2 files changed, 179 insertions(+), 20 deletions(-) diff --git a/examples/helia-browser-react-verified-fetch/package.json b/examples/helia-browser-react-verified-fetch/package.json index bcf1b89c..4d995a25 100644 --- a/examples/helia-browser-react-verified-fetch/package.json +++ b/examples/helia-browser-react-verified-fetch/package.json @@ -10,7 +10,8 @@ "preview": "vite preview" }, "dependencies": { - "@helia/verified-fetch": "^0.0.0-6c88ee1", + "@helia/verified-fetch": "0.0.0-3851fe2", + "@sgtpooki/file-type": "^1.0.1", "react": "^18.2.0", "react-dom": "^18.2.0" }, diff --git a/examples/helia-browser-react-verified-fetch/src/App.tsx b/examples/helia-browser-react-verified-fetch/src/App.tsx index 85867b30..2335dbde 100644 --- a/examples/helia-browser-react-verified-fetch/src/App.tsx +++ b/examples/helia-browser-react-verified-fetch/src/App.tsx @@ -1,25 +1,182 @@ -import { useCallback, useState } from 'react' +// import { verifiedFetch, createVerifiedFetch } from '@helia/verified-fetch' import { verifiedFetch } from '@helia/verified-fetch' +import { fileTypeFromBuffer } from '@sgtpooki/file-type' +import { useCallback, useState } from 'react' import { helpText } from './constants' -function App() { +function renderOutput (output: string | JSX.Element, err: string): JSX.Element { + console.log('err: ', err) + console.log('output: ', output) + if (err.length > 0) { + return ( +
+
{err}
+
+ ) + } + + if (typeof output === 'string') { + return ( +
+ {output != null && ( +
+            {`${output}`}
+          
+ )} +
+ ) + } + + return output +} + +function loadingIndicator (message: string): JSX.Element { + return ( +
+
Loading... {message}
+
+ ) +} + +function App (): JSX.Element { const [path, setPath] = useState('') - const [output, setOutput] = useState('') + const [output, setOutput] = useState('') const [err, setErr] = useState('') + const [loading, setLoadingTo] = useState(null) + + const setSuccess = useCallback((message: string | JSX.Element) => { + setOutput(message) + setLoadingTo(null) + setErr('') + }, []) + const setError = useCallback((message: string) => { + setOutput('') + setLoadingTo(null) + setErr(message) + }, []) + const setLoading = useCallback((message: string) => { + setErr('') + setLoadingTo(loadingIndicator(message)) + }, []) + + const handleImageType = useCallback(async (resp: Response) => { + try { + setLoading('Waiting for full image data...') + const blob = await resp.blob() + const url = URL.createObjectURL(blob) + setSuccess(fetched image content) + } catch (err) { + setError((err as Error).message) + } + }, []) + + const handleJsonType = useCallback(async (resp: Response) => { + try { + setLoading('Waiting for full JSON data...') + const json = await resp.json() + setSuccess(JSON.stringify(json, null, 2)) + } catch (err) { + setError((err as Error).message) + + } + }, []) + + const handleVideoType = useCallback(async (resp: Response) => { + try { + setLoading('Waiting for full video data...') + const blob = await resp.blob() + const url = URL.createObjectURL(blob) + setSuccess(