Queue executable speed and peer-to-peer sharing plans with tested patches and harnesses

This commit is contained in:
Claude
2026-09-29 19:03:12 +00:00
parent a0ffc1b493
commit c17bd4c9ac
54 changed files with 6369 additions and 11 deletions

View File

@@ -0,0 +1,22 @@
// Plan 012 harness check. Needs playwright (npm i --no-save playwright) and a
// Chromium: CHROMIUM=/path/to/chrome (default: the cloud image's /opt/pw-browsers one).
import { chromium } from 'playwright';
const b = await chromium.launch({ executablePath: process.env.CHROMIUM || '/opt/pw-browsers/chromium-1194/chrome-linux/chrome' });
const p = await b.newPage();
p.on('console', (m) => console.log('console:', m.text()));
await p.goto('http://localhost:8766/');
const out = await p.evaluate(async () => {
const sha = await (await fetch('/sha')).text();
const good = await OPFS.downloadVideo('good', '/api/download/good');
const bad = await OPFS.downloadVideo('bad', '/api/download/bad');
const nohash = await OPFS.downloadVideo('nohash', '/api/download/nohash');
const list = (await OPFS.listVideos()).map((x) => x.id).sort();
await DeviceDB.putFile({ videoId: 'good', cid: good.sha256, size: good.size, state: 'verified' });
const rec = await DeviceDB.getFile('good');
const byCid = await DeviceDB.getByCid(good.sha256);
await DeviceDB.deleteFile('good');
const after = await DeviceDB.listFiles();
return { shaOk: good.sha256 === sha, goodExpected: good.expectedSha === sha, bad, nohashSha: nohash.sha256 === sha, nohashExpected: nohash.expectedSha, list, rec: rec && rec.state, byCid: byCid && byCid.videoId, after: after.length };
});
console.log(JSON.stringify(out));
await b.close();

View File

@@ -0,0 +1,17 @@
// Plan 012 harness: serves ../../frontend plus fake /api/download/<id> responses
// (good hash / wrong hash / no hash). Run: bun device-db-server.js
import { createHash } from 'node:crypto';
const FE = new URL('../../frontend/', import.meta.url).pathname;
const body = new Uint8Array(3 * 1024 * 1024 + 123).map((_, i) => (i * 7) % 256);
const sha = createHash('sha256').update(body).digest('hex');
Bun.serve({ port: 8766, fetch(req) {
const u = new URL(req.url);
if (u.pathname === '/api/download/good') return new Response(body, { headers: { 'Content-Type': 'video/mp4', 'Content-Length': String(body.length), 'X-Content-SHA256': sha } });
if (u.pathname === '/api/download/bad') return new Response(body, { headers: { 'Content-Type': 'video/mp4', 'Content-Length': String(body.length), 'X-Content-SHA256': 'f'.repeat(64) } });
if (u.pathname === '/api/download/nohash') return new Response(body, { headers: { 'Content-Type': 'video/mp4', 'Content-Length': String(body.length) } });
if (u.pathname === '/sha') return new Response(sha);
if (u.pathname === '/') return new Response('<!doctype html><script src="/opfs.js"></script><script src="/sha256.js"></script><script src="/device-db.js"></script>', { headers: { 'Content-Type': 'text/html' } });
const f = Bun.file(FE + u.pathname.slice(1));
return new Response(f, { headers: { 'Content-Type': 'text/javascript' } });
} });
console.log('ready');

View File

@@ -0,0 +1,19 @@
// Plan 016 harness check: an unknown saved file → contribute → accepted.
import { chromium } from 'playwright';
const b = await chromium.launch({ executablePath: process.env.CHROMIUM || '/opt/pw-browsers/chromium-1194/chrome-linux/chrome' });
const p = await b.newPage();
await p.goto('http://localhost:8769/');
const out = await p.evaluate(async () => {
const bytes = new Uint8Array(await (await fetch('/fixture.mp4')).arrayBuffer());
const dir = await (await navigator.storage.getDirectory()).getDirectoryHandle('videos', { create: true });
const w = await (await dir.getFileHandle('upAAAAAAAA9.mp4', { create: true })).createWritable();
await w.write(bytes); await w.close();
P2PClient.start({ getSettings: () => ({}) });
const first = await P2PClient.sync();
const unknown = await P2PClient.unknownVideos();
const c = await P2PClient.contribute(unknown[0]);
const second = await P2PClient.sync();
return { firstUnknown: first.unknown.length, unknown, contribute: { ok: c.ok, adopted: c.adopted, cidOk: /^[0-9a-f]{64}$/.test(c.cid) }, secondAccepted: second.accepted.length, secondUnknown: second.unknown.length };
});
console.log(JSON.stringify(out));
await b.close();

View File

@@ -0,0 +1,29 @@
// Plan 016 harness: routes + intake with real validateMedia (needs ffmpeg).
// Run from server/: bun ../plans/harness/intake-server.js
const { Hono } = await import(process.cwd() + '/node_modules/hono/dist/index.js');
import { mkdtempSync, readFileSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const root = mkdtempSync(join(tmpdir(), 'ytp-h16-'));
process.env.DB_PATH = join(root, 'h.db');
const dbmod = await import(process.cwd() + '/db.js');
const p2pDb = await import(process.cwd() + '/p2p-db.js');
const { registerP2pRoutes } = await import(process.cwd() + '/p2p-routes.js');
const { registerIntakeRoutes } = await import(process.cwd() + '/p2p-intake.js');
const { admitFile } = await import(process.cwd() + '/p2p-admit.js');
const { validateMedia } = await import(process.cwd() + '/media-cache.js');
const FE = process.env.FE_DIR || new URL('../../frontend', import.meta.url).pathname;
await dbmod.initDb(); await p2pDb.initP2pSchema();
const fx = join(root, 'fx.mp4');
spawnSync('ffmpeg', ['-v', 'error', '-y', '-f', 'lavfi', '-i', 'testsrc=size=320x180:rate=25:duration=4', '-f', 'lavfi', '-i', 'sine=frequency=440:duration=4',
'-c:v', 'libx264', '-preset', 'ultrafast', '-pix_fmt', 'yuv420p', '-c:a', 'aac', '-shortest', '-movflags', '+faststart', fx]);
const cfg = { enabled: true, malwareScan: false, scanCmd: 'true', staleDays: 7, intakeDir: join(root, 'intake'), intakeMaxBytes: 50e6 };
const app = new Hono();
const p2p = registerP2pRoutes(app, { cfg, p2pDb, fileForCid: async () => null, sha256Range: async () => '' });
registerIntakeRoutes(app, { cfg, p2pDb, gate: p2p.gate, requireDevice: p2p.requireDevice, validateMedia, admitFile });
app.get('/fixture.mp4', () => new Response(readFileSync(fx)));
app.get('/', (c) => c.html('<!doctype html><script src="/opfs.js"></script><script src="/sha256.js"></script><script src="/device-db.js"></script><script src="/p2p-client.js"></script>'));
app.get('/:f', (c) => new Response(Bun.file(FE + '/' + c.req.param('f')), { headers: { 'Content-Type': 'text/javascript' } }));
Bun.serve({ port: 8769, fetch: app.fetch });
console.log('ready');

View File

@@ -0,0 +1,26 @@
// Plan 013 harness check (see device-db-check.mjs for requirements).
import { chromium } from 'playwright';
const b = await chromium.launch({ executablePath: process.env.CHROMIUM || '/opt/pw-browsers/chromium-1194/chrome-linux/chrome' });
const p = await b.newPage();
p.on('console', (m) => { if (m.type() === 'error') console.log('console:', m.text()); });
await p.goto('http://localhost:8767/');
const out = await p.evaluate(async () => {
const good = await OPFS.downloadVideo('goodAAAAAAA', '/api/download/goodAAAAAAA');
// A legacy save: in OPFS but no DeviceDB record, unknown to the server.
const dir = await (await navigator.storage.getDirectory()).getDirectoryHandle('videos', { create: true });
const w = await (await dir.getFileHandle('legacyAAAAA.mp4', { create: true })).createWritable();
await w.write(new Uint8Array(1000).fill(9)); await w.close();
await DeviceDB.putFile({ videoId: 'goodAAAAAAA', cid: good.sha256, size: good.size, state: 'unverified' });
await DeviceDB.putFile({ videoId: 'ghostAAAAAA', cid: 'e'.repeat(64), size: 5, state: 'verified' }); // no file
P2PClient.start({ getSettings: () => ({}) });
const res = await P2PClient.sync();
const recs = (await DeviceDB.listFiles()).map((r) => [r.videoId, r.state, !!r.cid]).sort();
const holders = await (await fetch('/debug/holders')).json();
// Turn sharing off → full withdrawal.
P2PClient.start({ getSettings: () => ({ p2pShare: false }) });
await P2PClient.sync();
const after = await (await fetch('/debug/holders')).json();
return { accepted: res && res.accepted.length, unknown: res && res.unknown.length, challenges: res && res.challenges.length, recs, trust: holders.map((h) => h.trust), afterShareOff: after.length, device: !!P2PClient.device() };
});
console.log(JSON.stringify(out));
await b.close();

View File

@@ -0,0 +1,27 @@
// Plan 013 harness: real p2p-routes + temp DB + the frontend files.
// Run from server/: bun ../plans/harness/p2p-client-server.js
const { Hono } = await import(process.cwd() + '/node_modules/hono/dist/index.js');
import { mkdtempSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { createHash } from 'node:crypto';
const root = mkdtempSync(join(tmpdir(), 'ytp-h13-'));
process.env.DB_PATH = join(root, 'h.db');
const dbmod = await import(process.cwd() + '/db.js');
const p2pDb = await import(process.cwd() + '/p2p-db.js');
const { registerP2pRoutes } = await import(process.cwd() + '/p2p-routes.js');
const { sha256Range } = await import(process.cwd() + '/hash.js');
const FE = process.env.FE_DIR || new URL('../../frontend', import.meta.url).pathname;
await dbmod.initDb(); await p2pDb.initP2pSchema();
const body = new Uint8Array(3 * 1024 * 1024 + 123).map((_, i) => (i * 7) % 256);
const sha = createHash('sha256').update(body).digest('hex');
const file = join(root, 'good.mp4'); writeFileSync(file, body);
await p2pDb.upsertContent({ cid: sha, videoId: 'goodAAAAAAA', size: body.length, origin: 'server', now: Date.now() });
const app = new Hono();
registerP2pRoutes(app, { cfg: { enabled: true, staleDays: 7 }, p2pDb, fileForCid: async (c) => (c === sha ? { path: file, size: body.length } : null), sha256Range });
app.get('/api/download/:id', () => new Response(body, { headers: { 'Content-Type': 'video/mp4', 'Content-Length': String(body.length), 'X-Content-SHA256': sha } }));
app.get('/debug/holders', async (c) => c.json(await p2pDb.listHolders(sha)));
app.get('/', (c) => c.html('<!doctype html><script src="/opfs.js"></script><script src="/sha256.js"></script><script src="/device-db.js"></script><script src="/p2p-client.js"></script>'));
app.get('/:f', (c) => new Response(Bun.file(FE + '/' + c.req.param('f')), { headers: { 'Content-Type': 'text/javascript' } }));
Bun.serve({ port: 8767, fetch: app.fetch });
console.log('ready');

View File

@@ -0,0 +1,21 @@
// Plan 014 harness check: two browsers, one signal (see device-db-check.mjs for requirements).
import { chromium } from 'playwright';
const b = await chromium.launch({ executablePath: process.env.CHROMIUM || '/opt/pw-browsers/chromium-1194/chrome-linux/chrome' });
const pages = [];
for (let i = 0; i < 2; i++) { const ctx = await b.newContext(); const p = await ctx.newPage(); await p.goto('http://localhost:8768/'); pages.push(p); }
const peers = [];
for (const p of pages) {
peers.push(await p.evaluate(async () => {
P2PClient.start({ getSettings: () => ({}) });
await P2PClient.sync();
for (let i = 0; i < 50 && !P2PClient.isConnected(); i++) await new Promise((r) => setTimeout(r, 100));
window.__got = [];
P2PClient.onMessage('signal', (m) => window.__got.push(m));
return P2PClient.peer();
}));
}
const sent = await pages[0].evaluate((to) => P2PClient.signal(to, { hi: 1 }), peers[1]);
await new Promise((r) => setTimeout(r, 500));
const got = await pages[1].evaluate(() => window.__got);
console.log(JSON.stringify({ peers: peers.map((x) => typeof x === 'string' && x.length === 12), distinct: peers[0] !== peers[1], sent, got: got.map((m) => ({ from: m.from === peers[0], data: m.data })) }));
await b.close();

View File

@@ -0,0 +1,24 @@
// Plan 014 harness: p2p-routes + p2p-hub on a real Bun server (websocket).
// Run from server/: bun ../plans/harness/presence-server.js
const { Hono } = await import(process.cwd() + '/node_modules/hono/dist/index.js');
import { mkdtempSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const root = mkdtempSync(join(tmpdir(), 'ytp-h14-'));
process.env.DB_PATH = join(root, 'h.db');
const dbmod = await import(process.cwd() + '/db.js');
const p2pDb = await import(process.cwd() + '/p2p-db.js');
const { registerP2pRoutes } = await import(process.cwd() + '/p2p-routes.js');
const { createP2pHub } = await import(process.cwd() + '/p2p-hub.js');
const FE = process.env.FE_DIR || new URL('../../frontend', import.meta.url).pathname;
await dbmod.initDb(); await p2pDb.initP2pSchema();
const app = new Hono();
registerP2pRoutes(app, { cfg: { enabled: true, staleDays: 7 }, p2pDb, fileForCid: async () => null, sha256Range: async () => '' });
const hub = createP2pHub({ getDevice: p2pDb.getDevice });
app.get('/', (c) => c.html('<!doctype html><script src="/opfs.js"></script><script src="/sha256.js"></script><script src="/device-db.js"></script><script src="/p2p-client.js"></script>'));
app.get('/:f', (c) => new Response(Bun.file(FE + '/' + c.req.param('f')), { headers: { 'Content-Type': 'text/javascript' } }));
Bun.serve({ port: 8768, fetch(req, server) {
if (new URL(req.url).pathname === '/ws/p2p') return hub.upgrade(req, server);
return app.fetch(req, server);
}, websocket: hub.websocket });
console.log('ready');

View File

@@ -0,0 +1,21 @@
// Plan 018 harness check: a holder is asked to restore an evicted copy.
import { chromium } from 'playwright';
const b = await chromium.launch({ executablePath: process.env.CHROMIUM || '/opt/pw-browsers/chromium-1194/chrome-linux/chrome' });
const p = await b.newPage();
await p.goto('http://localhost:8771/');
const out = await p.evaluate(async () => {
const bytes = new Uint8Array(await (await fetch('/fixture.mp4')).arrayBuffer());
const dir = await (await navigator.storage.getDirectory()).getDirectoryHandle('videos', { create: true });
const w = await (await dir.getFileHandle('goneAAAAAAA.mp4', { create: true })).createWritable();
await w.write(bytes); await w.close();
P2PClient.start({ getSettings: () => ({}) });
const rep = await P2PClient.sync(); // hashes the file, reports it → accepted (cid is verified content)
for (let i = 0; i < 50 && !P2PClient.isConnected(); i++) await new Promise((r) => setTimeout(r, 100));
const s1 = await (await fetch('/api/streams?v=goneAAAAAAA')).json();
let dbg;
for (let i = 0; i < 50; i++) { dbg = await (await fetch('/debug')).json(); if (dbg.adopted.length) break; await new Promise((r) => setTimeout(r, 200)); }
const s2 = await (await fetch('/api/streams?v=goneAAAAAAA')).json();
return { accepted: rep.accepted.length, first: s1, adopted: dbg.adopted.map((a) => [a.videoId, a.sha256 === dbg.cid]), second: s2 };
});
console.log(JSON.stringify(out));
await b.close();

View File

@@ -0,0 +1,49 @@
// Plan 018 harness: hub + intake + rehydrator + a stand-in /api/streams whose
// source always fails and whose server copy is gone. Port 8771.
// Run from server/: bun ../plans/harness/rehydrate-server.js (needs ffmpeg)
const { Hono } = await import(process.cwd() + '/node_modules/hono/dist/index.js');
import { mkdtempSync, readFileSync, unlinkSync } from 'node:fs';
import { spawnSync } from 'node:child_process';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { createHash } from 'node:crypto';
const root = mkdtempSync(join(tmpdir(), 'ytp-h18-'));
process.env.DB_PATH = join(root, 'h.db');
const dbmod = await import(process.cwd() + '/db.js');
const p2pDb = await import(process.cwd() + '/p2p-db.js');
const { registerP2pRoutes } = await import(process.cwd() + '/p2p-routes.js');
const { registerIntakeRoutes } = await import(process.cwd() + '/p2p-intake.js');
const { createP2pHub, createRehydrator } = await import(process.cwd() + '/p2p-hub.js');
const { admitFile } = await import(process.cwd() + '/p2p-admit.js');
const { validateMedia } = await import(process.cwd() + '/media-cache.js');
const FE = process.env.FE_DIR || new URL('../../frontend', import.meta.url).pathname;
await dbmod.initDb(); await p2pDb.initP2pSchema();
const fx = join(root, 'fx.mp4');
spawnSync('ffmpeg', ['-v', 'error', '-y', '-f', 'lavfi', '-i', 'testsrc=size=320x180:rate=25:duration=4', '-f', 'lavfi', '-i', 'sine=frequency=440:duration=4',
'-c:v', 'libx264', '-preset', 'ultrafast', '-pix_fmt', 'yuv420p', '-c:a', 'aac', '-shortest', '-movflags', '+faststart', fx]);
const bytes = readFileSync(fx);
const cid = createHash('sha256').update(bytes).digest('hex');
await p2pDb.upsertContent({ cid, videoId: 'goneAAAAAAA', size: bytes.length, origin: 'server', now: Date.now() }); // verified earlier, file since evicted
const cfg = { enabled: true, malwareScan: false, scanCmd: 'true', staleDays: 7, intakeDir: join(root, 'intake'), intakeMaxBytes: 50e6 };
const adopted = [];
const app = new Hono();
const p2p = registerP2pRoutes(app, { cfg, p2pDb, fileForCid: async () => null, sha256Range: async () => '' });
const hub = createP2pHub({ getDevice: p2pDb.getDevice });
registerIntakeRoutes(app, { cfg, p2pDb, gate: p2p.gate, requireDevice: p2p.requireDevice, validateMedia, admitFile,
serverHasCid: async () => adopted.length > 0,
adopt: async (videoId, path, info) => { adopted.push({ videoId, sha256: info.sha256 }); unlinkSync(path); return { adopted: true }; } });
const rehydrate = createRehydrator({ p2pDb, hub, hasServerCopy: async () => adopted.length > 0 });
app.get('/api/streams', async (c) => {
const v = c.req.query('v');
if (await rehydrate(v)) return c.json({ ok: false, restoring: true, error: 'restoring from a device' }, 503);
return c.json({ ok: false, error: 'source unavailable' }, 500);
});
app.get('/debug', (c) => c.json({ adopted, cid }));
app.get('/fixture.mp4', () => new Response(bytes));
app.get('/', (c) => c.html('<!doctype html><script src="/opfs.js"></script><script src="/sha256.js"></script><script src="/device-db.js"></script><script src="/p2p-client.js"></script>'));
app.get('/:f', (c) => new Response(Bun.file(FE + '/' + c.req.param('f')), { headers: { 'Content-Type': 'text/javascript' } }));
Bun.serve({ port: 8771, fetch(req, server) {
if (new URL(req.url).pathname === '/ws/p2p') return hub.upgrade(req, server);
return app.fetch(req, server);
}, websocket: hub.websocket });
console.log('ready');

View File

@@ -0,0 +1,52 @@
// Plan 017 harness check: device A holds a file; device B downloads it over WebRTC.
import { chromium } from 'playwright';
const b = await chromium.launch({
executablePath: process.env.CHROMIUM || '/opt/pw-browsers/chromium-1194/chrome-linux/chrome',
args: ['--disable-features=WebRtcHideLocalIpsWithMdns'],
});
const pages = [];
for (let i = 0; i < 2; i++) { const ctx = await b.newContext(); const p = await ctx.newPage(); p.on('console', (m) => { if (m.type() === 'error') console.log('console', i, m.text()); }); await p.goto('http://localhost:8770/'); pages.push(p); }
const setup = (p) => p.evaluate(async () => {
P2PClient.start({ getSettings: () => ({}) });
await P2PClient.sync();
for (let i = 0; i < 50 && !P2PClient.isConnected(); i++) await new Promise((r) => setTimeout(r, 100));
P2PTransfer.start({ iceServers: [] });
return P2PClient.peer();
});
// Holder: write a 5 MB file + registry record.
const held = await pages[0].evaluate(async () => {
const bytes = new Uint8Array(5 * 1024 * 1024 + 777).map((_, i) => (i * 31 + 7) % 256);
const dir = await (await navigator.storage.getDirectory()).getDirectoryHandle('videos', { create: true });
const w = await (await dir.getFileHandle('heldAAAAAAA.mp4', { create: true })).createWritable();
await w.write(bytes); await w.close();
const cid = Sha256.hex(bytes);
await DeviceDB.putFile({ videoId: 'heldAAAAAAA', cid, size: bytes.length, state: 'verified' });
return { cid, size: bytes.length };
});
const peerA = await setup(pages[0]);
await setup(pages[1]);
const t0 = Date.now();
const res = await pages[1].evaluate(async ({ peerA, held }) => {
const good = await P2PTransfer.download({ videoId: 'gotAAAAAAAA', cid: held.cid, size: held.size, peers: [{ peer: peerA }] });
const list = (await OPFS.listVideos()).map((x) => [x.id, x.size]);
const bad = await P2PTransfer.download({ videoId: 'badAAAAAAAA', cid: 'f'.repeat(64), size: held.size, peers: [{ peer: peerA }] });
const list2 = (await OPFS.listVideos()).map((x) => x.id);
return { good, list, bad, list2 };
}, { peerA, held });
// Holder's file gets corrupted (same size, one byte flipped) but its record still claims the cid.
await pages[0].evaluate(async () => {
const dir = await (await navigator.storage.getDirectory()).getDirectoryHandle('videos');
const fh = await dir.getFileHandle('heldAAAAAAA.mp4');
const bytes = new Uint8Array(await (await fh.getFile()).arrayBuffer());
bytes[12345] ^= 0xff;
const w = await fh.createWritable(); await w.write(bytes); await w.close();
});
res.corrupt = await pages[1].evaluate(async ({ peerA, held }) => {
const r = await P2PTransfer.download({ videoId: 'corAAAAAAAA', cid: held.cid, size: held.size, peers: [{ peer: peerA }] });
await new Promise((x) => setTimeout(x, 300));
const names = [];
for await (const [n] of (await (await navigator.storage.getDirectory()).getDirectoryHandle('videos')).entries()) names.push(n);
return { r, names: names.sort() };
}, { peerA, held });
console.log(JSON.stringify({ ...res, ms: Date.now() - t0 }));
await b.close();

View File

@@ -0,0 +1,24 @@
// Plan 017 harness: p2p-routes + p2p-hub + the transfer scripts (port 8770).
// Run from server/: bun ../plans/harness/transfer-server.js
const { Hono } = await import(process.cwd() + '/node_modules/hono/dist/index.js');
import { mkdtempSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
const root = mkdtempSync(join(tmpdir(), 'ytp-h14-'));
process.env.DB_PATH = join(root, 'h.db');
const dbmod = await import(process.cwd() + '/db.js');
const p2pDb = await import(process.cwd() + '/p2p-db.js');
const { registerP2pRoutes } = await import(process.cwd() + '/p2p-routes.js');
const { createP2pHub } = await import(process.cwd() + '/p2p-hub.js');
const FE = process.env.FE_DIR || new URL('../../frontend', import.meta.url).pathname;
await dbmod.initDb(); await p2pDb.initP2pSchema();
const app = new Hono();
registerP2pRoutes(app, { cfg: { enabled: true, staleDays: 7 }, p2pDb, fileForCid: async () => null, sha256Range: async () => '' });
const hub = createP2pHub({ getDevice: p2pDb.getDevice });
app.get('/', (c) => c.html('<!doctype html><script src="/opfs.js"></script><script src="/sha256.js"></script><script src="/device-db.js"></script><script src="/p2p-client.js"></script><script src="/p2p-transfer.js"></script>'));
app.get('/:f', (c) => new Response(Bun.file(FE + '/' + c.req.param('f')), { headers: { 'Content-Type': 'text/javascript' } }));
Bun.serve({ port: 8770, fetch(req, server) {
if (new URL(req.url).pathname === '/ws/p2p') return hub.upgrade(req, server);
return app.fetch(req, server);
}, websocket: hub.websocket });
console.log('ready');