@seedprotocol/gateway-hyper 0.7.4-next.711.gce2b766 → 0.7.4-next.784.g879c6a3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * Official Seed Protocol gateway Hyper tunnel operator key (z32).
3
3
  * Empty until ops generate and back up the first operator keypair.
4
+ * Also defined in packages/arweave/src/constants.ts; keep both equal (gateway-hyper __tests__/constants.test.ts checks).
4
5
  */
5
6
  export declare const DEFAULT_SEED_GATEWAY_HYPER_KEY = "";
6
7
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,8BAA8B,KAAK,CAAA"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,KAAK,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"src-CnXam5V8.js","names":["URL","fs","path","HyperDHT","ID","http","URL$1","toHex","buf","fromHex","hex","encodePublicKeyZ32","publicKey","decodePublicKey","trimmed","key","loadOrCreateOperatorKeypair","resolved","keyFile","raw","parsed","dir","kp","persisted","createEphemeralClientKeypair","MAX_FRAME_BYTES","StreamByteReader","stream","chunk","waiters","w","err","length","next","out","readers","getReader","reader","readExact","writeBuffer","onDrain","onError","resolve","reject","writeFrame","payload","header","readFrame","writeTunnelRequest","meta","body","readTunnelRequest","metaBuf","writeTunnelResponse","readTunnelResponse","flattenRequestHeaders","value","headers","filterResponseHeaders","skip","proxyTunnelRequest","base","upstreamBase","targetUrl","req","chunks","res","handleConnection","pendingRequest","socket","result","upstream","serveTunnel","options","keypair","dht","server","createTunnelSession","remotePublicKey","clientKey","activeSocket","connecting","getSocket","onReady","tunnelQueue","runOnTunnel","run","fn","readRequestBody","createLocalServer","responseMeta","responseBody","forwardHttp","message","connectTunnel","host","port","session","address","boundPort","baseUrl","localGatewayUrl","stripMountPath","urlPath","qIndex","pathname","query","mount","mountPath","rest","readNodeBody","forwardNodeRequest","writeNodeResponse","forwardFetchRequest","url","request","bodyBuf","headerRecord","resolveProxyKey","createGatewayProxy","starting","ensureSession","s","proxy","DEFAULT_SEED_GATEWAY_HYPER_KEY"],"sources":["../src/keys.ts","../src/tunnel/protocol.ts","../src/tunnel/proxy.ts","../src/tunnel/serve.ts","../src/tunnel/session.ts","../src/tunnel/connect.ts","../src/tunnel/mountPath.ts","../src/tunnel/forward.ts","../src/tunnel/proxyApp.ts","../src/constants.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport HyperDHT from 'hyperdht'\nimport ID from 'hypercore-id-encoding'\nimport type { OperatorKeyPair } from './types'\n\nexport interface PersistedKeyFile {\n publicKey: string\n secretKey: string\n encoding: 'hex'\n}\n\nfunction toHex(buf: Buffer): string {\n return buf.toString('hex')\n}\n\nfunction fromHex(hex: string): Buffer {\n return Buffer.from(hex, 'hex')\n}\n\nexport function encodePublicKeyZ32(publicKey: Buffer): string {\n return ID.encode(publicKey)\n}\n\nexport function decodePublicKey(key: string): Buffer {\n const trimmed = key.trim()\n if (!trimmed) {\n throw new Error('Gateway Hyper key is empty')\n }\n try {\n return Buffer.from(ID.decode(trimmed))\n } catch {\n if (/^[a-fA-F0-9]{64}$/.test(trimmed)) {\n return fromHex(trimmed)\n }\n throw new Error(`Invalid Gateway Hyper key (expected z32 or 64-char hex): ${trimmed.slice(0, 12)}…`)\n }\n}\n\nexport function loadOrCreateOperatorKeypair(keyFile: string): OperatorKeyPair {\n const resolved = path.resolve(keyFile)\n if (fs.existsSync(resolved)) {\n const raw = fs.readFileSync(resolved, 'utf8')\n const parsed = JSON.parse(raw) as PersistedKeyFile\n if (!parsed.publicKey || !parsed.secretKey) {\n throw new Error(`Invalid key file at ${resolved}: missing publicKey or secretKey`)\n }\n const publicKey = fromHex(parsed.publicKey)\n const secretKey = fromHex(parsed.secretKey)\n return {\n publicKey,\n secretKey,\n z32: encodePublicKeyZ32(publicKey),\n }\n }\n\n const dir = path.dirname(resolved)\n fs.mkdirSync(dir, { recursive: true })\n const kp = HyperDHT.keyPair()\n const persisted: PersistedKeyFile = {\n publicKey: toHex(kp.publicKey),\n secretKey: toHex(kp.secretKey),\n encoding: 'hex',\n }\n fs.writeFileSync(resolved, `${JSON.stringify(persisted, null, 2)}\\n`, { mode: 0o600 })\n return {\n publicKey: kp.publicKey,\n secretKey: kp.secretKey,\n z32: encodePublicKeyZ32(kp.publicKey),\n }\n}\n\nexport function createEphemeralClientKeypair(): OperatorKeyPair {\n const kp = HyperDHT.keyPair()\n return {\n publicKey: kp.publicKey,\n secretKey: kp.secretKey,\n z32: encodePublicKeyZ32(kp.publicKey),\n }\n}\n","import type { Readable, Writable } from 'node:stream'\nimport type { TunnelMeta, TunnelResponseMeta } from '../types'\n\n/** Maximum single frame payload (64 MiB). */\nexport const MAX_FRAME_BYTES = 64 * 1024 * 1024\n\ntype ByteWaiter = {\n length: number\n resolve: (buf: Buffer) => void\n reject: (err: Error) => void\n}\n\n/**\n * Per-stream byte buffer. HyperDHT duplexes do not reliably support `unshift`,\n * so we accumulate and slice locally instead of pushing leftovers back.\n */\nclass StreamByteReader {\n private buffer = Buffer.alloc(0)\n private waiters: ByteWaiter[] = []\n private ended = false\n private readonly onData: (chunk: Buffer) => void\n private readonly onError: (err: Error) => void\n private readonly onEnd: () => void\n\n constructor(private readonly stream: Readable) {\n this.onData = (chunk: Buffer) => {\n this.buffer = Buffer.concat([this.buffer, chunk])\n this.drain()\n }\n this.onError = (err: Error) => {\n const waiters = this.waiters.splice(0)\n for (const w of waiters) w.reject(err)\n }\n this.onEnd = () => {\n this.ended = true\n this.drain()\n if (this.waiters.length > 0) {\n const waiters = this.waiters.splice(0)\n for (const w of waiters) {\n w.reject(\n new Error(\n `Unexpected end of stream (expected ${w.length} bytes, got ${this.buffer.length})`,\n ),\n )\n }\n }\n }\n stream.on('data', this.onData)\n stream.on('error', this.onError)\n stream.on('end', this.onEnd)\n }\n\n readExact(length: number): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n if (length === 0) {\n resolve(Buffer.alloc(0))\n return\n }\n this.waiters.push({ length, resolve, reject })\n this.drain()\n if (this.ended && this.waiters.length > 0) {\n const waiters = this.waiters.splice(0)\n for (const w of waiters) {\n w.reject(\n new Error(\n `Unexpected end of stream (expected ${w.length} bytes, got ${this.buffer.length})`,\n ),\n )\n }\n }\n })\n }\n\n private drain(): void {\n while (this.waiters.length > 0) {\n const next = this.waiters[0]\n if (!next || this.buffer.length < next.length) break\n this.waiters.shift()\n const out = this.buffer.subarray(0, next.length)\n this.buffer = this.buffer.subarray(next.length)\n next.resolve(out)\n }\n }\n}\n\nconst readers = new WeakMap<Readable, StreamByteReader>()\n\nfunction getReader(stream: Readable): StreamByteReader {\n let reader = readers.get(stream)\n if (!reader) {\n reader = new StreamByteReader(stream)\n readers.set(stream, reader)\n }\n return reader\n}\n\nfunction readExact(stream: Readable, length: number): Promise<Buffer> {\n return getReader(stream).readExact(length)\n}\n\nfunction writeBuffer(stream: Writable, buf: Buffer): Promise<void> {\n return new Promise((resolve, reject) => {\n // HyperDHT duplexes often never invoke write(callback). Use return value + drain.\n try {\n const ok = stream.write(buf)\n if (ok) {\n resolve()\n return\n }\n const onDrain = () => {\n stream.off('error', onError)\n resolve()\n }\n const onError = (err: Error) => {\n stream.off('drain', onDrain)\n reject(err)\n }\n stream.once('drain', onDrain)\n stream.once('error', onError)\n } catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n }\n })\n}\n\nexport async function writeFrame(stream: Writable, payload: Buffer): Promise<void> {\n if (payload.length > MAX_FRAME_BYTES) {\n throw new Error(`Frame too large: ${payload.length} bytes (max ${MAX_FRAME_BYTES})`)\n }\n const header = Buffer.alloc(4)\n header.writeUInt32BE(payload.length, 0)\n // Single write — HyperDHT can drop/stall subsequent writes in the same turn.\n await writeBuffer(stream, Buffer.concat([header, payload]))\n}\n\nexport async function readFrame(stream: Readable): Promise<Buffer> {\n const header = await readExact(stream, 4)\n const length = header.readUInt32BE(0)\n if (length === 0) {\n return Buffer.alloc(0)\n }\n if (length > MAX_FRAME_BYTES) {\n throw new Error(`Frame too large: ${length} bytes (max ${MAX_FRAME_BYTES})`)\n }\n return readExact(stream, length)\n}\n\nexport async function writeTunnelRequest(\n stream: Writable,\n meta: TunnelMeta,\n body: Buffer,\n): Promise<void> {\n const metaFrame = Buffer.from(JSON.stringify(meta), 'utf8')\n await writeFrame(stream, metaFrame)\n await writeFrame(stream, body)\n}\n\nexport async function readTunnelRequest(\n stream: Readable,\n): Promise<{ meta: TunnelMeta; body: Buffer }> {\n const metaBuf = await readFrame(stream)\n const meta = JSON.parse(metaBuf.toString('utf8')) as TunnelMeta\n if (!meta.method || !meta.path) {\n throw new Error('Invalid tunnel request meta: missing method or path')\n }\n meta.headers = meta.headers ?? {}\n const body = await readFrame(stream)\n return { meta, body }\n}\n\nexport async function writeTunnelResponse(\n stream: Writable,\n meta: TunnelResponseMeta,\n body: Buffer,\n): Promise<void> {\n const metaFrame = Buffer.from(JSON.stringify(meta), 'utf8')\n await writeFrame(stream, metaFrame)\n await writeFrame(stream, body)\n}\n\nexport async function readTunnelResponse(\n stream: Readable,\n): Promise<{ meta: TunnelResponseMeta; body: Buffer }> {\n const metaBuf = await readFrame(stream)\n const meta = JSON.parse(metaBuf.toString('utf8')) as TunnelResponseMeta\n if (typeof meta.status !== 'number') {\n throw new Error('Invalid tunnel response meta: missing status')\n }\n meta.headers = meta.headers ?? {}\n const body = await readFrame(stream)\n return { meta, body }\n}\n\n/** Normalize header values to strings for tunnel transport. */\nexport function flattenRequestHeaders(\n headers: Record<string, string | string[] | undefined>,\n): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [key, value] of Object.entries(headers)) {\n if (value == null) continue\n out[key] = Array.isArray(value) ? value.join(', ') : value\n }\n return out\n}\n\n/** Pick response headers safe to forward to the local HTTP client. */\nexport function filterResponseHeaders(\n headers: Record<string, string | string[] | undefined>,\n): Record<string, string> {\n const skip = new Set([\n 'connection',\n 'keep-alive',\n 'transfer-encoding',\n 'upgrade',\n ])\n const out: Record<string, string> = {}\n for (const [key, value] of Object.entries(headers)) {\n if (skip.has(key.toLowerCase())) continue\n if (value == null) continue\n out[key] = Array.isArray(value) ? value.join(', ') : value\n }\n return out\n}\n","import http from 'node:http'\nimport { URL } from 'node:url'\nimport { filterResponseHeaders } from './protocol'\nimport type { TunnelMeta } from '../types'\n\nexport async function proxyTunnelRequest(\n upstreamBase: string,\n meta: TunnelMeta,\n body: Buffer,\n): Promise<{ status: number; headers: Record<string, string>; body: Buffer }> {\n const base = upstreamBase.replace(/\\/$/, '')\n const targetUrl = new URL(meta.path, `${base}/`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n targetUrl,\n {\n method: meta.method,\n headers: meta.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (chunk: Buffer) => chunks.push(chunk))\n res.on('end', () => {\n resolve({\n status: res.statusCode ?? 502,\n headers: filterResponseHeaders(res.headers as Record<string, string | string[] | undefined>),\n body: Buffer.concat(chunks),\n })\n })\n res.on('error', reject)\n },\n )\n req.on('error', reject)\n if (body.length > 0) {\n req.write(body)\n }\n req.end()\n })\n}\n","import type { Duplex } from 'node:stream'\nimport HyperDHT from 'hyperdht'\nimport { readTunnelRequest, writeTunnelResponse } from './protocol'\nimport { proxyTunnelRequest } from './proxy'\nimport { loadOrCreateOperatorKeypair } from '../keys'\nimport type { ServeTunnelOptions, ServeTunnelResult } from '../types'\n\nfunction handleConnection(\n socket: Duplex,\n upstream: string,\n): void {\n // Attach framed readers synchronously so HyperDHT early bytes are not lost.\n let pendingRequest = readTunnelRequest(socket)\n void (async () => {\n try {\n while (true) {\n const { meta, body } = await pendingRequest\n const result = await proxyTunnelRequest(upstream, meta, body)\n await writeTunnelResponse(\n socket,\n { status: result.status, headers: result.headers },\n result.body,\n )\n pendingRequest = readTunnelRequest(socket)\n }\n } catch {\n socket.destroy()\n }\n })()\n}\n\n/**\n * Operator: accept Hyperswarm/DHT connections and proxy framed HTTP to upstream Traefik.\n */\nexport async function serveTunnel(options: ServeTunnelOptions): Promise<ServeTunnelResult> {\n const upstream = options.upstream.replace(/\\/$/, '')\n const keyFile = options.keyFile ?? '.seed/gateway-tunnel/operator.key.json'\n const keypair = loadOrCreateOperatorKeypair(keyFile)\n\n const dht = new HyperDHT()\n const server = dht.createServer((socket) => {\n handleConnection(socket as Duplex, upstream)\n })\n\n await server.listen(keypair)\n\n return {\n key: keypair.z32,\n upstream,\n close: async () => {\n await server.close()\n await dht.destroy()\n },\n }\n}\n","import type { Duplex } from 'node:stream'\nimport HyperDHT from 'hyperdht'\nimport { createEphemeralClientKeypair, decodePublicKey } from '../keys'\nimport type { TunnelMeta, TunnelResponseMeta } from '../types'\nimport { readTunnelResponse, writeTunnelRequest } from './protocol'\n\nexport type TunnelSessionOptions = {\n /** Operator public key (z32 or hex) */\n key: string\n /** Optional store path for DHT client state */\n storePath?: string\n}\n\nexport type TunnelSession = {\n key: string\n runOnTunnel: <T>(fn: (socket: Duplex) => Promise<T>) => Promise<T>\n forwardHttp: (\n meta: TunnelMeta,\n body: Buffer,\n ) => Promise<{ meta: TunnelResponseMeta; body: Buffer }>\n close: () => Promise<void>\n}\n\n/**\n * Dial the operator HyperDHT key and expose a serialized request/response forwarder.\n */\nexport async function createTunnelSession(options: TunnelSessionOptions): Promise<TunnelSession> {\n const remotePublicKey = decodePublicKey(options.key)\n const clientKey = createEphemeralClientKeypair()\n\n const dht = new HyperDHT()\n let activeSocket: Duplex | null = null\n let connecting: Promise<Duplex> | null = null\n\n const getSocket = async (): Promise<Duplex> => {\n if (activeSocket && !activeSocket.destroyed) {\n return activeSocket\n }\n if (connecting) {\n return connecting\n }\n connecting = new Promise<Duplex>((resolve, reject) => {\n const socket = dht.connect(remotePublicKey, {\n keyPair: { publicKey: clientKey.publicKey, secretKey: clientKey.secretKey },\n }) as Duplex\n const onReady = () => {\n activeSocket = socket\n connecting = null\n resolve(socket)\n }\n socket.once('open', onReady)\n socket.once('connect', onReady)\n socket.once('error', (err: Error) => {\n connecting = null\n reject(err)\n })\n })\n return connecting\n }\n\n /** Serialize tunnel transactions on one persistent socket. */\n let tunnelQueue: Promise<unknown> = Promise.resolve()\n const runOnTunnel = async <T>(fn: (socket: Duplex) => Promise<T>): Promise<T> => {\n const run = tunnelQueue.then(() => getSocket()).then(fn)\n tunnelQueue = run.catch(() => {})\n return run\n }\n\n const forwardHttp = async (\n meta: TunnelMeta,\n body: Buffer,\n ): Promise<{ meta: TunnelResponseMeta; body: Buffer }> => {\n return runOnTunnel(async (socket) => {\n await writeTunnelRequest(socket, meta, body)\n return readTunnelResponse(socket)\n })\n }\n\n return {\n key: options.key,\n runOnTunnel,\n forwardHttp,\n close: async () => {\n if (activeSocket && !activeSocket.destroyed) {\n activeSocket.destroy()\n }\n await dht.destroy()\n },\n }\n}\n","import http from 'node:http'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport {\n flattenRequestHeaders,\n} from './protocol'\nimport { createTunnelSession } from './session'\nimport type { ConnectTunnelOptions, ConnectTunnelResult } from '../types'\n\nasync function readRequestBody(req: IncomingMessage): Promise<Buffer> {\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))\n }\n return Buffer.concat(chunks)\n}\n\nfunction createLocalServer(\n forwardHttp: (\n meta: { method: string; path: string; headers: Record<string, string> },\n body: Buffer,\n ) => Promise<{ meta: { status: number; headers: Record<string, string> }; body: Buffer }>,\n): http.Server {\n return http.createServer((req, res) => {\n void (async () => {\n try {\n const body = await readRequestBody(req)\n const path = req.url ?? '/'\n const meta = {\n method: req.method ?? 'GET',\n path,\n headers: flattenRequestHeaders(req.headers as Record<string, string | string[] | undefined>),\n }\n\n const { meta: responseMeta, body: responseBody } = await forwardHttp(meta, body)\n\n res.writeHead(responseMeta.status, responseMeta.headers)\n res.end(responseBody)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' })\n }\n res.end(`Gateway Hyper tunnel error: ${message}`)\n }\n })()\n })\n}\n\n/**\n * Client: dial operator key and expose a localhost HTTP server that forwards through the tunnel.\n */\nexport async function connectTunnel(options: ConnectTunnelOptions): Promise<ConnectTunnelResult> {\n const host = options.host ?? '127.0.0.1'\n const port = options.port ?? 1984\n\n const session = await createTunnelSession({\n key: options.key,\n storePath: options.storePath,\n })\n\n const server = createLocalServer((meta, body) => session.forwardHttp(meta, body))\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, host, () => resolve())\n })\n\n const address = server.address()\n const boundPort =\n address && typeof address === 'object' ? address.port : port\n\n const baseUrl = `http://${host}:${boundPort}`\n\n return {\n key: options.key,\n host,\n port: boundPort,\n baseUrl,\n close: async () => {\n await new Promise<void>((resolve) => server.close(() => resolve()))\n await session.close()\n },\n }\n}\n\nexport function localGatewayUrl(baseUrl: string, path = ''): string {\n const base = baseUrl.replace(/\\/$/, '')\n if (!path) return base\n return path.startsWith('/') ? `${base}${path}` : `${base}/${path}`\n}\n","/**\n * Strip a mount path prefix from an incoming request URL path (including query string).\n * If the path is already unmounted (framework stripped it), returns it unchanged (with leading `/`).\n */\nexport function stripMountPath(urlPath: string, mountPath: string): string {\n const raw = urlPath || '/'\n const qIndex = raw.indexOf('?')\n const pathname = qIndex === -1 ? raw : raw.slice(0, qIndex)\n const query = qIndex === -1 ? '' : raw.slice(qIndex)\n\n const mount = (mountPath || '').replace(/\\/$/, '')\n if (!mount || mount === '/') {\n const path = pathname.startsWith('/') ? pathname : `/${pathname}`\n return `${path}${query}` || '/'\n }\n\n if (pathname === mount || pathname.startsWith(`${mount}/`)) {\n const rest = pathname.slice(mount.length)\n const path = rest.startsWith('/') ? rest : rest ? `/${rest}` : '/'\n return `${path}${query}`\n }\n\n // Already stripped by the framework (e.g. Express mount)\n const path = pathname.startsWith('/') ? pathname : `/${pathname}`\n return `${path}${query}`\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport {\n filterResponseHeaders,\n flattenRequestHeaders,\n} from './protocol'\nimport { stripMountPath } from './mountPath'\nimport type { TunnelSession } from './session'\nimport type { TunnelMeta, TunnelResponseMeta } from '../types'\n\nasync function readNodeBody(req: IncomingMessage): Promise<Buffer> {\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))\n }\n return Buffer.concat(chunks)\n}\n\nexport async function forwardNodeRequest(\n session: TunnelSession,\n req: IncomingMessage,\n res: ServerResponse,\n mountPath: string,\n): Promise<void> {\n try {\n const body = await readNodeBody(req)\n const path = stripMountPath(req.url ?? '/', mountPath)\n const meta: TunnelMeta = {\n method: req.method ?? 'GET',\n path,\n headers: flattenRequestHeaders(req.headers as Record<string, string | string[] | undefined>),\n }\n const { meta: responseMeta, body: responseBody } = await session.forwardHttp(meta, body)\n writeNodeResponse(res, responseMeta, responseBody)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' })\n }\n res.end(`Gateway Hyper tunnel error: ${message}`)\n }\n}\n\nfunction writeNodeResponse(\n res: ServerResponse,\n meta: TunnelResponseMeta,\n body: Buffer,\n): void {\n res.writeHead(meta.status, filterResponseHeaders(meta.headers))\n res.end(body)\n}\n\nexport async function forwardFetchRequest(\n session: TunnelSession,\n request: Request,\n mountPath: string,\n): Promise<Response> {\n try {\n const url = new URL(request.url)\n const path = stripMountPath(`${url.pathname}${url.search}`, mountPath)\n const bodyBuf = Buffer.from(await request.arrayBuffer())\n const headerRecord: Record<string, string> = {}\n request.headers.forEach((value, key) => {\n headerRecord[key] = value\n })\n const meta: TunnelMeta = {\n method: request.method || 'GET',\n path,\n headers: flattenRequestHeaders(headerRecord),\n }\n const { meta: responseMeta, body: responseBody } = await session.forwardHttp(meta, bodyBuf)\n return new Response(responseBody, {\n status: responseMeta.status,\n headers: filterResponseHeaders(responseMeta.headers),\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n return new Response(`Gateway Hyper tunnel error: ${message}`, {\n status: 502,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { createTunnelSession, type TunnelSession } from './session'\nimport { forwardFetchRequest, forwardNodeRequest } from './forward'\nimport type { CreateGatewayProxyOptions, GatewayProxy } from '../types'\n\nfunction resolveProxyKey(options: CreateGatewayProxyOptions): string {\n const key =\n options.key?.trim() ||\n (typeof process !== 'undefined' ? process.env.SEED_GATEWAY_HYPER_KEY?.trim() : '') ||\n ''\n if (!key) {\n throw new Error(\n 'createGatewayProxy requires options.key or SEED_GATEWAY_HYPER_KEY environment variable',\n )\n }\n return key\n}\n\n/**\n * App-server Hyper gateway proxy for hosted web apps (Path B).\n *\n * Mount on a Node route (Next.js Node runtime, Express, etc.). Keep the operator\n * Hyper key on the server only — browsers talk HTTP to `proxyBaseUrl`.\n *\n * Prefer Node.js over Bun for Holepunch natives.\n */\nexport function createGatewayProxy(options: CreateGatewayProxyOptions = {}): GatewayProxy {\n const mountPath = options.mountPath?.trim() || '/api/seed-gateway'\n const key = resolveProxyKey(options)\n\n let session: TunnelSession | null = null\n let starting: Promise<TunnelSession> | null = null\n\n const ensureSession = async (): Promise<TunnelSession> => {\n if (session) return session\n if (starting) return starting\n starting = createTunnelSession({ key, storePath: options.storePath }).then((s) => {\n session = s\n starting = null\n return s\n })\n try {\n return await starting\n } catch (err) {\n starting = null\n throw err\n }\n }\n\n const proxy: GatewayProxy = {\n mountPath,\n start: async () => {\n await ensureSession()\n },\n close: async () => {\n if (starting) {\n try {\n await starting\n } catch {\n /* ignore start failure during close */\n }\n }\n if (session) {\n await session.close()\n session = null\n }\n },\n handleNode: (req: IncomingMessage, res: ServerResponse) => {\n void (async () => {\n try {\n const s = await ensureSession()\n await forwardNodeRequest(s, req, res, mountPath)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' })\n }\n res.end(`Gateway Hyper tunnel error: ${message}`)\n }\n })()\n },\n handleFetch: async (request: Request): Promise<Response> => {\n try {\n const s = await ensureSession()\n return await forwardFetchRequest(s, request, mountPath)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n return new Response(`Gateway Hyper tunnel error: ${message}`, {\n status: 502,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n },\n }\n\n if (options.eager) {\n void proxy.start().catch(() => {\n /* first request will surface the error */\n })\n }\n\n return proxy\n}\n","/**\n * Official Seed Protocol gateway Hyper tunnel operator key (z32).\n * Empty until ops generate and back up the first operator keypair.\n */\nexport const DEFAULT_SEED_GATEWAY_HYPER_KEY = ''\n"],"mappings":"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"}
1
+ {"version":3,"file":"src-CnXam5V8.js","names":["URL","fs","path","HyperDHT","ID","http","URL$1","toHex","buf","fromHex","hex","encodePublicKeyZ32","publicKey","decodePublicKey","trimmed","key","loadOrCreateOperatorKeypair","resolved","keyFile","raw","parsed","dir","kp","persisted","createEphemeralClientKeypair","MAX_FRAME_BYTES","StreamByteReader","stream","chunk","waiters","w","err","length","next","out","readers","getReader","reader","readExact","writeBuffer","onDrain","onError","resolve","reject","writeFrame","payload","header","readFrame","writeTunnelRequest","meta","body","readTunnelRequest","metaBuf","writeTunnelResponse","readTunnelResponse","flattenRequestHeaders","value","headers","filterResponseHeaders","skip","proxyTunnelRequest","base","upstreamBase","targetUrl","req","chunks","res","handleConnection","pendingRequest","socket","result","upstream","serveTunnel","options","keypair","dht","server","createTunnelSession","remotePublicKey","clientKey","activeSocket","connecting","getSocket","onReady","tunnelQueue","runOnTunnel","run","fn","readRequestBody","createLocalServer","responseMeta","responseBody","forwardHttp","message","connectTunnel","host","port","session","address","boundPort","baseUrl","localGatewayUrl","stripMountPath","urlPath","qIndex","pathname","query","mount","mountPath","rest","readNodeBody","forwardNodeRequest","writeNodeResponse","forwardFetchRequest","url","request","bodyBuf","headerRecord","resolveProxyKey","createGatewayProxy","starting","ensureSession","s","proxy","DEFAULT_SEED_GATEWAY_HYPER_KEY"],"sources":["../src/keys.ts","../src/tunnel/protocol.ts","../src/tunnel/proxy.ts","../src/tunnel/serve.ts","../src/tunnel/session.ts","../src/tunnel/connect.ts","../src/tunnel/mountPath.ts","../src/tunnel/forward.ts","../src/tunnel/proxyApp.ts","../src/constants.ts"],"sourcesContent":["import fs from 'node:fs'\nimport path from 'node:path'\nimport HyperDHT from 'hyperdht'\nimport ID from 'hypercore-id-encoding'\nimport type { OperatorKeyPair } from './types'\n\nexport interface PersistedKeyFile {\n publicKey: string\n secretKey: string\n encoding: 'hex'\n}\n\nfunction toHex(buf: Buffer): string {\n return buf.toString('hex')\n}\n\nfunction fromHex(hex: string): Buffer {\n return Buffer.from(hex, 'hex')\n}\n\nexport function encodePublicKeyZ32(publicKey: Buffer): string {\n return ID.encode(publicKey)\n}\n\nexport function decodePublicKey(key: string): Buffer {\n const trimmed = key.trim()\n if (!trimmed) {\n throw new Error('Gateway Hyper key is empty')\n }\n try {\n return Buffer.from(ID.decode(trimmed))\n } catch {\n if (/^[a-fA-F0-9]{64}$/.test(trimmed)) {\n return fromHex(trimmed)\n }\n throw new Error(`Invalid Gateway Hyper key (expected z32 or 64-char hex): ${trimmed.slice(0, 12)}…`)\n }\n}\n\nexport function loadOrCreateOperatorKeypair(keyFile: string): OperatorKeyPair {\n const resolved = path.resolve(keyFile)\n if (fs.existsSync(resolved)) {\n const raw = fs.readFileSync(resolved, 'utf8')\n const parsed = JSON.parse(raw) as PersistedKeyFile\n if (!parsed.publicKey || !parsed.secretKey) {\n throw new Error(`Invalid key file at ${resolved}: missing publicKey or secretKey`)\n }\n const publicKey = fromHex(parsed.publicKey)\n const secretKey = fromHex(parsed.secretKey)\n return {\n publicKey,\n secretKey,\n z32: encodePublicKeyZ32(publicKey),\n }\n }\n\n const dir = path.dirname(resolved)\n fs.mkdirSync(dir, { recursive: true })\n const kp = HyperDHT.keyPair()\n const persisted: PersistedKeyFile = {\n publicKey: toHex(kp.publicKey),\n secretKey: toHex(kp.secretKey),\n encoding: 'hex',\n }\n fs.writeFileSync(resolved, `${JSON.stringify(persisted, null, 2)}\\n`, { mode: 0o600 })\n return {\n publicKey: kp.publicKey,\n secretKey: kp.secretKey,\n z32: encodePublicKeyZ32(kp.publicKey),\n }\n}\n\nexport function createEphemeralClientKeypair(): OperatorKeyPair {\n const kp = HyperDHT.keyPair()\n return {\n publicKey: kp.publicKey,\n secretKey: kp.secretKey,\n z32: encodePublicKeyZ32(kp.publicKey),\n }\n}\n","import type { Readable, Writable } from 'node:stream'\nimport type { TunnelMeta, TunnelResponseMeta } from '../types'\n\n/** Maximum single frame payload (64 MiB). */\nexport const MAX_FRAME_BYTES = 64 * 1024 * 1024\n\ntype ByteWaiter = {\n length: number\n resolve: (buf: Buffer) => void\n reject: (err: Error) => void\n}\n\n/**\n * Per-stream byte buffer. HyperDHT duplexes do not reliably support `unshift`,\n * so we accumulate and slice locally instead of pushing leftovers back.\n */\nclass StreamByteReader {\n private buffer = Buffer.alloc(0)\n private waiters: ByteWaiter[] = []\n private ended = false\n private readonly onData: (chunk: Buffer) => void\n private readonly onError: (err: Error) => void\n private readonly onEnd: () => void\n\n constructor(private readonly stream: Readable) {\n this.onData = (chunk: Buffer) => {\n this.buffer = Buffer.concat([this.buffer, chunk])\n this.drain()\n }\n this.onError = (err: Error) => {\n const waiters = this.waiters.splice(0)\n for (const w of waiters) w.reject(err)\n }\n this.onEnd = () => {\n this.ended = true\n this.drain()\n if (this.waiters.length > 0) {\n const waiters = this.waiters.splice(0)\n for (const w of waiters) {\n w.reject(\n new Error(\n `Unexpected end of stream (expected ${w.length} bytes, got ${this.buffer.length})`,\n ),\n )\n }\n }\n }\n stream.on('data', this.onData)\n stream.on('error', this.onError)\n stream.on('end', this.onEnd)\n }\n\n readExact(length: number): Promise<Buffer> {\n return new Promise((resolve, reject) => {\n if (length === 0) {\n resolve(Buffer.alloc(0))\n return\n }\n this.waiters.push({ length, resolve, reject })\n this.drain()\n if (this.ended && this.waiters.length > 0) {\n const waiters = this.waiters.splice(0)\n for (const w of waiters) {\n w.reject(\n new Error(\n `Unexpected end of stream (expected ${w.length} bytes, got ${this.buffer.length})`,\n ),\n )\n }\n }\n })\n }\n\n private drain(): void {\n while (this.waiters.length > 0) {\n const next = this.waiters[0]\n if (!next || this.buffer.length < next.length) break\n this.waiters.shift()\n const out = this.buffer.subarray(0, next.length)\n this.buffer = this.buffer.subarray(next.length)\n next.resolve(out)\n }\n }\n}\n\nconst readers = new WeakMap<Readable, StreamByteReader>()\n\nfunction getReader(stream: Readable): StreamByteReader {\n let reader = readers.get(stream)\n if (!reader) {\n reader = new StreamByteReader(stream)\n readers.set(stream, reader)\n }\n return reader\n}\n\nfunction readExact(stream: Readable, length: number): Promise<Buffer> {\n return getReader(stream).readExact(length)\n}\n\nfunction writeBuffer(stream: Writable, buf: Buffer): Promise<void> {\n return new Promise((resolve, reject) => {\n // HyperDHT duplexes often never invoke write(callback). Use return value + drain.\n try {\n const ok = stream.write(buf)\n if (ok) {\n resolve()\n return\n }\n const onDrain = () => {\n stream.off('error', onError)\n resolve()\n }\n const onError = (err: Error) => {\n stream.off('drain', onDrain)\n reject(err)\n }\n stream.once('drain', onDrain)\n stream.once('error', onError)\n } catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n }\n })\n}\n\nexport async function writeFrame(stream: Writable, payload: Buffer): Promise<void> {\n if (payload.length > MAX_FRAME_BYTES) {\n throw new Error(`Frame too large: ${payload.length} bytes (max ${MAX_FRAME_BYTES})`)\n }\n const header = Buffer.alloc(4)\n header.writeUInt32BE(payload.length, 0)\n // Single write — HyperDHT can drop/stall subsequent writes in the same turn.\n await writeBuffer(stream, Buffer.concat([header, payload]))\n}\n\nexport async function readFrame(stream: Readable): Promise<Buffer> {\n const header = await readExact(stream, 4)\n const length = header.readUInt32BE(0)\n if (length === 0) {\n return Buffer.alloc(0)\n }\n if (length > MAX_FRAME_BYTES) {\n throw new Error(`Frame too large: ${length} bytes (max ${MAX_FRAME_BYTES})`)\n }\n return readExact(stream, length)\n}\n\nexport async function writeTunnelRequest(\n stream: Writable,\n meta: TunnelMeta,\n body: Buffer,\n): Promise<void> {\n const metaFrame = Buffer.from(JSON.stringify(meta), 'utf8')\n await writeFrame(stream, metaFrame)\n await writeFrame(stream, body)\n}\n\nexport async function readTunnelRequest(\n stream: Readable,\n): Promise<{ meta: TunnelMeta; body: Buffer }> {\n const metaBuf = await readFrame(stream)\n const meta = JSON.parse(metaBuf.toString('utf8')) as TunnelMeta\n if (!meta.method || !meta.path) {\n throw new Error('Invalid tunnel request meta: missing method or path')\n }\n meta.headers = meta.headers ?? {}\n const body = await readFrame(stream)\n return { meta, body }\n}\n\nexport async function writeTunnelResponse(\n stream: Writable,\n meta: TunnelResponseMeta,\n body: Buffer,\n): Promise<void> {\n const metaFrame = Buffer.from(JSON.stringify(meta), 'utf8')\n await writeFrame(stream, metaFrame)\n await writeFrame(stream, body)\n}\n\nexport async function readTunnelResponse(\n stream: Readable,\n): Promise<{ meta: TunnelResponseMeta; body: Buffer }> {\n const metaBuf = await readFrame(stream)\n const meta = JSON.parse(metaBuf.toString('utf8')) as TunnelResponseMeta\n if (typeof meta.status !== 'number') {\n throw new Error('Invalid tunnel response meta: missing status')\n }\n meta.headers = meta.headers ?? {}\n const body = await readFrame(stream)\n return { meta, body }\n}\n\n/** Normalize header values to strings for tunnel transport. */\nexport function flattenRequestHeaders(\n headers: Record<string, string | string[] | undefined>,\n): Record<string, string> {\n const out: Record<string, string> = {}\n for (const [key, value] of Object.entries(headers)) {\n if (value == null) continue\n out[key] = Array.isArray(value) ? value.join(', ') : value\n }\n return out\n}\n\n/** Pick response headers safe to forward to the local HTTP client. */\nexport function filterResponseHeaders(\n headers: Record<string, string | string[] | undefined>,\n): Record<string, string> {\n const skip = new Set([\n 'connection',\n 'keep-alive',\n 'transfer-encoding',\n 'upgrade',\n ])\n const out: Record<string, string> = {}\n for (const [key, value] of Object.entries(headers)) {\n if (skip.has(key.toLowerCase())) continue\n if (value == null) continue\n out[key] = Array.isArray(value) ? value.join(', ') : value\n }\n return out\n}\n","import http from 'node:http'\nimport { URL } from 'node:url'\nimport { filterResponseHeaders } from './protocol'\nimport type { TunnelMeta } from '../types'\n\nexport async function proxyTunnelRequest(\n upstreamBase: string,\n meta: TunnelMeta,\n body: Buffer,\n): Promise<{ status: number; headers: Record<string, string>; body: Buffer }> {\n const base = upstreamBase.replace(/\\/$/, '')\n const targetUrl = new URL(meta.path, `${base}/`)\n\n return new Promise((resolve, reject) => {\n const req = http.request(\n targetUrl,\n {\n method: meta.method,\n headers: meta.headers,\n },\n (res) => {\n const chunks: Buffer[] = []\n res.on('data', (chunk: Buffer) => chunks.push(chunk))\n res.on('end', () => {\n resolve({\n status: res.statusCode ?? 502,\n headers: filterResponseHeaders(res.headers as Record<string, string | string[] | undefined>),\n body: Buffer.concat(chunks),\n })\n })\n res.on('error', reject)\n },\n )\n req.on('error', reject)\n if (body.length > 0) {\n req.write(body)\n }\n req.end()\n })\n}\n","import type { Duplex } from 'node:stream'\nimport HyperDHT from 'hyperdht'\nimport { readTunnelRequest, writeTunnelResponse } from './protocol'\nimport { proxyTunnelRequest } from './proxy'\nimport { loadOrCreateOperatorKeypair } from '../keys'\nimport type { ServeTunnelOptions, ServeTunnelResult } from '../types'\n\nfunction handleConnection(\n socket: Duplex,\n upstream: string,\n): void {\n // Attach framed readers synchronously so HyperDHT early bytes are not lost.\n let pendingRequest = readTunnelRequest(socket)\n void (async () => {\n try {\n while (true) {\n const { meta, body } = await pendingRequest\n const result = await proxyTunnelRequest(upstream, meta, body)\n await writeTunnelResponse(\n socket,\n { status: result.status, headers: result.headers },\n result.body,\n )\n pendingRequest = readTunnelRequest(socket)\n }\n } catch {\n socket.destroy()\n }\n })()\n}\n\n/**\n * Operator: accept Hyperswarm/DHT connections and proxy framed HTTP to upstream Traefik.\n */\nexport async function serveTunnel(options: ServeTunnelOptions): Promise<ServeTunnelResult> {\n const upstream = options.upstream.replace(/\\/$/, '')\n const keyFile = options.keyFile ?? '.seed/gateway-tunnel/operator.key.json'\n const keypair = loadOrCreateOperatorKeypair(keyFile)\n\n const dht = new HyperDHT()\n const server = dht.createServer((socket) => {\n handleConnection(socket as Duplex, upstream)\n })\n\n await server.listen(keypair)\n\n return {\n key: keypair.z32,\n upstream,\n close: async () => {\n await server.close()\n await dht.destroy()\n },\n }\n}\n","import type { Duplex } from 'node:stream'\nimport HyperDHT from 'hyperdht'\nimport { createEphemeralClientKeypair, decodePublicKey } from '../keys'\nimport type { TunnelMeta, TunnelResponseMeta } from '../types'\nimport { readTunnelResponse, writeTunnelRequest } from './protocol'\n\nexport type TunnelSessionOptions = {\n /** Operator public key (z32 or hex) */\n key: string\n /** Optional store path for DHT client state */\n storePath?: string\n}\n\nexport type TunnelSession = {\n key: string\n runOnTunnel: <T>(fn: (socket: Duplex) => Promise<T>) => Promise<T>\n forwardHttp: (\n meta: TunnelMeta,\n body: Buffer,\n ) => Promise<{ meta: TunnelResponseMeta; body: Buffer }>\n close: () => Promise<void>\n}\n\n/**\n * Dial the operator HyperDHT key and expose a serialized request/response forwarder.\n */\nexport async function createTunnelSession(options: TunnelSessionOptions): Promise<TunnelSession> {\n const remotePublicKey = decodePublicKey(options.key)\n const clientKey = createEphemeralClientKeypair()\n\n const dht = new HyperDHT()\n let activeSocket: Duplex | null = null\n let connecting: Promise<Duplex> | null = null\n\n const getSocket = async (): Promise<Duplex> => {\n if (activeSocket && !activeSocket.destroyed) {\n return activeSocket\n }\n if (connecting) {\n return connecting\n }\n connecting = new Promise<Duplex>((resolve, reject) => {\n const socket = dht.connect(remotePublicKey, {\n keyPair: { publicKey: clientKey.publicKey, secretKey: clientKey.secretKey },\n }) as Duplex\n const onReady = () => {\n activeSocket = socket\n connecting = null\n resolve(socket)\n }\n socket.once('open', onReady)\n socket.once('connect', onReady)\n socket.once('error', (err: Error) => {\n connecting = null\n reject(err)\n })\n })\n return connecting\n }\n\n /** Serialize tunnel transactions on one persistent socket. */\n let tunnelQueue: Promise<unknown> = Promise.resolve()\n const runOnTunnel = async <T>(fn: (socket: Duplex) => Promise<T>): Promise<T> => {\n const run = tunnelQueue.then(() => getSocket()).then(fn)\n tunnelQueue = run.catch(() => {})\n return run\n }\n\n const forwardHttp = async (\n meta: TunnelMeta,\n body: Buffer,\n ): Promise<{ meta: TunnelResponseMeta; body: Buffer }> => {\n return runOnTunnel(async (socket) => {\n await writeTunnelRequest(socket, meta, body)\n return readTunnelResponse(socket)\n })\n }\n\n return {\n key: options.key,\n runOnTunnel,\n forwardHttp,\n close: async () => {\n if (activeSocket && !activeSocket.destroyed) {\n activeSocket.destroy()\n }\n await dht.destroy()\n },\n }\n}\n","import http from 'node:http'\nimport type { IncomingMessage, ServerResponse } from 'node:http'\nimport {\n flattenRequestHeaders,\n} from './protocol'\nimport { createTunnelSession } from './session'\nimport type { ConnectTunnelOptions, ConnectTunnelResult } from '../types'\n\nasync function readRequestBody(req: IncomingMessage): Promise<Buffer> {\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))\n }\n return Buffer.concat(chunks)\n}\n\nfunction createLocalServer(\n forwardHttp: (\n meta: { method: string; path: string; headers: Record<string, string> },\n body: Buffer,\n ) => Promise<{ meta: { status: number; headers: Record<string, string> }; body: Buffer }>,\n): http.Server {\n return http.createServer((req, res) => {\n void (async () => {\n try {\n const body = await readRequestBody(req)\n const path = req.url ?? '/'\n const meta = {\n method: req.method ?? 'GET',\n path,\n headers: flattenRequestHeaders(req.headers as Record<string, string | string[] | undefined>),\n }\n\n const { meta: responseMeta, body: responseBody } = await forwardHttp(meta, body)\n\n res.writeHead(responseMeta.status, responseMeta.headers)\n res.end(responseBody)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' })\n }\n res.end(`Gateway Hyper tunnel error: ${message}`)\n }\n })()\n })\n}\n\n/**\n * Client: dial operator key and expose a localhost HTTP server that forwards through the tunnel.\n */\nexport async function connectTunnel(options: ConnectTunnelOptions): Promise<ConnectTunnelResult> {\n const host = options.host ?? '127.0.0.1'\n const port = options.port ?? 1984\n\n const session = await createTunnelSession({\n key: options.key,\n storePath: options.storePath,\n })\n\n const server = createLocalServer((meta, body) => session.forwardHttp(meta, body))\n\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject)\n server.listen(port, host, () => resolve())\n })\n\n const address = server.address()\n const boundPort =\n address && typeof address === 'object' ? address.port : port\n\n const baseUrl = `http://${host}:${boundPort}`\n\n return {\n key: options.key,\n host,\n port: boundPort,\n baseUrl,\n close: async () => {\n await new Promise<void>((resolve) => server.close(() => resolve()))\n await session.close()\n },\n }\n}\n\nexport function localGatewayUrl(baseUrl: string, path = ''): string {\n const base = baseUrl.replace(/\\/$/, '')\n if (!path) return base\n return path.startsWith('/') ? `${base}${path}` : `${base}/${path}`\n}\n","/**\n * Strip a mount path prefix from an incoming request URL path (including query string).\n * If the path is already unmounted (framework stripped it), returns it unchanged (with leading `/`).\n */\nexport function stripMountPath(urlPath: string, mountPath: string): string {\n const raw = urlPath || '/'\n const qIndex = raw.indexOf('?')\n const pathname = qIndex === -1 ? raw : raw.slice(0, qIndex)\n const query = qIndex === -1 ? '' : raw.slice(qIndex)\n\n const mount = (mountPath || '').replace(/\\/$/, '')\n if (!mount || mount === '/') {\n const path = pathname.startsWith('/') ? pathname : `/${pathname}`\n return `${path}${query}` || '/'\n }\n\n if (pathname === mount || pathname.startsWith(`${mount}/`)) {\n const rest = pathname.slice(mount.length)\n const path = rest.startsWith('/') ? rest : rest ? `/${rest}` : '/'\n return `${path}${query}`\n }\n\n // Already stripped by the framework (e.g. Express mount)\n const path = pathname.startsWith('/') ? pathname : `/${pathname}`\n return `${path}${query}`\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport {\n filterResponseHeaders,\n flattenRequestHeaders,\n} from './protocol'\nimport { stripMountPath } from './mountPath'\nimport type { TunnelSession } from './session'\nimport type { TunnelMeta, TunnelResponseMeta } from '../types'\n\nasync function readNodeBody(req: IncomingMessage): Promise<Buffer> {\n const chunks: Buffer[] = []\n for await (const chunk of req) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk))\n }\n return Buffer.concat(chunks)\n}\n\nexport async function forwardNodeRequest(\n session: TunnelSession,\n req: IncomingMessage,\n res: ServerResponse,\n mountPath: string,\n): Promise<void> {\n try {\n const body = await readNodeBody(req)\n const path = stripMountPath(req.url ?? '/', mountPath)\n const meta: TunnelMeta = {\n method: req.method ?? 'GET',\n path,\n headers: flattenRequestHeaders(req.headers as Record<string, string | string[] | undefined>),\n }\n const { meta: responseMeta, body: responseBody } = await session.forwardHttp(meta, body)\n writeNodeResponse(res, responseMeta, responseBody)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' })\n }\n res.end(`Gateway Hyper tunnel error: ${message}`)\n }\n}\n\nfunction writeNodeResponse(\n res: ServerResponse,\n meta: TunnelResponseMeta,\n body: Buffer,\n): void {\n res.writeHead(meta.status, filterResponseHeaders(meta.headers))\n res.end(body)\n}\n\nexport async function forwardFetchRequest(\n session: TunnelSession,\n request: Request,\n mountPath: string,\n): Promise<Response> {\n try {\n const url = new URL(request.url)\n const path = stripMountPath(`${url.pathname}${url.search}`, mountPath)\n const bodyBuf = Buffer.from(await request.arrayBuffer())\n const headerRecord: Record<string, string> = {}\n request.headers.forEach((value, key) => {\n headerRecord[key] = value\n })\n const meta: TunnelMeta = {\n method: request.method || 'GET',\n path,\n headers: flattenRequestHeaders(headerRecord),\n }\n const { meta: responseMeta, body: responseBody } = await session.forwardHttp(meta, bodyBuf)\n return new Response(responseBody, {\n status: responseMeta.status,\n headers: filterResponseHeaders(responseMeta.headers),\n })\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n return new Response(`Gateway Hyper tunnel error: ${message}`, {\n status: 502,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n}\n","import type { IncomingMessage, ServerResponse } from 'node:http'\nimport { createTunnelSession, type TunnelSession } from './session'\nimport { forwardFetchRequest, forwardNodeRequest } from './forward'\nimport type { CreateGatewayProxyOptions, GatewayProxy } from '../types'\n\nfunction resolveProxyKey(options: CreateGatewayProxyOptions): string {\n const key =\n options.key?.trim() ||\n (typeof process !== 'undefined' ? process.env.SEED_GATEWAY_HYPER_KEY?.trim() : '') ||\n ''\n if (!key) {\n throw new Error(\n 'createGatewayProxy requires options.key or SEED_GATEWAY_HYPER_KEY environment variable',\n )\n }\n return key\n}\n\n/**\n * App-server Hyper gateway proxy for hosted web apps (Path B).\n *\n * Mount on a Node route (Next.js Node runtime, Express, etc.). Keep the operator\n * Hyper key on the server only — browsers talk HTTP to `proxyBaseUrl`.\n *\n * Prefer Node.js over Bun for Holepunch natives.\n */\nexport function createGatewayProxy(options: CreateGatewayProxyOptions = {}): GatewayProxy {\n const mountPath = options.mountPath?.trim() || '/api/seed-gateway'\n const key = resolveProxyKey(options)\n\n let session: TunnelSession | null = null\n let starting: Promise<TunnelSession> | null = null\n\n const ensureSession = async (): Promise<TunnelSession> => {\n if (session) return session\n if (starting) return starting\n starting = createTunnelSession({ key, storePath: options.storePath }).then((s) => {\n session = s\n starting = null\n return s\n })\n try {\n return await starting\n } catch (err) {\n starting = null\n throw err\n }\n }\n\n const proxy: GatewayProxy = {\n mountPath,\n start: async () => {\n await ensureSession()\n },\n close: async () => {\n if (starting) {\n try {\n await starting\n } catch {\n /* ignore start failure during close */\n }\n }\n if (session) {\n await session.close()\n session = null\n }\n },\n handleNode: (req: IncomingMessage, res: ServerResponse) => {\n void (async () => {\n try {\n const s = await ensureSession()\n await forwardNodeRequest(s, req, res, mountPath)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n if (!res.headersSent) {\n res.writeHead(502, { 'Content-Type': 'text/plain; charset=utf-8' })\n }\n res.end(`Gateway Hyper tunnel error: ${message}`)\n }\n })()\n },\n handleFetch: async (request: Request): Promise<Response> => {\n try {\n const s = await ensureSession()\n return await forwardFetchRequest(s, request, mountPath)\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err)\n return new Response(`Gateway Hyper tunnel error: ${message}`, {\n status: 502,\n headers: { 'Content-Type': 'text/plain; charset=utf-8' },\n })\n }\n },\n }\n\n if (options.eager) {\n void proxy.start().catch(() => {\n /* first request will surface the error */\n })\n }\n\n return proxy\n}\n","/**\n * Official Seed Protocol gateway Hyper tunnel operator key (z32).\n * Empty until ops generate and back up the first operator keypair.\n * Also defined in packages/arweave/src/constants.ts; keep both equal (gateway-hyper __tests__/constants.test.ts checks).\n */\nexport const DEFAULT_SEED_GATEWAY_HYPER_KEY = ''\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seedprotocol/gateway-hyper",
3
- "version": "0.7.4-next.711.gce2b766",
3
+ "version": "0.7.4-next.784.g879c6a3",
4
4
  "description": "Hyperswarm HTTP tunnel for Seed Protocol gateway + upload API infrastructure",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",