{
  "$schema": "https://hyperjs.ai/schema/registry-item.json",
  "name": "msgpack",
  "version": "0.1.0",
  "description": "MessagePack wire format for Hyper — content-negotiated encode/decode.",
  "readme": "# @hyper/msgpack\n\nMessagePack wire format for Hyper — content-negotiated encode/decode.\n\n## Install\n\nComponents are installed as source into your repo, not pulled from npm:\n\n```bash\nbunx hyper add msgpack\n```\n\nWires the alias `@hyper/msgpack` to `src/hyper/msgpack/` (configurable in `hyper.config.json`). See [hyperjs.ai](https://hyperjs.ai) for the full registry.\n\n## Usage\n\n```ts\nimport { Hyper } from \"@hyper/core\"\nimport { msgpack } from \"@hyper/msgpack\"\n\nexport default new Hyper()\n  .use(msgpack())\n  .listen(3000)\n```\n\n## Docs\n\nSee the [main README](../../README.md) and [docs/](../../docs) for guides and integration recipes.\n\n## License\n\nMIT\n",
  "registryDeps": [
    "core"
  ],
  "peerDeps": {},
  "optionalPeerDeps": {},
  "files": [
    {
      "path": "msgpack/codec.ts",
      "contents": "/**\n * Minimal MessagePack encoder/decoder.\n *\n * Covers the subset Hyper traffic uses in practice:\n *   nil, bool, int (8/16/32/64 signed), float64, string, bin, array, map.\n *\n * Not a drop-in for `@msgpack/msgpack` — no extensions, timestamps, or\n * BigInts. If your payload needs more than this, plug in the full codec\n * via `app({ encoders: { \"application/msgpack\": custom } })`.\n */\n\nexport function encode(value: unknown): Uint8Array {\n  const buf: number[] = []\n  write(buf, value)\n  return Uint8Array.from(buf)\n}\n\nexport function decode(bytes: Uint8Array): unknown {\n  const cursor = { i: 0 }\n  const v = read(bytes, cursor)\n  return v\n}\n\nfunction write(buf: number[], v: unknown): void {\n  if (v === null || v === undefined) {\n    buf.push(0xc0)\n    return\n  }\n  if (typeof v === \"boolean\") {\n    buf.push(v ? 0xc3 : 0xc2)\n    return\n  }\n  if (typeof v === \"number\") {\n    if (Number.isInteger(v)) {\n      writeInt(buf, v)\n    } else {\n      writeFloat64(buf, v)\n    }\n    return\n  }\n  if (typeof v === \"string\") {\n    writeStr(buf, v)\n    return\n  }\n  if (v instanceof Uint8Array) {\n    writeBin(buf, v)\n    return\n  }\n  if (Array.isArray(v)) {\n    writeArray(buf, v)\n    return\n  }\n  if (typeof v === \"object\") {\n    writeMap(buf, v as Record<string, unknown>)\n    return\n  }\n  throw new Error(`msgpack: unsupported type: ${typeof v}`)\n}\n\nfunction writeInt(buf: number[], n: number): void {\n  if (n >= 0 && n <= 0x7f) {\n    buf.push(n)\n  } else if (n < 0 && n >= -0x20) {\n    buf.push(n & 0xff)\n  } else if (n >= 0 && n <= 0xff) {\n    buf.push(0xcc, n)\n  } else if (n >= 0 && n <= 0xffff) {\n    buf.push(0xcd, (n >> 8) & 0xff, n & 0xff)\n  } else if (n >= 0 && n <= 0xffffffff) {\n    buf.push(0xce, (n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff)\n  } else if (n >= -0x80 && n <= 0x7f) {\n    buf.push(0xd0, n & 0xff)\n  } else if (n >= -0x8000 && n <= 0x7fff) {\n    buf.push(0xd1, (n >> 8) & 0xff, n & 0xff)\n  } else if (n >= -0x80000000 && n <= 0x7fffffff) {\n    buf.push(0xd2, (n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff)\n  } else {\n    // Fallback: encode as float64 — preserves precision up to 2^53.\n    writeFloat64(buf, n)\n  }\n}\n\nfunction writeFloat64(buf: number[], n: number): void {\n  buf.push(0xcb)\n  const b = new ArrayBuffer(8)\n  new DataView(b).setFloat64(0, n, false)\n  const view = new Uint8Array(b)\n  for (let i = 0; i < 8; i++) buf.push(view[i]!)\n}\n\nfunction writeStr(buf: number[], s: string): void {\n  const bytes = new TextEncoder().encode(s)\n  const n = bytes.length\n  if (n <= 31) buf.push(0xa0 | n)\n  else if (n <= 0xff) buf.push(0xd9, n)\n  else if (n <= 0xffff) buf.push(0xda, (n >> 8) & 0xff, n & 0xff)\n  else buf.push(0xdb, (n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff)\n  for (let i = 0; i < bytes.length; i++) buf.push(bytes[i]!)\n}\n\nfunction writeBin(buf: number[], b: Uint8Array): void {\n  const n = b.length\n  if (n <= 0xff) buf.push(0xc4, n)\n  else if (n <= 0xffff) buf.push(0xc5, (n >> 8) & 0xff, n & 0xff)\n  else buf.push(0xc6, (n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff)\n  for (let i = 0; i < b.length; i++) buf.push(b[i]!)\n}\n\nfunction writeArray(buf: number[], arr: readonly unknown[]): void {\n  const n = arr.length\n  if (n <= 15) buf.push(0x90 | n)\n  else if (n <= 0xffff) buf.push(0xdc, (n >> 8) & 0xff, n & 0xff)\n  else buf.push(0xdd, (n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff)\n  for (const v of arr) write(buf, v)\n}\n\nfunction writeMap(buf: number[], o: Record<string, unknown>): void {\n  const keys = Object.keys(o)\n  const n = keys.length\n  if (n <= 15) buf.push(0x80 | n)\n  else if (n <= 0xffff) buf.push(0xde, (n >> 8) & 0xff, n & 0xff)\n  else buf.push(0xdf, (n >>> 24) & 0xff, (n >>> 16) & 0xff, (n >>> 8) & 0xff, n & 0xff)\n  for (const k of keys) {\n    writeStr(buf, k)\n    write(buf, o[k])\n  }\n}\n\nfunction read(bytes: Uint8Array, c: { i: number }): unknown {\n  const b = bytes[c.i++]!\n  if (b <= 0x7f) return b\n  if (b >= 0xe0) return b - 0x100\n  if (b === 0xc0) return null\n  if (b === 0xc2) return false\n  if (b === 0xc3) return true\n  if (b === 0xcc) return bytes[c.i++]!\n  if (b === 0xcd) {\n    const v = (bytes[c.i]! << 8) | bytes[c.i + 1]!\n    c.i += 2\n    return v\n  }\n  if (b === 0xce) {\n    const v =\n      bytes[c.i]! * 0x1000000 + ((bytes[c.i + 1]! << 16) | (bytes[c.i + 2]! << 8) | bytes[c.i + 3]!)\n    c.i += 4\n    return v\n  }\n  if (b === 0xd0) {\n    const v = bytes[c.i++]!\n    return v > 0x7f ? v - 0x100 : v\n  }\n  if (b === 0xd1) {\n    const v = (bytes[c.i]! << 8) | bytes[c.i + 1]!\n    c.i += 2\n    return v > 0x7fff ? v - 0x10000 : v\n  }\n  if (b === 0xd2) {\n    const dv = new DataView(bytes.buffer, bytes.byteOffset + c.i, 4)\n    const v = dv.getInt32(0, false)\n    c.i += 4\n    return v\n  }\n  if (b === 0xcb) {\n    const dv = new DataView(bytes.buffer, bytes.byteOffset + c.i, 8)\n    const v = dv.getFloat64(0, false)\n    c.i += 8\n    return v\n  }\n  if (b >= 0xa0 && b <= 0xbf) return readStr(bytes, c, b & 0x1f)\n  if (b === 0xd9) return readStr(bytes, c, bytes[c.i++]!)\n  if (b === 0xda) {\n    const n = (bytes[c.i]! << 8) | bytes[c.i + 1]!\n    c.i += 2\n    return readStr(bytes, c, n)\n  }\n  if (b === 0xdb) {\n    const dv = new DataView(bytes.buffer, bytes.byteOffset + c.i, 4)\n    const n = dv.getUint32(0, false)\n    c.i += 4\n    return readStr(bytes, c, n)\n  }\n  if (b === 0xc4) return readBin(bytes, c, bytes[c.i++]!)\n  if (b >= 0x90 && b <= 0x9f) return readArr(bytes, c, b & 0x0f)\n  if (b === 0xdc) {\n    const n = (bytes[c.i]! << 8) | bytes[c.i + 1]!\n    c.i += 2\n    return readArr(bytes, c, n)\n  }\n  if (b >= 0x80 && b <= 0x8f) return readMap(bytes, c, b & 0x0f)\n  if (b === 0xde) {\n    const n = (bytes[c.i]! << 8) | bytes[c.i + 1]!\n    c.i += 2\n    return readMap(bytes, c, n)\n  }\n  throw new Error(`msgpack: unexpected byte 0x${b.toString(16)}`)\n}\n\nfunction readStr(bytes: Uint8Array, c: { i: number }, n: number): string {\n  const s = new TextDecoder().decode(bytes.subarray(c.i, c.i + n))\n  c.i += n\n  return s\n}\nfunction readBin(bytes: Uint8Array, c: { i: number }, n: number): Uint8Array {\n  const v = bytes.slice(c.i, c.i + n)\n  c.i += n\n  return v\n}\nfunction readArr(bytes: Uint8Array, c: { i: number }, n: number): unknown[] {\n  const out: unknown[] = []\n  for (let i = 0; i < n; i++) out.push(read(bytes, c))\n  return out\n}\nfunction readMap(bytes: Uint8Array, c: { i: number }, n: number): Record<string, unknown> {\n  const out: Record<string, unknown> = {}\n  for (let i = 0; i < n; i++) {\n    const k = read(bytes, c) as string\n    out[k] = read(bytes, c)\n  }\n  return out\n}\n",
      "sha256": "bd0e918d130dfc037a6337fa6c6d9e74ba96aad84d6ad53692b120df00ec9d21"
    },
    {
      "path": "msgpack/index.ts",
      "contents": "/**\n * @hyper/msgpack — content-negotiated MessagePack middleware + transport.\n *\n *   use(msgpack())\n *\n * When the client sends `Accept: application/msgpack` AND the handler\n * returns a serializable object, we encode with msgpack. When the client\n * posts `Content-Type: application/msgpack`, we decode the body first.\n *\n * HTTP semantics are preserved; only the wire format changes.\n */\n\nimport type { Middleware } from \"@hyper/core\"\nimport { decode, encode } from \"./codec.ts\"\n\nexport { decode, encode } from \"./codec.ts\"\n\nexport const CONTENT_TYPE = \"application/msgpack\"\n\nexport function msgpack(): Middleware {\n  return async ({ req, next }) => {\n    // Decode inbound body if it's msgpack. We rewrite the Request body\n    // as JSON so the rest of the stack (validators, handlers) sees the\n    // same shape regardless of wire format.\n    let inbound = req\n    if (req.body && (req.headers.get(\"content-type\") ?? \"\").startsWith(CONTENT_TYPE)) {\n      const bytes = new Uint8Array(await req.arrayBuffer())\n      const decoded = decode(bytes)\n      const newHeaders = new Headers(req.headers)\n      newHeaders.set(\"content-type\", \"application/json\")\n      inbound = new Request(req.url, {\n        method: req.method,\n        headers: newHeaders,\n        body: JSON.stringify(decoded),\n      })\n    }\n\n    const wantsMsgpack = (req.headers.get(\"accept\") ?? \"\").includes(CONTENT_TYPE)\n    // Use `inbound` if we rewrote the Request — the rest of the chain\n    // pulls from the original handler scope so this swap only affects\n    // our own cloned-body reads; we just forward the headers.\n    void inbound\n    const out = await next()\n    if (!wantsMsgpack) return out\n    const res =\n      out instanceof Response\n        ? out\n        : new Response(JSON.stringify(out), {\n            headers: { \"content-type\": \"application/json\" },\n          })\n    if ((res.headers.get(\"content-type\") ?? \"\").includes(\"application/json\")) {\n      const body = await res.clone().json()\n      const bytes = encode(body)\n      const headers = new Headers(res.headers)\n      headers.set(\"content-type\", CONTENT_TYPE)\n      headers.set(\"content-length\", bytes.byteLength.toString())\n      return new Response(bytes, { status: res.status, headers })\n    }\n    return res\n  }\n}\n",
      "sha256": "81f92241243fd660d23bb1e207616adfdd01c90009b7b3561f1511acf8706d95"
    }
  ],
  "subpaths": {}
}