update orpc tanstack query integration (#299)

This commit is contained in:
Aman Varshney
2025-06-05 07:36:27 +05:30
committed by GitHub
parent 19f6a2ba6f
commit 1485809ad7
32 changed files with 85 additions and 110 deletions

View File

@@ -0,0 +1,5 @@
---
"create-better-t-stack": minor
---
update orpc tanstack integration

View File

@@ -87,12 +87,9 @@ export const dependencyVersionMap = {
"@prisma/extension-accelerate": "^1.3.0",
"@orpc/server": "^1.2.0",
"@orpc/client": "^1.2.0",
"@orpc/react-query": "^1.2.0",
"@orpc/solid-query": "^1.2.0",
"@orpc/vue-query": "^1.2.0",
"@orpc/svelte-query": "^1.2.0",
"@orpc/server": "^1.4.1",
"@orpc/client": "^1.4.1",
"@orpc/tanstack-query": "^1.4.1",
"@trpc/tanstack-react-query": "^11.0.0",
"@trpc/server": "^11.0.0",

View File

@@ -54,7 +54,11 @@ export async function setupApi(config: ProjectConfig): Promise<void> {
if (hasReactWeb) {
if (api === "orpc") {
await addPackageDependency({
dependencies: ["@orpc/react-query", "@orpc/client", "@orpc/server"],
dependencies: [
"@orpc/tanstack-query",
"@orpc/client",
"@orpc/server",
],
projectDir: webDir,
});
} else if (api === "trpc") {
@@ -70,7 +74,11 @@ export async function setupApi(config: ProjectConfig): Promise<void> {
} else if (hasNuxtWeb) {
if (api === "orpc") {
await addPackageDependency({
dependencies: ["@orpc/vue-query", "@orpc/client", "@orpc/server"],
dependencies: [
"@orpc/tanstack-query",
"@orpc/client",
"@orpc/server",
],
projectDir: webDir,
});
}
@@ -78,7 +86,7 @@ export async function setupApi(config: ProjectConfig): Promise<void> {
if (api === "orpc") {
await addPackageDependency({
dependencies: [
"@orpc/svelte-query",
"@orpc/tanstack-query",
"@orpc/client",
"@orpc/server",
"@tanstack/svelte-query",
@@ -90,7 +98,7 @@ export async function setupApi(config: ProjectConfig): Promise<void> {
if (api === "orpc") {
await addPackageDependency({
dependencies: [
"@orpc/solid-query",
"@orpc/tanstack-query",
"@orpc/client",
"@orpc/server",
"@tanstack/solid-query",
@@ -113,7 +121,11 @@ export async function setupApi(config: ProjectConfig): Promise<void> {
});
} else if (api === "orpc") {
await addPackageDependency({
dependencies: ["@orpc/react-query", "@orpc/client", "@orpc/server"],
dependencies: [
"@orpc/tanstack-query",
"@orpc/client",
"@orpc/server",
],
projectDir: nativeDir,
});
}

View File

@@ -30,7 +30,8 @@ export function processAndValidateFlags(
if (options.api === "none") {
if (
options.examples &&
!(options.examples.length === 1 && options.examples[0] === "none")
!(options.examples.length === 1 && options.examples[0] === "none") &&
options.backend !== "convex"
) {
consola.fatal(
"Cannot use '--examples' when '--api' is set to 'none'. Please remove the --examples flag or choose an API type.",

View File

@@ -1,7 +1,7 @@
import { createORPCClient } from "@orpc/client";
import { RPCLink } from "@orpc/client/fetch";
import { createORPCReactQueryUtils } from "@orpc/react-query";
import type { RouterUtils } from "@orpc/react-query";
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
import type { RouterUtils } from "@orpc/tanstack-query";
import type { RouterClient } from "@orpc/server";
import { QueryCache, QueryClient } from "@tanstack/react-query";
import { createContext, useContext } from "react";
@@ -36,7 +36,7 @@ export const link = new RPCLink({
export const client: RouterClient<typeof appRouter> = createORPCClient(link);
export const orpc = createORPCReactQueryUtils(client);
export const orpc = createTanstackQueryUtils(client);
export const ORPCContext = createContext<ORPCReactUtils | undefined>(undefined);

View File

@@ -3,7 +3,7 @@ import type { RouterClient } from '@orpc/server'
import type { appRouter } from "../../../server/src/routers/index";
import { createORPCClient } from '@orpc/client'
import { RPCLink } from '@orpc/client/fetch'
import { createORPCVueQueryUtils } from '@orpc/vue-query'
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
export default defineNuxtPlugin(() => {
const config = useRuntimeConfig()
@@ -25,7 +25,7 @@ export default defineNuxtPlugin(() => {
const client: RouterClient<typeof appRouter> = createORPCClient(rpcLink)
const orpcUtils = createORPCVueQueryUtils(client)
const orpcUtils = createTanstackQueryUtils(client)
return {
provide: {

View File

@@ -1,12 +1,12 @@
import { createORPCClient } from "@orpc/client";
import { RPCLink } from "@orpc/client/fetch";
import { createORPCReactQueryUtils } from "@orpc/react-query";
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
import { QueryCache, QueryClient } from "@tanstack/react-query";
import { toast } from "sonner";
import type { appRouter } from "../../../server/src/routers/index";
import type { RouterClient } from "@orpc/server";
import { createContext, use } from 'react'
import type { RouterUtils } from '@orpc/react-query'
import type { RouterUtils } from '@orpc/tanstack-query'
type ORPCReactUtils = RouterUtils<RouterClient<typeof appRouter>>
@@ -43,7 +43,7 @@ export const link = new RPCLink({
export const client: RouterClient<typeof appRouter> = createORPCClient(link)
export const orpc = createORPCReactQueryUtils(client)
export const orpc = createTanstackQueryUtils(client)
export const ORPCContext = createContext<ORPCReactUtils | undefined>(undefined)

View File

@@ -1,6 +1,6 @@
import { createORPCClient } from "@orpc/client";
import { RPCLink } from "@orpc/client/fetch";
import { createORPCSolidQueryUtils } from "@orpc/solid-query";
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
import { QueryCache, QueryClient } from "@tanstack/solid-query";
import type { appRouter } from "../../../server/src/routers/index";
import type { RouterClient } from "@orpc/server";
@@ -27,4 +27,4 @@ export const link = new RPCLink({
export const client: RouterClient<typeof appRouter> = createORPCClient(link);
export const orpc = createORPCSolidQueryUtils(client);
export const orpc = createTanstackQueryUtils(client);

View File

@@ -2,7 +2,7 @@ import { PUBLIC_SERVER_URL } from "$env/static/public";
import { createORPCClient } from "@orpc/client";
import { RPCLink } from "@orpc/client/fetch";
import type { RouterClient } from "@orpc/server";
import { createORPCSvelteQueryUtils } from "@orpc/svelte-query";
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
import { QueryCache, QueryClient } from "@tanstack/svelte-query";
import type { appRouter } from "../../../server/src/routers/index";
@@ -28,4 +28,4 @@ export const link = new RPCLink({
export const client: RouterClient<typeof appRouter> = createORPCClient(link);
export const orpc = createORPCSvelteQueryUtils(client);
export const orpc = createTanstackQueryUtils(client);

View File

@@ -9,7 +9,7 @@ const toast = useToast()
const loading = ref(false)
const schema = z.object({
email: z.string().email('Invalid email address'),
email: z.email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters'),
})

View File

@@ -10,7 +10,7 @@ const loading = ref(false)
const schema = z.object({
name: z.string().min(2, 'Name must be at least 2 characters'),
email: z.string().email('Invalid email address'),
email: z.email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters'),
})

View File

@@ -40,7 +40,7 @@ export default function SignInForm({
},
validators: {
onSubmit: z.object({
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -43,7 +43,7 @@ export default function SignUpForm({
validators: {
onSubmit: z.object({
name: z.string().min(2, "Name must be at least 2 characters"),
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -40,7 +40,7 @@ export default function SignInForm({
},
validators: {
onSubmit: z.object({
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -43,7 +43,7 @@ export default function SignUpForm({
validators: {
onSubmit: z.object({
name: z.string().min(2, "Name must be at least 2 characters"),
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -44,7 +44,7 @@ export default function SignInForm({
},
validators: {
onSubmit: z.object({
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -47,7 +47,7 @@ export default function SignUpForm({
validators: {
onSubmit: z.object({
name: z.string().min(2, "Name must be at least 2 characters"),
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -44,7 +44,7 @@ export default function SignInForm({
},
validators: {
onSubmit: z.object({
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -47,7 +47,7 @@ export default function SignUpForm({
validators: {
onSubmit: z.object({
name: z.string().min(2, "Name must be at least 2 characters"),
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -39,7 +39,7 @@ export default function SignInForm({
},
validators: {
onSubmit: z.object({
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -42,7 +42,7 @@ export default function SignUpForm({
validators: {
onSubmit: z.object({
name: z.string().min(2, "Name must be at least 2 characters"),
email: z.string().email("Invalid email address"),
email: z.email("Invalid email address"),
password: z.string().min(8, "Password must be at least 8 characters"),
}),
},

View File

@@ -7,7 +7,7 @@
let { switchToSignUp } = $props<{ switchToSignUp: () => void }>();
const validationSchema = z.object({
email: z.string().email('Invalid email address'),
email: z.email('Invalid email address'),
password: z.string().min(1, 'Password is required'),
});

View File

@@ -8,7 +8,7 @@
const validationSchema = z.object({
name: z.string().min(2, 'Name must be at least 2 characters'),
email: z.string().email('Invalid email address'),
email: z.email('Invalid email address'),
password: z.string().min(8, 'Password must be at least 8 characters'),
});

View File

@@ -70,12 +70,12 @@ export default function TodosScreen() {
);
const toggleMutation = useMutation(
orpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
const deleteMutation = useMutation(
orpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
{{/if}}
@@ -91,12 +91,12 @@ export default function TodosScreen() {
);
const toggleMutation = useMutation(
trpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
const deleteMutation = useMutation(
trpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
{{/if}}

View File

@@ -73,12 +73,12 @@ export default function TodosScreen() {
);
const toggleMutation = useMutation(
orpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
})
);
const deleteMutation = useMutation(
orpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
})
);
{{/if}}
@@ -94,12 +94,12 @@ export default function TodosScreen() {
);
const toggleMutation = useMutation(
trpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
})
);
const deleteMutation = useMutation(
trpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
})
);
{{/if}}
@@ -337,4 +337,4 @@ const styles = StyleSheet.create((theme) => ({
textDecorationLine: "line-through",
color: theme.colors.border,
},
}));
}));

View File

@@ -65,12 +65,12 @@ export default function TodosPage() {
);
const toggleMutation = useMutation(
orpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
const deleteMutation = useMutation(
orpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
{{/if}}
@@ -86,12 +86,12 @@ export default function TodosPage() {
);
const toggleMutation = useMutation(
trpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
const deleteMutation = useMutation(
trpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
{{/if}}

View File

@@ -62,12 +62,12 @@ export default function Todos() {
);
const toggleMutation = useMutation(
orpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
})
);
const deleteMutation = useMutation(
orpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
})
);
{{/if}}
@@ -83,12 +83,12 @@ export default function Todos() {
);
const toggleMutation = useMutation(
trpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
})
);
const deleteMutation = useMutation(
trpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
})
);
{{/if}}

View File

@@ -67,12 +67,12 @@ function TodosRoute() {
);
const toggleMutation = useMutation(
orpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
const deleteMutation = useMutation(
orpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
{{/if}}
@@ -88,12 +88,12 @@ function TodosRoute() {
);
const toggleMutation = useMutation(
trpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
const deleteMutation = useMutation(
trpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
{{/if}}

View File

@@ -17,7 +17,7 @@ import { useSuspenseQuery } from "@tanstack/react-query";
import { convexQuery } from "@convex-dev/react-query";
import { useMutation } from "convex/react";
import { api } from "@{{projectName}}/backend/convex/_generated/api";
import type { Id } from "@{{projectName}}/backend/convex/_generated/dataModel.js";
import type { Id } from "@{{projectName}}/backend/convex/_generated/dataModel";
{{else}}
{{#if (eq api "trpc")}}
import { useTRPC } from "@/utils/trpc";
@@ -92,12 +92,12 @@ function TodosRoute() {
);
const toggleMutation = useMutation(
trpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
const deleteMutation = useMutation(
trpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
{{/if}}
@@ -113,12 +113,12 @@ function TodosRoute() {
);
const toggleMutation = useMutation(
orpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
const deleteMutation = useMutation(
orpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
{{/if}}

View File

@@ -24,13 +24,13 @@ function TodosRoute() {
const toggleMutation = useMutation(() =>
orpc.todo.toggle.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);
const deleteMutation = useMutation(() =>
orpc.todo.delete.mutationOptions({
onSuccess: () => todos.refetch(),
onSuccess: () => { todos.refetch() },
}),
);

View File

@@ -2,7 +2,7 @@
<script lang="ts">
import { useQuery, useConvexClient } from 'convex-svelte';
import { api } from '@{{projectName}}/backend/convex/_generated/api';
import type { Id } from '@{{projectName}}/backend/convex/_generated/dataModel.js';
import type { Id } from '@{{projectName}}/backend/convex/_generated/dataModel';
let newTodoText = $state('');
let isAdding = $state(false);
@@ -164,9 +164,6 @@
{{#if (eq api "orpc")}}
import { orpc } from '$lib/orpc';
{{/if}}
{{#if (eq api "trpc")}}
import { trpc } from '$lib/trpc';
{{/if}}
import { createQuery, createMutation } from '@tanstack/svelte-query';
let newTodoText = $state('');
@@ -208,43 +205,6 @@
})
);
{{/if}}
{{#if (eq api "trpc")}}
const todosQuery = createQuery(trpc.todo.getAll.queryOptions());
const addMutation = createMutation(
trpc.todo.create.mutationOptions({
onSuccess: () => {
$todosQuery.refetch();
newTodoText = '';
},
onError: (error) => {
console.error('Failed to create todo:', error?.message ?? error);
},
})
);
const toggleMutation = createMutation(
trpc.todo.toggle.mutationOptions({
onSuccess: () => {
$todosQuery.refetch();
},
onError: (error) => {
console.error('Failed to toggle todo:', error?.message ?? error);
},
})
);
const deleteMutation = createMutation(
trpc.todo.delete.mutationOptions({
onSuccess: () => {
$todosQuery.refetch();
},
onError: (error) => {
console.error('Failed to delete todo:', error?.message ?? error);
},
})
);
{{/if}}
function handleAddTodo(event: SubmitEvent) {
event.preventDefault();
@@ -271,7 +231,7 @@
</script>
<div class="p-4">
<h1 class="text-xl mb-4">Todos{{#if (eq api "trpc")}} (tRPC){{/if}}{{#if (eq api "orpc")}} (oRPC){{/if}}</h1>
<h1 class="text-xl mb-4">Todos{{#if (eq api "orpc")}} (oRPC){{/if}}</h1>
<form onsubmit={handleAddTodo} class="flex gap-2 mb-4">
<input

View File

@@ -8,7 +8,7 @@ import type { QueryClient } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { useState } from "react";
import type { RouterClient } from "@orpc/server";
import { createORPCReactQueryUtils } from "@orpc/react-query";
import { createTanstackQueryUtils } from "@orpc/tanstack-query";
import type { appRouter } from "../../../server/src/routers";
import { createORPCClient } from "@orpc/client";
{{/if}}
@@ -68,7 +68,7 @@ function RootComponent() {
{{#if (eq api "orpc")}}
const [client] = useState<RouterClient<typeof appRouter>>(() => createORPCClient(link));
const [orpcUtils] = useState(() => createORPCReactQueryUtils(client));
const [orpcUtils] = useState(() => createTanstackQueryUtils(client));
{{/if}}
return (