refactor(core-trpc): make the tRPC context router-agnostic
Ports the type-safety/ergonomics half of the upstream cycle-break: core-trpc no longer imports AppRouter from @repo/core-api (an illegal core -> core-composition boundary edge). The runtime context and both providers are now AnyTRPCRouter-generic; consumers inject their router type via useTRPC<TRouter>(). Our tree is already cycle-free (the demo features that closed the cycle are deleted and no kept feature depends on core-trpc), so this is purely the architecture/boundary improvement. The per-feature app-slice types the upstream commit added for blog/marketing-pages/navigation are intentionally skipped: no kept feature consumes useTRPC yet, so there is nothing to type, and adding slice types now would be speculative. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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<AppRouter>();
|
||||
// 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<AnyTRPCRouter>();
|
||||
|
||||
export const TRPCProvider = context.TRPCProvider;
|
||||
|
||||
export function useTRPC<
|
||||
TRouter extends AnyTRPCRouter = AnyTRPCRouter,
|
||||
>(): TRPCOptionsProxy<TRouter> {
|
||||
return context.useTRPC() as unknown as TRPCOptionsProxy<TRouter>;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
export { useTRPC, TRPCProvider } from "./client";
|
||||
export { getQueryClient } from "./query-client";
|
||||
export type { AppRouter } from "@repo/core-api";
|
||||
|
||||
@@ -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<AppRouter>({
|
||||
// Router-agnostic on purpose: procedure typing comes from useTRPC<TRouter>
|
||||
// at the call sites, not from the wire-level client.
|
||||
createTRPCClient<AnyTRPCRouter>({
|
||||
links: [
|
||||
httpBatchLink({
|
||||
url: `${getBaseUrl()}${trpcUrl}`,
|
||||
|
||||
@@ -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<AppRouter>({
|
||||
// Router-agnostic on purpose: procedure typing comes from useTRPC<TRouter>
|
||||
// at the call sites, not from the wire-level client.
|
||||
createTRPCClient<AnyTRPCRouter>({
|
||||
links: [httpBatchLink({ url: trpcUrl, transformer: superjson })],
|
||||
}),
|
||||
);
|
||||
|
||||
3
pnpm-lock.yaml
generated
3
pnpm-lock.yaml
generated
@@ -914,9 +914,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)
|
||||
|
||||
Reference in New Issue
Block a user