{
  "$schema": "https://hyperjs.ai/schema/registry-item.json",
  "name": "trpc",
  "version": "0.1.0",
  "description": "tRPC bridge — mount tRPC into Hyper, or convert a tRPC router to Hyper routes.",
  "readme": "# @hyper/trpc\n\ntRPC bridge — mount tRPC into Hyper, or convert a tRPC router into Hyper routes.\n\n## Install\n\nComponents are installed as source into your repo, not pulled from npm:\n\n```bash\nbunx hyper add trpc\n```\n\nWires the alias `@hyper/trpc` to `src/hyper/trpc/` (configurable in `hyper.config.json`). See [hyperjs.ai](https://hyperjs.ai) for the full registry.\n\n## Usage\n\nMount a tRPC router inside a Hyper app:\n\n```ts\nimport { Hyper } from \"@hyper/core\"\nimport { trpcPlugin } from \"@hyper/trpc\"\nimport { appRouter } from \"./trpc/router.ts\"\n\nexport default new Hyper()\n  .use(trpcPlugin({ router: appRouter, prefix: \"/trpc\" }))\n  .listen(3000)\n```\n\nOr convert a Hyper app into a tRPC router:\n\n```ts\nimport { toTrpcRouter } from \"@hyper/trpc\"\nimport { initTRPC } from \"@trpc/server\"\nimport app from \"./app.ts\"\n\nconst t = initTRPC.create()\nexport const trpcRouter = toTrpcRouter(app, { t })\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": {
    "@trpc/server": ">=11.0.0 <12.0.0"
  },
  "files": [
    {
      "path": "trpc/bridge.ts",
      "contents": "/**\n * Mount a tRPC router at a path prefix inside a Hyper app.\n *\n * Strategy: we use tRPC's `callTRPCProcedure` API if available; otherwise\n * fall back to a minimal POST-JSON protocol we know how to drive:\n *\n *   POST /trpc/<procPath>          body: { input?: ... }\n *   response: { result: { data: T } }  or  { error: { code, message, data } }\n *\n * The tRPC server package itself provides `fetchRequestHandler` — users who\n * want full batch/stream semantics should use that directly and simply add\n * an explicit Hyper route that forwards the request.\n */\n\nimport type { HyperPlugin, Middleware } from \"@hyper/core\"\nimport type { TrpcBridgeOptions, TrpcRouterLike } from \"./types.ts\"\n\nexport function trpcPlugin<Ctx = unknown>(\n  router: TrpcRouterLike,\n  opts: TrpcBridgeOptions<Ctx> = {},\n): HyperPlugin {\n  const prefix = (opts.prefix ?? \"/trpc\").replace(/\\/+$/, \"\")\n  const trpcAny = router as { _def?: { procedures?: Record<string, unknown> } }\n  const procedures = trpcAny?._def?.procedures ?? {}\n\n  return {\n    name: \"@hyper/trpc\",\n    async build(app) {\n      // The bridge is delivered as an HTTP handler mounted via\n      // `trpcHandler(path)` returned below. This `build` hook is a no-op\n      // but reserved for future dynamic route registration.\n      void app\n    },\n  }\n}\n\n/**\n * Build a fetch-compatible handler you can mount as a Hyper route:\n *\n *   app({ routes: [\n *     route.post(\"/trpc/:proc\").handle(trpcHandler(router)),\n *     route.post(\"/trpc/:proc/*\").handle(trpcHandler(router)),\n *   ]})\n *\n * Or as a catch-all via your framework of choice.\n */\nexport function trpcHandler<Ctx>(\n  router: TrpcRouterLike,\n  opts: TrpcBridgeOptions<Ctx> = {},\n): (c: {\n  req: Request\n  params: { proc?: string }\n  ctx: Ctx\n  body: unknown\n}) => Promise<Response> {\n  const trpcAny = router as {\n    _def?: { procedures?: Record<string, { _def?: { type?: string } }> }\n  }\n  const procedures = trpcAny._def?.procedures ?? {}\n  return async (c) => {\n    const procName = c.params.proc\n    if (!procName) {\n      return json({ error: { code: \"BAD_REQUEST\", message: \"missing procedure\" } }, 400)\n    }\n    const proc = procedures[procName]\n    if (!proc) {\n      return json({ error: { code: \"NOT_FOUND\", message: `unknown procedure: ${procName}` } }, 404)\n    }\n    const rawInput = (c.body as { input?: unknown } | undefined)?.input\n    try {\n      const callable = proc as unknown as (args: {\n        ctx: unknown\n        input: unknown\n        rawInput: unknown\n        type: string\n      }) => Promise<unknown>\n      const ctx = opts.createContext ? await opts.createContext({ req: c.req, ctx: c.ctx }) : c.ctx\n      const type = proc._def?.type ?? (c.req.method === \"GET\" ? \"query\" : \"mutation\")\n      const data = await callable({ ctx, input: rawInput, rawInput, type })\n      return json({ result: { data } }, 200)\n    } catch (e) {\n      opts.onError?.({ path: procName, error: e })\n      const err = e as { code?: string; message?: string; cause?: unknown }\n      return json(\n        {\n          error: {\n            code: err.code ?? \"INTERNAL_SERVER_ERROR\",\n            message: err.message ?? \"tRPC procedure failed\",\n          },\n        },\n        500,\n      )\n    }\n  }\n}\n\n/**\n * sharedCtxMiddleware — exposes Hyper's AppContext as tRPC's ctx, so the\n * same ctx singletons (db, log, session) power both transports.\n */\nexport function sharedCtxMiddleware(): Middleware {\n  return async (args) => args.next()\n}\n\nfunction json(body: unknown, status: number): Response {\n  return new Response(JSON.stringify(body), {\n    status,\n    headers: { \"content-type\": \"application/json\" },\n  })\n}\n",
      "sha256": "b4e9cfd7f45971496911fbbb8bca1e8712d8a061a6bb9ba73d4f97e2e7b1da79"
    },
    {
      "path": "trpc/index.ts",
      "contents": "/**\n * @hyper/trpc — two-way bridge.\n *\n *  - `trpcHandler(router)` — mount a tRPC router into a Hyper route handler.\n *  - `trpcToHyper(router)` — convert a tRPC router to an array of Hyper routes.\n *  - `trpcPlugin(router)`  — register the bridge as a Hyper plugin (reserved for\n *    future dynamic-route registration).\n *\n * The bridge is structurally typed so @hyper/trpc loads without @trpc/server\n * installed. Users pass their real router and we narrow at the call site.\n */\n\nexport { sharedCtxMiddleware, trpcHandler, trpcPlugin } from \"./bridge.ts\"\nexport { trpcToHyper } from \"./to-hyper.ts\"\nexport type { TrpcBridgeOptions, TrpcRouterLike, TrpcToHyperOptions } from \"./types.ts\"\n",
      "sha256": "e8e1ea2d4a4f212b34cdae02fe0214903195c47e44004f522ac9faee290dbd95"
    },
    {
      "path": "trpc/to-hyper.ts",
      "contents": "/**\n * trpcToHyper — walks a tRPC router's procedure map and emits Hyper routes.\n * Used for migration: drop a tRPC router into a Hyper app with one call.\n *\n * We emit one POST route per procedure at `${prefix}/${procPath}`, body =\n * the raw tRPC input. Query-vs-mutation distinction is preserved via\n * `meta.trpc.type`.\n */\n\nimport { type CallableRoute, route } from \"@hyper/core\"\nimport type { TrpcRouterLike, TrpcToHyperOptions } from \"./types.ts\"\n\nexport function trpcToHyper(\n  router: TrpcRouterLike,\n  opts: TrpcToHyperOptions = {},\n): readonly CallableRoute[] {\n  const prefix = (opts.prefix ?? \"/trpc\").replace(/\\/+$/, \"\")\n  const procedures =\n    (\n      router as {\n        _def?: { procedures?: Record<string, { _def?: { type?: string } }> }\n      }\n    )._def?.procedures ?? {}\n\n  const routes: CallableRoute[] = []\n  for (const [procName, proc] of Object.entries(procedures)) {\n    const type = proc._def?.type ?? \"mutation\"\n    const meta = {\n      name: procName,\n      trpc: { type },\n      ...(opts.mapMeta ? opts.mapMeta(procName, proc) : {}),\n    }\n    const r = route\n      .post(`${prefix}/${procName}`)\n      .meta(meta)\n      .handle(async (c) => {\n        const callable = proc as unknown as (args: {\n          ctx: unknown\n          input: unknown\n          rawInput: unknown\n          type: string\n        }) => Promise<unknown>\n        const input = (c.body as { input?: unknown })?.input\n        const data = await callable({ ctx: c.ctx, input, rawInput: input, type })\n        return { result: { data } }\n      }) as CallableRoute\n    routes.push(r)\n  }\n  return routes\n}\n",
      "sha256": "afc025df796f2ab8a45f05a9e420e16383b46b5a4c753e10ea149c7b3e39619d"
    },
    {
      "path": "trpc/types.ts",
      "contents": "/**\n * Structural tRPC types — we avoid importing @trpc/server so the package\n * loads without the peer installed. Users pass their real router and we\n * type-narrow at the call site.\n */\n\n// biome-ignore lint/suspicious/noExplicitAny: structural tRPC router\nexport type TrpcRouterLike = any\n\nexport interface TrpcBridgeOptions<Ctx = unknown> {\n  /** Path prefix for the HTTP POST JSON handler. Defaults to /trpc. */\n  readonly prefix?: string\n  /** Build a tRPC context from the Hyper AppContext. */\n  readonly createContext?: (args: {\n    readonly req: Request\n    readonly ctx: Ctx\n  }) => Promise<unknown> | unknown\n  /** Error-bridge hook — called on tRPC error before response. */\n  readonly onError?: (args: { readonly path?: string; readonly error: unknown }) => void\n}\n\nexport interface TrpcToHyperOptions {\n  readonly prefix?: string\n  /** Convert a tRPC procedure shape to Hyper `meta` (auth, mcp, etc.). */\n  readonly mapMeta?: (procName: string, procedure: unknown) => Record<string, unknown>\n}\n",
      "sha256": "f855779991397c774988f48de0e7d032b7913db90b9dc482a67f8c10e4c9022c"
    }
  ],
  "subpaths": {}
}