{"_id":"@bbk47/yamux","name":"@bbk47/yamux","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@bbk47/yamux","author":{"name":"bbk47"},"contributors":[{"name":"GPT-5.3-Codex","url":"original @llmcode/yamux-ts"}],"license":"ISC","version":"0.1.0","description":"Production-hardened Yamux multiplexer for Node.js (TypeScript), interoperable with hashicorp/yamux. Fork of @llmcode/yamux-ts with the unknown-stream session-teardown fix.","repository":{"type":"git","url":"git+https://github.com/bbk47/yamux.git"},"homepage":"https://github.com/bbk47/yamux#readme","bugs":{"url":"https://github.com/bbk47/yamux/issues"},"type":"module","main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs","require":"./dist/index.cjs"}},"scripts":{"build":"tsdown","typecheck":"tsc --noEmit","test":"vitest run","test:interop":"vitest run test/interop","test:watch":"vitest","prepublishOnly":"tsdown"},"publishConfig":{"access":"public"},"keywords":["yamux","multiplex","stream"],"packageManager":"pnpm@10.30.2","devDependencies":{"@types/node":"^24.5.2","tsdown":"^0.21.0","typescript":"^5.9.2","vitest":"^3.2.4"},"_id":"@bbk47/yamux@0.1.0","gitHead":"2faa0010f2f996042c03792cfb22a7f4626cf92b","_nodeVersion":"24.4.1","_npmVersion":"11.4.2","dist":{"integrity":"sha512-M3cXCIk0b9AfKzV/oCiQxdodtzkfysa4iBQw+3KuhGQbhD6wWB4YwAsMB5VDVfYJ0mOosCbjP3/7oV4bmYpAmA==","shasum":"ddc77480bab13e143d72d474d091049376c79ed1","tarball":"https://registry.npmjs.org/@bbk47/yamux/-/yamux-0.1.0.tgz","fileCount":11,"unpackedSize":160524,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCQvc8+zJTQEXIV3XfdiVgz0LfXdPkeX29v8Y6oUTPMQQIhAKsUB1DmSW4YfhUjosT9/buIUGoBS2xSog/BmUQ1Xiif"}]},"_npmUser":{"name":"x373241884y","email":"xuxihai123@gmail.com"},"directories":{},"maintainers":[{"name":"x373241884y","email":"xuxihai123@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/yamux_0.1.0_1782546430843_0.4159050698529647"},"_hasShrinkwrap":false}},"time":{"created":"2026-06-27T07:47:10.649Z","0.1.0":"2026-06-27T07:47:11.015Z","modified":"2026-06-27T07:47:11.269Z"},"maintainers":[{"name":"x373241884y","email":"xuxihai123@gmail.com"}],"description":"Production-hardened Yamux multiplexer for Node.js (TypeScript), interoperable with hashicorp/yamux. Fork of @llmcode/yamux-ts with the unknown-stream session-teardown fix.","homepage":"https://github.com/bbk47/yamux#readme","keywords":["yamux","multiplex","stream"],"repository":{"type":"git","url":"git+https://github.com/bbk47/yamux.git"},"contributors":[{"name":"GPT-5.3-Codex","url":"original @llmcode/yamux-ts"}],"author":{"name":"bbk47"},"bugs":{"url":"https://github.com/bbk47/yamux/issues"},"license":"ISC","readme":"# @bbk47/yamux\n\nProduction-hardened TypeScript implementation of Yamux for Node.js, interoperable with [`hashicorp/yamux`](https://github.com/hashicorp/yamux) (Go).\n\nThis library multiplexes many logical `Duplex` streams over a single underlying transport (typically a TCP socket), following the Yamux framing and stream lifecycle rules.\n\n> **Fork.** This is a maintained fork of [`@llmcode/yamux-ts`](https://github.com/wangcode/yamux-ts) (`wangcode/yamux-ts`). See [Fork changes](#fork-changes) for what differs from upstream.\n\n## Features\n\n- Yamux frame codec (12-byte header, big-endian)\n- `SYN`/`ACK`/`FIN`/`RST` stream lifecycle\n- Per-stream flow control (default 256 KB)\n- Session-level `Ping` and `GoAway`\n- Node.js `Duplex` API for each logical stream\n- Interop tests with `hashicorp/yamux` (Go)\n- **Robust against late/duplicate frames for closed streams** (does not tear down the whole session)\n\n## Fork changes\n\nRelative to `@llmcode/yamux-ts@0.0.2`:\n\n- **Unknown-stream frames no longer kill the session.** Previously a late or duplicate frame\n  (e.g. a trailing `WindowUpdate`/`FIN` for an already-closed stream) threw a fatal\n  `YamuxProtocolError`, which propagated to `GoAway(ProtocolError)` + `close()` and destroyed the\n  entire session and all its streams. This reliably broke any yamux **server** that opens one\n  stream per inbound connection (the 2nd connection died). It now mirrors `hashicorp/yamux`:\n  ignore the frame, and reply `RST` for non-teardown frames so the peer stops.\n- **Duplicate `SYN` for a known stream** resets only that stream instead of tearing down the session.\n- Regression tests added in `test/unit/session.test.ts` covering both cases.\n\n## Install\n\n```bash\nnpm install @bbk47/yamux\n# or: pnpm add @bbk47/yamux\n```\n\n## Quick Start\n\n### Client side\n\n```ts\nimport net from \"node:net\";\nimport { Client } from \"@bbk47/yamux\";\n\nconst socket = net.connect(9000, \"127.0.0.1\");\n\nsocket.once(\"connect\", async () => {\n  const session = Client(socket);\n\n  session.on(\"error\", (err) => {\n    console.error(\"session error\", err);\n  });\n\n  const stream = session.openStream();\n  stream.write(\"hello over yamux\\n\");\n  stream.end();\n\n  for await (const chunk of stream) {\n    process.stdout.write(chunk);\n  }\n\n  const ping = await session.ping();\n  console.log(\"rtt(ms)\", ping.rttMs);\n\n  session.goAway();\n  session.close();\n});\n```\n\n### Server side\n\n```ts\nimport net from \"node:net\";\nimport { Server } from \"@bbk47/yamux\";\n\nconst server = net.createServer((socket) => {\n  const session = Server(socket);\n\n  session.on(\"stream\", (stream) => {\n    stream.on(\"data\", (chunk) => {\n      // Echo back.\n      stream.write(chunk);\n    });\n\n    stream.on(\"end\", () => {\n      stream.end();\n    });\n  });\n\n  session.on(\"goaway\", (code) => {\n    console.log(\"peer sent goaway\", code);\n  });\n\n  session.on(\"error\", (err) => {\n    console.error(\"session error\", err);\n    session.close();\n  });\n});\n\nserver.listen(9000, \"127.0.0.1\");\n```\n\n## API\n\n### `Client(transport, config?)`\n\nCreate a Yamux session in client mode (outbound stream IDs are odd: `1, 3, 5...`).\n\n### `Server(transport, config?)`\n\nCreate a Yamux session in server mode (outbound stream IDs are even: `2, 4, 6...`).\n\n### `createClientSession(transport, options?)` and `createServerSession(transport, options?)`\n\nCompatibility aliases for users who prefer explicit factory names. They are functionally equivalent to `Client` and `Server`.\n\n### `new YamuxSession(transport, options)`\n\n`options` / `config`:\n\n- `role: \"client\" | \"server\"` (required)\n- `initialStreamWindow?: number` default `256 * 1024`\n- `maxFrameSize?: number` default `64 * 1024`\n\nMethods:\n\n- `openStream(): YamuxStream`\n- `ping(timeoutMs?: number): Promise<{ nonce: number; rttMs: number }>`\n- `goAway(code?: GoAwayCode): void`\n- `close(): void`\n\nEvents:\n\n- `stream` incoming `YamuxStream`\n- `goaway` peer session termination code\n- `error` session/protocol error\n- `close` session closed\n\n### `YamuxStream` (extends `Duplex`)\n\nUse it as a normal Node stream:\n\n- write with `stream.write()` / `stream.end()`\n- read with `stream.on(\"data\")` / async iteration\n- remote half-close maps to `end`\n- reset maps to stream error (`YamuxStreamResetError`)\n\n## Constants and Types\n\nExported protocol constants:\n\n- `YAMUX_VERSION`\n- `HEADER_SIZE`\n- `FrameType`\n- `FrameFlag`\n- `GoAwayCode`\n- `DEFAULT_INITIAL_WINDOW`\n- `DEFAULT_MAX_FRAME_SIZE`\n\nExported low-level helpers:\n\n- `encodeFrame`, `decodeFrame`, `decodeHeader`, `writeHeader`\n- `FrameParser`, `YamuxCodec`\n\n## Error Semantics\n\n- `YamuxProtocolError`: invalid frame or protocol violation\n- `YamuxClosedError`: operation on closed/goaway session\n- `YamuxStreamResetError`: stream reset (RST)\n\nOn a genuine protocol violation (e.g. a malformed frame), the session sends `GoAway(ProtocolError)` and closes. Late/duplicate frames for unknown (already-closed) streams are **not** treated as violations — they are tolerated and answered with `RST`, matching `hashicorp/yamux`.\n\n## Development\n\n```bash\npnpm typecheck\npnpm test\npnpm test:interop\npnpm build\n```\n\n## Interop Testing\n\n`pnpm test:interop` starts a Go process in `test/interop/go` using `hashicorp/yamux` and validates:\n\n- stream open + payload echo\n- concurrent streams\n- ping roundtrip\n\n## LLM Integration Guide\n\nFor code generation agents, see:\n\n- `docs/LLM_GUIDE.md`\n","readmeFilename":"README.md","_rev":"1-4994b640b2420ea63601cae78aba4b2d"}