diff --git a/packages/core-trpc/package.json b/packages/core-trpc/package.json index 518bb50..d9b9db4 100644 --- a/packages/core-trpc/package.json +++ b/packages/core-trpc/package.json @@ -15,7 +15,6 @@ "test": "vitest run --passWithNoTests" }, "dependencies": { - "@repo/core-api": "workspace:*", "@tanstack/react-query": "^5.66.0", "@trpc/client": "^11.18.0", "@trpc/server": "^11.18.0", diff --git a/packages/core-trpc/src/client.test.ts b/packages/core-trpc/src/client.test.ts index e998a06..9d879d2 100644 --- a/packages/core-trpc/src/client.test.ts +++ b/packages/core-trpc/src/client.test.ts @@ -1,4 +1,15 @@ -import { describe, it, expect } from "vitest"; +import { describe, it, expect, vi } from "vitest"; + +// Stub the tRPC context factory so useTRPC() can run outside a React render: +// the real context.useTRPC() requires a mounted TRPCProvider. The stubbed +// proxy lets us exercise the router-agnostic delegation (client.ts:useTRPC). +vi.mock("@trpc/tanstack-react-query", () => ({ + createTRPCContext: () => ({ + TRPCProvider: () => null, + useTRPC: () => ({ __proxy: "trpc-options-proxy" }), + }), +})); + import { useTRPC, TRPCProvider } from "./client"; describe("core-trpc client exports", () => { @@ -9,4 +20,10 @@ describe("core-trpc client exports", () => { it("exports TRPCProvider component", () => { expect(TRPCProvider).toBeTypeOf("function"); }); + + it("useTRPC delegates to the underlying router-agnostic tRPC proxy", () => { + // The generic is a compile-time-only cast; at runtime it returns whatever + // the shared context proxy yields. + expect(useTRPC()).toEqual({ __proxy: "trpc-options-proxy" }); + }); }); diff --git a/packages/core-trpc/src/client.ts b/packages/core-trpc/src/client.ts index 722b8c1..b0c68bf 100644 --- a/packages/core-trpc/src/client.ts +++ b/packages/core-trpc/src/client.ts @@ -1,6 +1,20 @@ "use client"; import { createTRPCContext } from "@trpc/tanstack-react-query"; -import type { AppRouter } from "@repo/core-api"; +import type { TRPCOptionsProxy } from "@trpc/tanstack-react-query"; +import type { AnyTRPCRouter } from "@trpc/server"; -export const { TRPCProvider, useTRPC } = createTRPCContext(); +// core-trpc must not depend on @repo/core-api (core → core-composition is an +// illegal boundary edge and creates a package cycle through the features). +// The runtime context is router-agnostic; consumers inject their router type +// as a generic: features pass their app-slice type (e.g. `BlogAppSlice`), +// apps may pass the full AppRouter. +const context = createTRPCContext(); + +export const TRPCProvider = context.TRPCProvider; + +export function useTRPC< + TRouter extends AnyTRPCRouter = AnyTRPCRouter, +>(): TRPCOptionsProxy { + return context.useTRPC() as unknown as TRPCOptionsProxy; +} diff --git a/packages/core-trpc/src/index.ts b/packages/core-trpc/src/index.ts index 7b27b5d..94a24e8 100644 --- a/packages/core-trpc/src/index.ts +++ b/packages/core-trpc/src/index.ts @@ -1,3 +1,2 @@ export { useTRPC, TRPCProvider } from "./client"; export { getQueryClient } from "./query-client"; -export type { AppRouter } from "@repo/core-api"; diff --git a/packages/core-trpc/src/providers/next-provider.tsx b/packages/core-trpc/src/providers/next-provider.tsx index dc4b9d8..0b24838 100644 --- a/packages/core-trpc/src/providers/next-provider.tsx +++ b/packages/core-trpc/src/providers/next-provider.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import { QueryClientProvider } from "@tanstack/react-query"; import { createTRPCClient, httpBatchLink } from "@trpc/client"; import superjson from "superjson"; -import type { AppRouter } from "@repo/core-api"; +import type { AnyTRPCRouter } from "@trpc/server"; import { TRPCProvider } from "../client"; import { getQueryClient } from "../query-client"; @@ -22,7 +22,9 @@ export function NextTrpcProvider({ }) { const [queryClient] = useState(() => getQueryClient()); const [trpcClient] = useState(() => - createTRPCClient({ + // Router-agnostic on purpose: procedure typing comes from useTRPC + // at the call sites, not from the wire-level client. + createTRPCClient({ links: [ httpBatchLink({ url: `${getBaseUrl()}${trpcUrl}`, diff --git a/packages/core-trpc/src/providers/tanstack-provider.tsx b/packages/core-trpc/src/providers/tanstack-provider.tsx index 0f48647..c5e46dc 100644 --- a/packages/core-trpc/src/providers/tanstack-provider.tsx +++ b/packages/core-trpc/src/providers/tanstack-provider.tsx @@ -4,7 +4,7 @@ import { useState } from "react"; import { QueryClientProvider } from "@tanstack/react-query"; import { createTRPCClient, httpBatchLink } from "@trpc/client"; import superjson from "superjson"; -import type { AppRouter } from "@repo/core-api"; +import type { AnyTRPCRouter } from "@trpc/server"; import { TRPCProvider } from "../client"; import { getQueryClient } from "../query-client"; @@ -17,7 +17,9 @@ export function TanstackTrpcProvider({ }) { const [queryClient] = useState(() => getQueryClient()); const [trpcClient] = useState(() => - createTRPCClient({ + // Router-agnostic on purpose: procedure typing comes from useTRPC + // at the call sites, not from the wire-level client. + createTRPCClient({ links: [httpBatchLink({ url: trpcUrl, transformer: superjson })], }), ); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24affeb..77bca3c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -760,9 +760,6 @@ importers: packages/core-trpc: dependencies: - "@repo/core-api": - specifier: workspace:* - version: link:../core-api "@tanstack/react-query": specifier: ^5.66.0 version: 5.96.2(react@19.2.4)