diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index aa060aa56..f92512bc8 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -31,7 +31,7 @@ jobs:
 
         strategy:
             matrix:
-                node-version: [18.x]
+                node-version: [20.x]
                 prisma-version: [v4, v5]
 
         steps:
diff --git a/README.md b/README.md
index e3b910b38..bb640ae6c 100644
--- a/README.md
+++ b/README.md
@@ -183,7 +183,18 @@ The following diagram gives a high-level architecture overview of ZenStack.
 
 ## Examples
 
-### Todo SaaS App
+### Schema Samples
+
+The [sample repo](https://github.com/zenstackhq/authz-modeling-samples) includes the following patterns:
+
+-   ACL
+-   RBAC
+-   ABAC
+-   Multi-Tenancy
+
+You can use [this blog post](https://zenstack.dev/blog/model-authz) as an introduction.
+
+### Multi-Tenant Todo App
 
 Check out the [Multi-tenant Todo App](https://zenstack-todo.vercel.app/) for a running example. You can find different implementations below:
 
@@ -213,6 +224,8 @@ Join our [discord server](https://discord.gg/Ykhr738dUe) for chat and updates!
 
 If you like ZenStack, join us to make it a better tool! Please use the [Contributing Guide](CONTRIBUTING.md) for details on how to get started, and don't hesitate to join [Discord](https://discord.gg/Ykhr738dUe) to share your thoughts.
 
+Please also consider [sponsoring our work](https://github.com/sponsors/zenstackhq) to speed up the development of ZenStack. Thank you!
+
 ## License
 
 [MIT](LICENSE)
diff --git a/package.json b/package.json
index d622deade..35bf85df1 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
     "name": "zenstack-monorepo",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "description": "",
     "scripts": {
         "build": "pnpm -r build",
diff --git a/packages/ide/jetbrains/.idea/misc.xml b/packages/ide/jetbrains/.idea/misc.xml
index 68bf986ec..faebea582 100644
--- a/packages/ide/jetbrains/.idea/misc.xml
+++ b/packages/ide/jetbrains/.idea/misc.xml
@@ -5,4 +5,7 @@
     <file type="web" url="file://$PROJECT_DIR$" />
   </component>
   <component name="ProjectRootManager" version="2" languageLevel="JDK_20" default="true" project-jdk-name="20" project-jdk-type="JavaSDK" />
+  <component name="SuppressKotlinCodeStyleNotification">
+    <option name="disableForAll" value="true" />
+  </component>
 </project>
\ No newline at end of file
diff --git a/packages/ide/jetbrains/CHANGELOG.md b/packages/ide/jetbrains/CHANGELOG.md
new file mode 100644
index 000000000..4f4625001
--- /dev/null
+++ b/packages/ide/jetbrains/CHANGELOG.md
@@ -0,0 +1,6 @@
+# Changelog
+
+## [Unreleased]
+
+### Added
+- Auto-completion is now supported inside attributes.
diff --git a/packages/ide/jetbrains/build.gradle.kts b/packages/ide/jetbrains/build.gradle.kts
index 95c926cd6..8c01895ad 100644
--- a/packages/ide/jetbrains/build.gradle.kts
+++ b/packages/ide/jetbrains/build.gradle.kts
@@ -1,11 +1,15 @@
+import org.jetbrains.changelog.Changelog
+import org.jetbrains.changelog.date
+
 plugins {
     id("java")
     id("org.jetbrains.kotlin.jvm") version "1.9.21"
     id("org.jetbrains.intellij") version "1.16.1"
+    id("org.jetbrains.changelog") version "2.2.0"
 }
 
 group = "dev.zenstack"
-version = "1.7.1"
+version = "1.8.0"
 
 repositories {
     mavenCentral()
@@ -52,8 +56,17 @@ tasks {
     }
 
     patchPluginXml {
-        sinceBuild.set("231")
-        untilBuild.set("241.*")
+        sinceBuild.set("233.2")
+        untilBuild.set("251.*")
+        changeNotes.set(provider {
+            changelog.renderItem(
+                    changelog
+                            .getUnreleased()
+                            .withHeader(false)
+                            .withEmptySections(false),
+                    Changelog.OutputType.HTML
+            )
+        })
     }
 
     signPlugin {
@@ -66,3 +79,21 @@ tasks {
         token.set(System.getenv("PUBLISH_TOKEN"))
     }
 }
+
+changelog {
+    header.set(provider { "[${version.get()}] - ${date()}" })
+    introduction.set(
+            """
+        [ZenStack](https://zenstack.dev) is a toolkit that simplifies the development of a web app's backend. This plugin provides code editing experiences for its ZModel schema language.
+        
+        ## Features
+        
+        - Syntax highlighting
+        - Error highlighting
+        - Go to definition
+        - Code completion
+        - Formatting
+        """.trimIndent()
+    )
+    groups.set(listOf("Added", "Changed", "Deprecated", "Removed", "Fixed", "Security"))
+}
diff --git a/packages/ide/jetbrains/package.json b/packages/ide/jetbrains/package.json
index f4c6cb59b..7f672561e 100644
--- a/packages/ide/jetbrains/package.json
+++ b/packages/ide/jetbrains/package.json
@@ -1,6 +1,6 @@
 {
     "name": "jetbrains",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "displayName": "ZenStack JetBrains IDE Plugin",
     "description": "ZenStack JetBrains IDE plugin",
     "homepage": "https://zenstack.dev",
diff --git a/packages/language/package.json b/packages/language/package.json
index bde19396a..49d147545 100644
--- a/packages/language/package.json
+++ b/packages/language/package.json
@@ -1,6 +1,6 @@
 {
     "name": "@zenstackhq/language",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "displayName": "ZenStack modeling language compiler",
     "description": "ZenStack modeling language compiler",
     "homepage": "https://zenstack.dev",
diff --git a/packages/misc/redwood/package.json b/packages/misc/redwood/package.json
index 9f9537ee8..12a63f6d9 100644
--- a/packages/misc/redwood/package.json
+++ b/packages/misc/redwood/package.json
@@ -1,7 +1,7 @@
 {
     "name": "@zenstackhq/redwood",
     "displayName": "ZenStack RedwoodJS Integration",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "description": "CLI and runtime for integrating ZenStack with RedwoodJS projects.",
     "repository": {
         "type": "git",
diff --git a/packages/plugins/openapi/package.json b/packages/plugins/openapi/package.json
index 8969a2c06..137bfd8e5 100644
--- a/packages/plugins/openapi/package.json
+++ b/packages/plugins/openapi/package.json
@@ -1,7 +1,7 @@
 {
   "name": "@zenstackhq/openapi",
   "displayName": "ZenStack Plugin and Runtime for OpenAPI",
-  "version": "1.7.1",
+  "version": "1.8.0",
   "description": "ZenStack plugin and runtime supporting OpenAPI",
   "main": "index.js",
   "repository": {
diff --git a/packages/plugins/swr/package.json b/packages/plugins/swr/package.json
index d3e246a1c..800447668 100644
--- a/packages/plugins/swr/package.json
+++ b/packages/plugins/swr/package.json
@@ -1,7 +1,7 @@
 {
     "name": "@zenstackhq/swr",
     "displayName": "ZenStack plugin for generating SWR hooks",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "description": "ZenStack plugin for generating SWR hooks",
     "main": "index.js",
     "repository": {
diff --git a/packages/plugins/swr/tests/swr.test.ts b/packages/plugins/swr/tests/swr.test.ts
index 76db29b49..9d198269b 100644
--- a/packages/plugins/swr/tests/swr.test.ts
+++ b/packages/plugins/swr/tests/swr.test.ts
@@ -59,7 +59,12 @@ ${sharedModel}
             {
                 provider: 'postgresql',
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, 'react@18.2.0', '@types/react@18.2.0', 'swr@^2'],
+                extraDependencies: [
+                    `${path.join(__dirname, '../dist')}`,
+                    'react@18.2.0',
+                    '@types/react@18.2.0',
+                    'swr@^2',
+                ],
                 compile: true,
             }
         );
diff --git a/packages/plugins/tanstack-query/package.json b/packages/plugins/tanstack-query/package.json
index efd031243..74c198535 100644
--- a/packages/plugins/tanstack-query/package.json
+++ b/packages/plugins/tanstack-query/package.json
@@ -1,7 +1,7 @@
 {
     "name": "@zenstackhq/tanstack-query",
     "displayName": "ZenStack plugin for generating tanstack-query hooks",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "description": "ZenStack plugin for generating tanstack-query hooks",
     "main": "index.js",
     "exports": {
diff --git a/packages/plugins/tanstack-query/src/generator.ts b/packages/plugins/tanstack-query/src/generator.ts
index c32799cbc..bf0c88e0a 100644
--- a/packages/plugins/tanstack-query/src/generator.ts
+++ b/packages/plugins/tanstack-query/src/generator.ts
@@ -84,9 +84,9 @@ function generateQueryHook(
     const capOperation = upperCaseFirst(operation);
 
     const argsType = overrideInputType ?? `Prisma.${model}${capOperation}Args`;
-    const inputType = `Prisma.SelectSubset<T, ${argsType}>`;
+    const inputType = `Prisma.SelectSubset<TArgs, ${argsType}>`;
 
-    let defaultReturnType = `Prisma.${model}GetPayload<T>`;
+    let defaultReturnType = `Prisma.${model}GetPayload<TArgs>`;
     if (optimisticUpdate) {
         defaultReturnType += '& { $optimistic?: boolean }';
     }
@@ -95,11 +95,16 @@ function generateQueryHook(
     }
 
     const returnType = overrideReturnType ?? defaultReturnType;
-    const optionsType = makeQueryOptions(target, returnType, infinite, version);
+    const optionsType = makeQueryOptions(target, 'TQueryFnData', 'TData', infinite, version);
 
     const func = sf.addFunction({
         name: `use${infinite ? 'Infinite' : ''}${capOperation}${model}`,
-        typeParameters: overrideTypeParameters ?? [`T extends ${argsType}`],
+        typeParameters: overrideTypeParameters ?? [
+            `TArgs extends ${argsType}`,
+            `TQueryFnData = ${returnType} `,
+            'TData = TQueryFnData',
+            'TError = DefaultError',
+        ],
         parameters: [
             {
                 name: optionalInput ? 'args?' : 'args',
@@ -129,7 +134,9 @@ function generateQueryHook(
 
     func.addStatements([
         makeGetContext(target),
-        `return ${infinite ? 'useInfiniteModelQuery' : 'useModelQuery'}('${model}', \`\${endpoint}/${lowerCaseFirst(
+        `return ${
+            infinite ? 'useInfiniteModelQuery' : 'useModelQuery'
+        }<TQueryFnData, TData, TError>('${model}', \`\${endpoint}/${lowerCaseFirst(
             model
         )}/${operation}\`, args, options, fetch${optimisticUpdate ? ', optimisticUpdate' : ''});`,
     ]);
@@ -403,7 +410,7 @@ function generateModelHooks(
             'aggregate',
             false,
             false,
-            `Prisma.Get${modelNameCap}AggregateType<T>`
+            `Prisma.Get${modelNameCap}AggregateType<TArgs>`
         );
     }
 
@@ -415,16 +422,27 @@ function generateModelHooks(
             useName = model.name;
         }
 
+        const returnType = `{} extends InputErrors ? 
+        Array<PickEnumerable<Prisma.${modelNameCap}GroupByOutputType, TArgs['by']> &
+          {
+            [P in ((keyof TArgs) & (keyof Prisma.${modelNameCap}GroupByOutputType))]: P extends '_count'
+              ? TArgs[P] extends boolean
+                ? number
+                : Prisma.GetScalarType<TArgs[P], Prisma.${modelNameCap}GroupByOutputType[P]>
+              : Prisma.GetScalarType<TArgs[P], Prisma.${modelNameCap}GroupByOutputType[P]>
+          }
+        > : InputErrors`;
+
         const typeParameters = [
-            `T extends Prisma.${useName}GroupByArgs`,
-            `HasSelectOrTake extends Prisma.Or<Prisma.Extends<'skip', Prisma.Keys<T>>, Prisma.Extends<'take', Prisma.Keys<T>>>`,
+            `TArgs extends Prisma.${useName}GroupByArgs`,
+            `HasSelectOrTake extends Prisma.Or<Prisma.Extends<'skip', Prisma.Keys<TArgs>>, Prisma.Extends<'take', Prisma.Keys<TArgs>>>`,
             `OrderByArg extends Prisma.True extends HasSelectOrTake ? { orderBy: Prisma.${useName}GroupByArgs['orderBy'] }: { orderBy?: Prisma.${useName}GroupByArgs['orderBy'] },`,
-            `OrderFields extends Prisma.ExcludeUnderscoreKeys<Prisma.Keys<Prisma.MaybeTupleToUnion<T['orderBy']>>>`,
-            `ByFields extends Prisma.MaybeTupleToUnion<T['by']>`,
+            `OrderFields extends Prisma.ExcludeUnderscoreKeys<Prisma.Keys<Prisma.MaybeTupleToUnion<TArgs['orderBy']>>>`,
+            `ByFields extends Prisma.MaybeTupleToUnion<TArgs['by']>`,
             `ByValid extends Prisma.Has<ByFields, OrderFields>`,
-            `HavingFields extends Prisma.GetHavingFields<T['having']>`,
+            `HavingFields extends Prisma.GetHavingFields<TArgs['having']>`,
             `HavingValid extends Prisma.Has<ByFields, HavingFields>`,
-            `ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False`,
+            `ByEmpty extends TArgs['by'] extends never[] ? Prisma.True : Prisma.False`,
             `InputErrors extends ByEmpty extends Prisma.True
             ? \`Error: "by" must not be empty.\`
             : HavingValid extends Prisma.False
@@ -440,8 +458,8 @@ function generateModelHooks(
                     \` in "having" needs to be provided in "by"\`,
                     ]
             }[HavingFields]
-            : 'take' extends Prisma.Keys<T>
-            ? 'orderBy' extends Prisma.Keys<T>
+            : 'take' extends Prisma.Keys<TArgs>
+            ? 'orderBy' extends Prisma.Keys<TArgs>
             ? ByValid extends Prisma.True
                 ? {}
                 : {
@@ -450,8 +468,8 @@ function generateModelHooks(
                     : \`Error: Field "\${P}" in "orderBy" needs to be provided in "by"\`
                 }[OrderFields]
             : 'Error: If you provide "take", you also need to provide "orderBy"'
-            : 'skip' extends Prisma.Keys<T>
-            ? 'orderBy' extends Prisma.Keys<T>
+            : 'skip' extends Prisma.Keys<TArgs>
+            ? 'orderBy' extends Prisma.Keys<TArgs>
             ? ByValid extends Prisma.True
                 ? {}
                 : {
@@ -467,19 +485,11 @@ function generateModelHooks(
                 ? never
                 : \`Error: Field "\${P}" in "orderBy" needs to be provided in "by"\`
             }[OrderFields]`,
+            `TQueryFnData = ${returnType}`,
+            `TData = TQueryFnData`,
+            `TError = DefaultError`,
         ];
 
-        const returnType = `{} extends InputErrors ? 
-        Array<PickEnumerable<Prisma.${modelNameCap}GroupByOutputType, T['by']> &
-          {
-            [P in ((keyof T) & (keyof Prisma.${modelNameCap}GroupByOutputType))]: P extends '_count'
-              ? T[P] extends boolean
-                ? number
-                : Prisma.GetScalarType<T[P], Prisma.${modelNameCap}GroupByOutputType[P]>
-              : Prisma.GetScalarType<T[P], Prisma.${modelNameCap}GroupByOutputType[P]>
-          }
-        > : InputErrors`;
-
         generateQueryHook(
             target,
             version,
@@ -489,7 +499,7 @@ function generateModelHooks(
             false,
             false,
             returnType,
-            `Prisma.SubsetIntersection<T, Prisma.${useName}GroupByArgs, OrderByArg> & InputErrors`,
+            `Prisma.SubsetIntersection<TArgs, Prisma.${useName}GroupByArgs, OrderByArg> & InputErrors`,
             typeParameters
         );
     }
@@ -504,7 +514,7 @@ function generateModelHooks(
             'count',
             false,
             true,
-            `T extends { select: any; } ? T['select'] extends true ? number : Prisma.GetScalarType<T['select'], Prisma.${modelNameCap}CountAggregateOutputType> : number`
+            `TArgs extends { select: any; } ? TArgs['select'] extends true ? number : Prisma.GetScalarType<TArgs['select'], Prisma.${modelNameCap}CountAggregateOutputType> : number`
         );
     }
 }
@@ -552,12 +562,13 @@ function makeBaseImports(target: TargetFramework, version: TanStackVersion) {
         `import { useModelQuery, useInfiniteModelQuery, useModelMutation } from '${runtimeImportBase}/${target}';`,
         `import type { PickEnumerable, CheckSelect } from '${runtimeImportBase}';`,
         `import metadata from './__model_meta';`,
+        `type DefaultError = Error;`,
     ];
     switch (target) {
         case 'react':
             return [
                 `import type { UseMutationOptions, UseQueryOptions, UseInfiniteQueryOptions, InfiniteData } from '@tanstack/react-query';`,
-                `import { RequestHandlerContext, getHooksContext } from '${runtimeImportBase}/${target}';`,
+                `import { getHooksContext } from '${runtimeImportBase}/${target}';`,
                 ...shared,
             ];
         case 'vue':
@@ -573,7 +584,7 @@ function makeBaseImports(target: TargetFramework, version: TanStackVersion) {
                 ...(version === 'v5'
                     ? [`import type { InfiniteData, StoreOrVal } from '@tanstack/svelte-query';`]
                     : []),
-                `import { SvelteQueryContextKey, type RequestHandlerContext, getHooksContext } from '${runtimeImportBase}/${target}';`,
+                `import { getHooksContext } from '${runtimeImportBase}/${target}';`,
                 ...shared,
             ];
         default:
@@ -581,24 +592,30 @@ function makeBaseImports(target: TargetFramework, version: TanStackVersion) {
     }
 }
 
-function makeQueryOptions(target: string, returnType: string, infinite: boolean, version: TanStackVersion) {
+function makeQueryOptions(
+    target: string,
+    returnType: string,
+    dataType: string,
+    infinite: boolean,
+    version: TanStackVersion
+) {
     switch (target) {
         case 'react':
             return infinite
                 ? version === 'v4'
-                    ? `Omit<UseInfiniteQueryOptions<${returnType}>, 'queryKey'>`
-                    : `Omit<UseInfiniteQueryOptions<${returnType}, unknown, InfiniteData<${returnType}>>, 'queryKey'>`
-                : `Omit<UseQueryOptions<${returnType}>, 'queryKey'>`;
+                    ? `Omit<UseInfiniteQueryOptions<${returnType}, TError, ${dataType}>, 'queryKey'>`
+                    : `Omit<UseInfiniteQueryOptions<${returnType}, TError, InfiniteData<${dataType}>>, 'queryKey'>`
+                : `Omit<UseQueryOptions<${returnType}, TError, ${dataType}>, 'queryKey'>`;
         case 'vue':
-            return `Omit<Use${infinite ? 'Infinite' : ''}QueryOptions<${returnType}>, 'queryKey'>`;
+            return `Omit<Use${infinite ? 'Infinite' : ''}QueryOptions<${returnType}, TError, ${dataType}>, 'queryKey'>`;
         case 'svelte':
             return infinite
                 ? version === 'v4'
-                    ? `Omit<CreateInfiniteQueryOptions<${returnType}>, 'queryKey'>`
-                    : `StoreOrVal<Omit<CreateInfiniteQueryOptions<${returnType}, unknown, InfiniteData<${returnType}>>, 'queryKey'>>`
+                    ? `Omit<CreateInfiniteQueryOptions<${returnType}, TError, ${dataType}>, 'queryKey'>`
+                    : `StoreOrVal<Omit<CreateInfiniteQueryOptions<${returnType}, TError, InfiniteData<${dataType}>>, 'queryKey'>>`
                 : version === 'v4'
-                ? `Omit<CreateQueryOptions<${returnType}>, 'queryKey'>`
-                : `StoreOrVal<Omit<CreateQueryOptions<${returnType}>, 'queryKey'>>`;
+                ? `Omit<CreateQueryOptions<${returnType}, TError, ${dataType}>, 'queryKey'>`
+                : `StoreOrVal<Omit<CreateQueryOptions<${returnType}, TError, ${dataType}>, 'queryKey'>>`;
         default:
             throw new PluginError(name, `Unsupported target: ${target}`);
     }
diff --git a/packages/plugins/tanstack-query/src/runtime-v5/react.ts b/packages/plugins/tanstack-query/src/runtime-v5/react.ts
index 907e42595..4871e8229 100644
--- a/packages/plugins/tanstack-query/src/runtime-v5/react.ts
+++ b/packages/plugins/tanstack-query/src/runtime-v5/react.ts
@@ -55,18 +55,18 @@ export const Provider = RequestHandlerContext.Provider;
  * @param optimisticUpdate Whether to enable automatic optimistic update
  * @returns useQuery hook
  */
-export function useModelQuery<R>(
+export function useModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args?: unknown,
-    options?: Omit<UseQueryOptions<R>, 'queryKey'>,
+    options?: Omit<UseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>,
     fetch?: FetchFn,
     optimisticUpdate = false
 ) {
     const reqUrl = makeUrl(url, args);
     return useQuery({
         queryKey: getQueryKey(model, url, args, false, optimisticUpdate),
-        queryFn: () => fetcher<R, false>(reqUrl, undefined, fetch, false),
+        queryFn: () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false),
         ...options,
     });
 }
@@ -81,17 +81,17 @@ export function useModelQuery<R>(
  * @param fetch The fetch function to use for sending the HTTP request
  * @returns useInfiniteQuery hook
  */
-export function useInfiniteModelQuery<R>(
+export function useInfiniteModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args: unknown,
-    options: Omit<UseInfiniteQueryOptions<R, unknown, InfiniteData<R>>, 'queryKey'>,
+    options: Omit<UseInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey'>,
     fetch?: FetchFn
 ) {
     return useInfiniteQuery({
         queryKey: getQueryKey(model, url, args, true),
         queryFn: ({ pageParam }) => {
-            return fetcher<R, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);
+            return fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);
         },
         ...options,
     });
diff --git a/packages/plugins/tanstack-query/src/runtime-v5/svelte.ts b/packages/plugins/tanstack-query/src/runtime-v5/svelte.ts
index d01ed02e4..5f479138e 100644
--- a/packages/plugins/tanstack-query/src/runtime-v5/svelte.ts
+++ b/packages/plugins/tanstack-query/src/runtime-v5/svelte.ts
@@ -5,10 +5,10 @@ import {
     createQuery,
     useQueryClient,
     type CreateInfiniteQueryOptions,
+    type CreateQueryOptions,
     type InfiniteData,
     type MutationOptions,
     type StoreOrVal,
-    type CreateQueryOptions,
 } from '@tanstack/svelte-query-v5';
 import { ModelMeta } from '@zenstackhq/runtime/cross';
 import { getContext, setContext } from 'svelte';
@@ -58,17 +58,17 @@ export function getHooksContext() {
  * @param optimisticUpdate Whether to enable automatic optimistic update
  * @returns useQuery hook
  */
-export function useModelQuery<R>(
+export function useModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args?: unknown,
-    options?: StoreOrVal<Omit<CreateQueryOptions<R>, 'queryKey'>>,
+    options?: StoreOrVal<Omit<CreateQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>>,
     fetch?: FetchFn,
     optimisticUpdate = false
 ) {
     const reqUrl = makeUrl(url, args);
     const queryKey = getQueryKey(model, url, args, false, optimisticUpdate);
-    const queryFn = () => fetcher<R, false>(reqUrl, undefined, fetch, false);
+    const queryFn = () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false);
 
     let mergedOpt: any;
     if (isStore(options)) {
@@ -100,19 +100,19 @@ export function useModelQuery<R>(
  * @param options The svelte-query infinite query options object
  * @returns useQuery hook
  */
-export function useInfiniteModelQuery<R>(
+export function useInfiniteModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args: unknown,
-    options: StoreOrVal<Omit<CreateInfiniteQueryOptions<R, unknown, InfiniteData<R>>, 'queryKey'>>,
+    options: StoreOrVal<Omit<CreateInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>, 'queryKey'>>,
     fetch?: FetchFn
 ) {
     const queryKey = getQueryKey(model, url, args, true);
     const queryFn = ({ pageParam }: { pageParam: unknown }) =>
-        fetcher<R, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);
+        fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);
 
-    let mergedOpt: StoreOrVal<CreateInfiniteQueryOptions<R, unknown, InfiniteData<R>>>;
-    if (isStore<CreateInfiniteQueryOptions<R, unknown, InfiniteData<R>>>(options)) {
+    let mergedOpt: StoreOrVal<CreateInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>>;
+    if (isStore<CreateInfiniteQueryOptions<TQueryFnData, TError, InfiniteData<TData>>>(options)) {
         // options is store
         mergedOpt = derived([options], ([$opt]) => {
             return {
@@ -129,7 +129,7 @@ export function useInfiniteModelQuery<R>(
             ...options,
         };
     }
-    return createInfiniteQuery<R, unknown, InfiniteData<R>>(mergedOpt);
+    return createInfiniteQuery<TQueryFnData, TError, InfiniteData<TData>>(mergedOpt);
 }
 
 function isStore<T>(opt: unknown): opt is Readable<T> {
diff --git a/packages/plugins/tanstack-query/src/runtime/react.ts b/packages/plugins/tanstack-query/src/runtime/react.ts
index 617302a3c..2f75d88eb 100644
--- a/packages/plugins/tanstack-query/src/runtime/react.ts
+++ b/packages/plugins/tanstack-query/src/runtime/react.ts
@@ -55,18 +55,18 @@ export function getHooksContext() {
  * @param optimisticUpdate Whether to enable automatic optimistic update
  * @returns useQuery hook
  */
-export function useModelQuery<R>(
+export function useModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args?: unknown,
-    options?: Omit<UseQueryOptions<R>, 'queryKey'>,
+    options?: Omit<UseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>,
     fetch?: FetchFn,
     optimisticUpdate = false
 ) {
     const reqUrl = makeUrl(url, args);
-    return useQuery<R>({
+    return useQuery<TQueryFnData, TError, TData>({
         queryKey: getQueryKey(model, url, args, false, optimisticUpdate),
-        queryFn: () => fetcher<R, false>(reqUrl, undefined, fetch, false),
+        queryFn: () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false),
         ...options,
     });
 }
@@ -81,17 +81,17 @@ export function useModelQuery<R>(
  * @param fetch The fetch function to use for sending the HTTP request
  * @returns useInfiniteQuery hook
  */
-export function useInfiniteModelQuery<R>(
+export function useInfiniteModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args?: unknown,
-    options?: Omit<UseInfiniteQueryOptions<R>, 'queryKey'>,
+    options?: Omit<UseInfiniteQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>,
     fetch?: FetchFn
 ) {
-    return useInfiniteQuery<R>({
+    return useInfiniteQuery<TQueryFnData, TError, TData>({
         queryKey: getQueryKey(model, url, args, true),
         queryFn: ({ pageParam }) => {
-            return fetcher<R, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);
+            return fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);
         },
         ...options,
     });
diff --git a/packages/plugins/tanstack-query/src/runtime/svelte.ts b/packages/plugins/tanstack-query/src/runtime/svelte.ts
index 84a175f58..88c675a82 100644
--- a/packages/plugins/tanstack-query/src/runtime/svelte.ts
+++ b/packages/plugins/tanstack-query/src/runtime/svelte.ts
@@ -5,8 +5,8 @@ import {
     createQuery,
     useQueryClient,
     type CreateInfiniteQueryOptions,
-    type MutationOptions,
     type CreateQueryOptions,
+    type MutationOptions,
 } from '@tanstack/svelte-query';
 import { ModelMeta } from '@zenstackhq/runtime/cross';
 import { getContext, setContext } from 'svelte';
@@ -55,18 +55,18 @@ export function getHooksContext() {
  * @param optimisticUpdate Whether to enable automatic optimistic update
  * @returns useQuery hook
  */
-export function useModelQuery<R>(
+export function useModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args?: unknown,
-    options?: Omit<CreateQueryOptions<R>, 'queryKey'>,
+    options?: Omit<CreateQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>,
     fetch?: FetchFn,
     optimisticUpdate = false
 ) {
     const reqUrl = makeUrl(url, args);
-    return createQuery<R>({
+    return createQuery<TQueryFnData, TError, TData>({
         queryKey: getQueryKey(model, url, args, false, optimisticUpdate),
-        queryFn: () => fetcher<R, false>(reqUrl, undefined, fetch, false),
+        queryFn: () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false),
         ...options,
     });
 }
@@ -81,16 +81,17 @@ export function useModelQuery<R>(
  * @param fetch The fetch function to use for sending the HTTP request
  * @returns useQuery hook
  */
-export function useInfiniteModelQuery<R>(
+export function useInfiniteModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args?: unknown,
-    options?: Omit<CreateInfiniteQueryOptions<R>, 'queryKey'>,
+    options?: Omit<CreateInfiniteQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>,
     fetch?: FetchFn
 ) {
-    return createInfiniteQuery<R>({
+    return createInfiniteQuery<TQueryFnData, TError, TData>({
         queryKey: getQueryKey(model, url, args, true),
-        queryFn: ({ pageParam }) => fetcher<R, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false),
+        queryFn: ({ pageParam }) =>
+            fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false),
         ...options,
     });
 }
diff --git a/packages/plugins/tanstack-query/src/runtime/vue.ts b/packages/plugins/tanstack-query/src/runtime/vue.ts
index fe6cfc6a2..a0f1055e8 100644
--- a/packages/plugins/tanstack-query/src/runtime/vue.ts
+++ b/packages/plugins/tanstack-query/src/runtime/vue.ts
@@ -57,18 +57,18 @@ export function getHooksContext() {
  * @param optimisticUpdate Whether to enable automatic optimistic update
  * @returns useQuery hook
  */
-export function useModelQuery<R>(
+export function useModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args?: unknown,
-    options?: UseQueryOptions<R>,
+    options?: UseQueryOptions<TQueryFnData, TError, TData>,
     fetch?: FetchFn,
     optimisticUpdate = false
 ) {
     const reqUrl = makeUrl(url, args);
-    return useQuery<R>({
+    return useQuery<TQueryFnData, TError, TData>({
         queryKey: getQueryKey(model, url, args, false, optimisticUpdate),
-        queryFn: () => fetcher<R, false>(reqUrl, undefined, fetch, false),
+        queryFn: () => fetcher<TQueryFnData, false>(reqUrl, undefined, fetch, false),
         ...options,
     });
 }
@@ -83,17 +83,17 @@ export function useModelQuery<R>(
  * @param fetch The fetch function to use for sending the HTTP request
  * @returns useInfiniteQuery hook
  */
-export function useInfiniteModelQuery<R>(
+export function useInfiniteModelQuery<TQueryFnData, TData, TError>(
     model: string,
     url: string,
     args?: unknown,
-    options?: UseInfiniteQueryOptions<R>,
+    options?: UseInfiniteQueryOptions<TQueryFnData, TError, TData>,
     fetch?: FetchFn
 ) {
-    return useInfiniteQuery<R>({
+    return useInfiniteQuery<TQueryFnData, TError, TData>({
         queryKey: getQueryKey(model, url, args, true),
         queryFn: ({ pageParam }) => {
-            return fetcher<R, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);
+            return fetcher<TQueryFnData, false>(makeUrl(url, pageParam ?? args), undefined, fetch, false);
         },
         ...options,
     });
diff --git a/packages/plugins/tanstack-query/tests/plugin.test.ts b/packages/plugins/tanstack-query/tests/plugin.test.ts
index 49a99df94..38370d38a 100644
--- a/packages/plugins/tanstack-query/tests/plugin.test.ts
+++ b/packages/plugins/tanstack-query/tests/plugin.test.ts
@@ -61,7 +61,7 @@ ${sharedModel}
                 provider: 'postgresql',
                 pushDb: false,
                 extraDependencies: ['react@18.2.0', '@types/react@18.2.0', '@tanstack/react-query@4.29.7'],
-                copyDependencies: [`${origDir}/dist`],
+                copyDependencies: [`${path.join(__dirname, '..')}/dist`],
                 compile: true,
             }
         );
@@ -83,7 +83,7 @@ ${sharedModel}
                 provider: 'postgresql',
                 pushDb: false,
                 extraDependencies: ['react@18.2.0', '@types/react@18.2.0', '@tanstack/react-query@^5.0.0'],
-                copyDependencies: [`${origDir}/dist`],
+                copyDependencies: [`${path.join(__dirname, '..')}/dist`],
                 compile: true,
             }
         );
@@ -104,7 +104,7 @@ ${sharedModel}
                 provider: 'postgresql',
                 pushDb: false,
                 extraDependencies: ['vue@^3.3.4', '@tanstack/vue-query@4.37.0'],
-                copyDependencies: [`${origDir}/dist`],
+                copyDependencies: [`${path.join(__dirname, '..')}/dist`],
                 compile: true,
             }
         );
@@ -126,7 +126,7 @@ ${sharedModel}
                 provider: 'postgresql',
                 pushDb: false,
                 extraDependencies: ['vue@^3.3.4', '@tanstack/vue-query@latest'],
-                copyDependencies: [`${origDir}/dist`],
+                copyDependencies: [`${path.join(__dirname, '..')}/dist`],
                 compile: true,
             }
         );
@@ -147,7 +147,7 @@ ${sharedModel}
                 provider: 'postgresql',
                 pushDb: false,
                 extraDependencies: ['svelte@^3.0.0', '@tanstack/svelte-query@4.29.7'],
-                copyDependencies: [`${origDir}/dist`],
+                copyDependencies: [`${path.join(__dirname, '..')}/dist`],
                 compile: true,
             }
         );
@@ -169,7 +169,7 @@ ${sharedModel}
                 provider: 'postgresql',
                 pushDb: false,
                 extraDependencies: ['svelte@^3.0.0', '@tanstack/svelte-query@^5.0.0'],
-                copyDependencies: [`${origDir}/dist`],
+                copyDependencies: [`${path.join(__dirname, '..')}/dist`],
                 compile: true,
             }
         );
diff --git a/packages/plugins/trpc/package.json b/packages/plugins/trpc/package.json
index 4d72c799b..cd82c3aad 100644
--- a/packages/plugins/trpc/package.json
+++ b/packages/plugins/trpc/package.json
@@ -1,7 +1,7 @@
 {
     "name": "@zenstackhq/trpc",
     "displayName": "ZenStack plugin for tRPC",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "description": "ZenStack plugin for tRPC",
     "main": "index.js",
     "repository": {
diff --git a/packages/plugins/trpc/src/generator.ts b/packages/plugins/trpc/src/generator.ts
index 0a340be1a..0d252cabc 100644
--- a/packages/plugins/trpc/src/generator.ts
+++ b/packages/plugins/trpc/src/generator.ts
@@ -99,6 +99,7 @@ function createAppRouter(
     appRouter.addImportDeclarations([
         {
             namedImports: [
+                'unsetMarker',
                 'type AnyRouter',
                 'type AnyRootConfig',
                 'type CreateRouterInner',
@@ -111,15 +112,12 @@ function createAppRouter(
             moduleSpecifier: '@trpc/server',
         },
         {
-            namedImports: ['type PrismaClient', 'type Prisma'],
+            namedImports: ['type PrismaClient'],
             moduleSpecifier: prismaImport,
         },
-        { defaultImport: 'z', moduleSpecifier: 'zod', isTypeOnly: true },
     ]);
 
     appRouter.addStatements(`
-        ${/** to be used by the other routers without making a bigger commit */ ''}
-        export { PrismaClient } from '${prismaImport}'; 
 
         export type BaseConfig = AnyRootConfig;
 
@@ -129,56 +127,11 @@ function createAppRouter(
             procedures: ProcRouterRecord
         ) => CreateRouterInner<Config, ProcRouterRecord>;
             
-        ${
-            /** this is needed in order to prevent type errors between a procedure and a middleware-extended procedure */ ''
-        }
-        export type ProcBuilder<Config extends BaseConfig> = ProcedureBuilder<{
-            _config: Config;
-            _ctx_out: Config['$types']['ctx'];
-            _input_in: any;
-            _input_out: any;
-            _output_in: any;
-            _output_out: any;
-            _meta: Config['$types']['meta'];
-        }>;
-
-        type ExtractParamsFromProcBuilder<Builder extends ProcedureBuilder<any>> =
-            Builder extends ProcedureBuilder<infer P> ? P : never;
-        
-        type FromPromise<P extends Promise<any>> = P extends Promise<infer T>
-            ? T
-            : never;
-          
-        ${/** workaround to avoid creating 'typeof unsetMarker & object' on the procedure output */ ''}
-        type Join<A, B> = A extends symbol ? B : A & B;
-
-        ${
-            /** you can name it whatever you want, but this is to make sure that 
-                the types from the middleware and the procedure are correctly merged */ ''
-        }
-        export type ProcReturns<
-            PType extends ProcedureType,
-            PBuilder extends ProcBuilder<BaseConfig>,
-            ZType extends z.ZodType,
-            PPromise extends Prisma.PrismaPromise<any>
-        > = Procedure<
-                PType,
-                ProcedureParams<
-                    ExtractParamsFromProcBuilder<PBuilder>["_config"],
-                    ExtractParamsFromProcBuilder<PBuilder>["_ctx_out"],
-                    Join<ExtractParamsFromProcBuilder<PBuilder>["_input_in"], z.infer<ZType>>,
-                    Join<ExtractParamsFromProcBuilder<PBuilder>["_input_out"], z.infer<ZType>>,
-                    Join<
-                        ExtractParamsFromProcBuilder<PBuilder>["_output_in"],
-                        FromPromise<PPromise>
-                    >,
-                    Join<
-                        ExtractParamsFromProcBuilder<PBuilder>["_output_out"],
-                        FromPromise<PPromise>
-                    >,
-                    ExtractParamsFromProcBuilder<PBuilder>["_meta"]
-                >
-            >;
+        export type UnsetMarker = typeof unsetMarker;
+
+        export type ProcBuilder<Config extends BaseConfig> = ProcedureBuilder<
+            ProcedureParams<Config, any, any, any, UnsetMarker, UnsetMarker, any>
+        >;
 
         export function db(ctx: any) {
             if (!ctx.prisma) {
@@ -193,10 +146,10 @@ function createAppRouter(
 
     appRouter
         .addFunction({
-            name: 'createRouter<Router extends RouterFactory<BaseConfig>, Proc extends ProcBuilder<BaseConfig>>',
+            name: 'createRouter<Config extends BaseConfig>',
             parameters: [
-                { name: 'router', type: 'Router' },
-                { name: 'procedure', type: 'Proc' },
+                { name: 'router', type: 'RouterFactory<Config>' },
+                { name: 'procedure', type: 'ProcBuilder<Config>' },
             ],
             isExported: true,
         })
@@ -225,9 +178,7 @@ function createAppRouter(
                         moduleSpecifier: `./${model}.router`,
                     });
 
-                    writer.writeLine(
-                        `${lowerCaseFirst(model)}: create${model}Router<Router, Proc>(router, procedure),`
-                    );
+                    writer.writeLine(`${lowerCaseFirst(model)}: create${model}Router(router, procedure),`);
                 }
             });
             writer.write(');');
@@ -299,14 +250,7 @@ function generateModelCreateRouter(
 
     modelRouter.addImportDeclarations([
         {
-            namedImports: [
-                'type RouterFactory',
-                'type ProcBuilder',
-                'type BaseConfig',
-                'type ProcReturns',
-                'type PrismaClient',
-                'db',
-            ],
+            namedImports: ['type RouterFactory', 'type ProcBuilder', 'type BaseConfig', 'db'],
             moduleSpecifier: '.',
         },
     ]);
@@ -318,10 +262,10 @@ function generateModelCreateRouter(
     }
 
     const createRouterFunc = modelRouter.addFunction({
-        name: 'createRouter<Router extends RouterFactory<BaseConfig>, Proc extends ProcBuilder<BaseConfig>>',
+        name: 'createRouter<Config extends BaseConfig>',
         parameters: [
-            { name: 'router', type: 'Router' },
-            { name: 'procedure', type: 'Proc' },
+            { name: 'router', type: 'RouterFactory<Config>' },
+            { name: 'procedure', type: 'ProcBuilder<Config>' },
         ],
         isExported: true,
         isDefaultExport: true,
diff --git a/packages/plugins/trpc/src/helpers.ts b/packages/plugins/trpc/src/helpers.ts
index 1fbeb9efd..54aec3ecb 100644
--- a/packages/plugins/trpc/src/helpers.ts
+++ b/packages/plugins/trpc/src/helpers.ts
@@ -21,24 +21,14 @@ export function generateProcedure(
         writer.write(`
         ${opType}: procedure.input(${typeName}).query(({ctx, input}) => checkRead(db(ctx).${lowerCaseFirst(
             modelName
-        )}.${prismaMethod}(input as any))) as ProcReturns<
-            "query",
-            Proc,
-            (typeof $Schema.${upperCaseFirst(modelName)}InputSchema)["${opType.replace('OrThrow', '')}"],
-            ReturnType<PrismaClient["${lowerCaseFirst(modelName)}"]["${opType}"]>
-        >,
+        )}.${prismaMethod}(input as any))),
     `);
     } else if (procType === 'mutation') {
         // the cast "as any" is to circumvent a TS compiler misfired error in certain cases
         writer.write(`
         ${opType}: procedure.input(${typeName}).mutation(async ({ctx, input}) => checkMutate(db(ctx).${lowerCaseFirst(
             modelName
-        )}.${prismaMethod}(input as any))) as ProcReturns<
-                "mutation",
-                Proc,
-                (typeof $Schema.${upperCaseFirst(modelName)}InputSchema)["${opType.replace('OrThrow', '')}"],
-                ReturnType<PrismaClient["${lowerCaseFirst(modelName)}"]["${opType}"]>
-            >,
+        )}.${prismaMethod}(input as any))),
     `);
     }
 }
@@ -203,18 +193,18 @@ export function generateRouterTyping(writer: CodeBlockWriter, opType: string, mo
     writer.block(() => {
         if (procType === 'query') {
             writer.writeLine(`
-                useQuery: <T extends ${genericBase}>(
+                useQuery: <T extends ${genericBase}, TData = ${resultType}>(
                     input: ${argsType},
-                    opts?: UseTRPCQueryOptions<string, T, ${resultType}, ${resultType}, Error>
+                    opts?: UseTRPCQueryOptions<string, T, ${resultType}, TData, Error>
                     ) => UseTRPCQueryResult<
-                    ${resultType},
+                        TData,
                         ${errorType}
                     >;
                 useInfiniteQuery: <T extends ${genericBase}>(
                     input: Omit<${argsType}, 'cursor'>,
                     opts?: UseTRPCInfiniteQueryOptions<string, T, ${resultType}, Error>
                     ) => UseTRPCInfiniteQueryResult<
-                    ${resultType},
+                        ${resultType},
                         ${errorType}
                     >;
                     `);
@@ -223,7 +213,7 @@ export function generateRouterTyping(writer: CodeBlockWriter, opType: string, mo
                 useMutation: <T extends ${genericBase}>(opts?: UseTRPCMutationOptions<
                     ${genericBase},
                     ${errorType},
-                    Prisma.${upperCaseFirst(modelName)}GetPayload<null>,
+                    ${resultType},
                     Context
                 >,) =>
                 Omit<UseTRPCMutationResult<${resultType}, ${errorType}, ${argsType}, Context>, 'mutateAsync'> & {
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/.eslintrc.cjs b/packages/plugins/trpc/tests/projects/t3-trpc-v10/.eslintrc.cjs
new file mode 100644
index 000000000..c946e46e0
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/.eslintrc.cjs
@@ -0,0 +1,37 @@
+/** @type {import("eslint").Linter.Config} */
+const config = {
+  parser: "@typescript-eslint/parser",
+  parserOptions: {
+    project: true,
+  },
+  plugins: ["@typescript-eslint"],
+  extends: [
+    "next/core-web-vitals",
+    "plugin:@typescript-eslint/recommended-type-checked",
+    "plugin:@typescript-eslint/stylistic-type-checked",
+  ],
+  rules: {
+    // These opinionated rules are enabled in stylistic-type-checked above.
+    // Feel free to reconfigure them to your own preference.
+    "@typescript-eslint/array-type": "off",
+    "@typescript-eslint/consistent-type-definitions": "off",
+
+    "@typescript-eslint/consistent-type-imports": [
+      "warn",
+      {
+        prefer: "type-imports",
+        fixStyle: "inline-type-imports",
+      },
+    ],
+    "@typescript-eslint/no-unused-vars": ["warn", { argsIgnorePattern: "^_" }],
+    "@typescript-eslint/require-await": "off",
+    "@typescript-eslint/no-misused-promises": [
+      "error",
+      {
+        checksVoidReturn: { attributes: false },
+      },
+    ],
+  },
+};
+
+module.exports = config;
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/.gitignore b/packages/plugins/trpc/tests/projects/t3-trpc-v10/.gitignore
new file mode 100644
index 000000000..b9331d6ce
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/.gitignore
@@ -0,0 +1,43 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# database
+/prisma/db.sqlite
+/prisma/db.sqlite-journal
+
+# next.js
+/.next/
+/out/
+next-env.d.ts
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+.pnpm-debug.log*
+
+# local env files
+# do not commit any .env files to git, except for the .env.example file. https://create.t3.gg/en/usage/env-variables#using-environment-variables
+.env
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+package-lock.json
\ No newline at end of file
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/README.md b/packages/plugins/trpc/tests/projects/t3-trpc-v10/README.md
new file mode 100644
index 000000000..fba19edac
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/README.md
@@ -0,0 +1,28 @@
+# Create T3 App
+
+This is a [T3 Stack](https://create.t3.gg/) project bootstrapped with `create-t3-app`.
+
+## What's next? How do I make an app with this?
+
+We try to keep this project as simple as possible, so you can start with just the scaffolding we set up for you, and add additional things later when they become necessary.
+
+If you are not familiar with the different technologies used in this project, please refer to the respective docs. If you still are in the wind, please join our [Discord](https://t3.gg/discord) and ask for help.
+
+- [Next.js](https://nextjs.org)
+- [NextAuth.js](https://next-auth.js.org)
+- [Prisma](https://prisma.io)
+- [Tailwind CSS](https://tailwindcss.com)
+- [tRPC](https://trpc.io)
+
+## Learn More
+
+To learn more about the [T3 Stack](https://create.t3.gg/), take a look at the following resources:
+
+- [Documentation](https://create.t3.gg/)
+- [Learn the T3 Stack](https://create.t3.gg/en/faq#what-learning-resources-are-currently-available) — Check out these awesome tutorials
+
+You can check out the [create-t3-app GitHub repository](https://github.com/t3-oss/create-t3-app) — your feedback and contributions are welcome!
+
+## How do I deploy this?
+
+Follow our deployment guides for [Vercel](https://create.t3.gg/en/deployment/vercel), [Netlify](https://create.t3.gg/en/deployment/netlify) and [Docker](https://create.t3.gg/en/deployment/docker) for more information.
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/next.config.js b/packages/plugins/trpc/tests/projects/t3-trpc-v10/next.config.js
new file mode 100644
index 000000000..ffbeb9fb4
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/next.config.js
@@ -0,0 +1,22 @@
+/**
+ * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially useful
+ * for Docker builds.
+ */
+await import("./src/env.js");
+
+/** @type {import("next").NextConfig} */
+const config = {
+  reactStrictMode: true,
+
+  /**
+   * If you are using `appDir` then you must comment the below `i18n` config out.
+   *
+   * @see https://github.com/vercel/next.js/issues/41980
+   */
+  i18n: {
+    locales: ["en"],
+    defaultLocale: "en",
+  },
+};
+
+export default config;
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/package.json b/packages/plugins/trpc/tests/projects/t3-trpc-v10/package.json
new file mode 100644
index 000000000..a9c99ebba
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/package.json
@@ -0,0 +1,45 @@
+{
+  "name": "t3-trpc-v10",
+  "version": "0.1.0",
+  "private": true,
+  "type": "module",
+  "scripts": {
+    "build": "next build",
+    "db:push": "prisma db push",
+    "db:studio": "prisma studio",
+    "dev": "next dev",
+    "postinstall": "prisma generate",
+    "lint": "next lint",
+    "start": "next start"
+  },
+  "dependencies": {
+    "@prisma/client": "^5.6.0",
+    "@t3-oss/env-nextjs": "^0.7.1",
+    "@tanstack/react-query": "^4.36.1",
+    "@trpc/client": "^10.43.6",
+    "@trpc/next": "^10.43.6",
+    "@trpc/react-query": "^10.43.6",
+    "@trpc/server": "^10.43.6",
+    "next": "^14.0.4",
+    "react": "18.2.0",
+    "react-dom": "18.2.0",
+    "superjson": "^2.2.1",
+    "zod": "^3.22.4"
+  },
+  "devDependencies": {
+    "@types/eslint": "^8.44.7",
+    "@types/node": "^18.17.0",
+    "@types/react": "^18.2.37",
+    "@types/react-dom": "^18.2.15",
+    "@typescript-eslint/eslint-plugin": "^6.11.0",
+    "@typescript-eslint/parser": "^6.11.0",
+    "eslint": "^8.54.0",
+    "eslint-config-next": "^14.0.4",
+    "prisma": "^5.6.0",
+    "typescript": "^5.1.6"
+  },
+  "ct3aMetadata": {
+    "initVersion": "7.26.0"
+  },
+  "packageManager": "npm@10.2.3"
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/prisma/schema.prisma b/packages/plugins/trpc/tests/projects/t3-trpc-v10/prisma/schema.prisma
new file mode 100644
index 000000000..2a0b2142a
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/prisma/schema.prisma
@@ -0,0 +1,31 @@
+//////////////////////////////////////////////////////////////////////////////////////////////
+// DO NOT MODIFY THIS FILE                                                                  //
+// This file is automatically generated by ZenStack CLI and should not be manually updated. //
+//////////////////////////////////////////////////////////////////////////////////////////////
+
+datasource db {
+    provider = "sqlite"
+    url = "file:./dev.db"
+}
+
+generator client {
+    provider = "prisma-client-js"
+}
+
+model User {
+    id Int @id() @default(autoincrement())
+    email String @unique()
+    posts Post[]
+}
+
+model Post {
+    id Int @id() @default(autoincrement())
+    name String
+    createdAt DateTime @default(now())
+    updatedAt DateTime @updatedAt()
+    published Boolean @default(false)
+    author User @relation(fields: [authorId], references: [id])
+    authorId Int
+
+    @@index([name])
+}
\ No newline at end of file
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/public/favicon.ico b/packages/plugins/trpc/tests/projects/t3-trpc-v10/public/favicon.ico
new file mode 100644
index 000000000..60c702aac
Binary files /dev/null and b/packages/plugins/trpc/tests/projects/t3-trpc-v10/public/favicon.ico differ
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/schema.zmodel b/packages/plugins/trpc/tests/projects/t3-trpc-v10/schema.zmodel
new file mode 100644
index 000000000..01c23bd80
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/schema.zmodel
@@ -0,0 +1,35 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+    provider = "prisma-client-js"
+}
+
+datasource db {
+    provider = "sqlite"
+    url      = "file:./dev.db"
+}
+
+plugin trpc {
+    provider = "../../../dist"
+    output = "src/server/api/routers/generated"
+    generateClientHelpers = "next"
+}
+
+model User {
+    id Int @id @default(autoincrement())
+    email String @unique
+    posts Post[]
+}
+
+model Post {
+    id Int @id @default(autoincrement())
+    name String
+    createdAt DateTime @default(now())
+    updatedAt DateTime @updatedAt
+    published Boolean @default(false)
+    author User @relation(fields: [authorId], references: [id])
+    authorId Int
+
+    @@index([name])
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/env.js b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/env.js
new file mode 100644
index 000000000..d0ba1eb56
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/env.js
@@ -0,0 +1,40 @@
+import { createEnv } from '@t3-oss/env-nextjs';
+import { z } from 'zod';
+
+export const env = createEnv({
+    /**
+     * Specify your server-side environment variables schema here. This way you can ensure the app
+     * isn't built with invalid env vars.
+     */
+    server: {
+        NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
+    },
+
+    /**
+     * Specify your client-side environment variables schema here. This way you can ensure the app
+     * isn't built with invalid env vars. To expose them to the client, prefix them with
+     * `NEXT_PUBLIC_`.
+     */
+    client: {
+        // NEXT_PUBLIC_CLIENTVAR: z.string(),
+    },
+
+    /**
+     * You can't destruct `process.env` as a regular object in the Next.js edge runtimes (e.g.
+     * middlewares) or client-side so we need to destruct manually.
+     */
+    runtimeEnv: {
+        NODE_ENV: process.env.NODE_ENV,
+        // NEXT_PUBLIC_CLIENTVAR: process.env.NEXT_PUBLIC_CLIENTVAR,
+    },
+    /**
+     * Run `build` or `dev` with `SKIP_ENV_VALIDATION` to skip env validation. This is especially
+     * useful for Docker builds.
+     */
+    skipValidation: !!process.env.SKIP_ENV_VALIDATION,
+    /**
+     * Makes it so that empty strings are treated as undefined.
+     * `SOME_VAR: z.string()` and `SOME_VAR=''` will throw an error.
+     */
+    emptyStringAsUndefined: true,
+});
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/_app.tsx b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/_app.tsx
new file mode 100644
index 000000000..18319174e
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/_app.tsx
@@ -0,0 +1,11 @@
+import { type AppType } from "next/app";
+
+import { api } from "~/utils/api";
+
+import "~/styles/globals.css";
+
+const MyApp: AppType = ({ Component, pageProps }) => {
+  return <Component {...pageProps} />;
+};
+
+export default api.withTRPC(MyApp);
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/api/trpc/[trpc].ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/api/trpc/[trpc].ts
new file mode 100644
index 000000000..587dd2bdf
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/api/trpc/[trpc].ts
@@ -0,0 +1,19 @@
+import { createNextApiHandler } from "@trpc/server/adapters/next";
+
+import { env } from "~/env";
+import { appRouter } from "~/server/api/root";
+import { createTRPCContext } from "~/server/api/trpc";
+
+// export API handler
+export default createNextApiHandler({
+  router: appRouter,
+  createContext: createTRPCContext,
+  onError:
+    env.NODE_ENV === "development"
+      ? ({ path, error }) => {
+          console.error(
+            `❌ tRPC failed on ${path ?? "<no-path>"}: ${error.message}`
+          );
+        }
+      : undefined,
+});
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.module.css b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.module.css
new file mode 100644
index 000000000..fac9982a3
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.module.css
@@ -0,0 +1,177 @@
+.main {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  min-height: 100vh;
+  background-image: linear-gradient(to bottom, #2e026d, #15162c);
+}
+
+.container {
+  width: 100%;
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: 3rem;
+  padding: 4rem 1rem;
+}
+
+@media (min-width: 640px) {
+  .container {
+    max-width: 640px;
+  }
+}
+
+@media (min-width: 768px) {
+  .container {
+    max-width: 768px;
+  }
+}
+
+@media (min-width: 1024px) {
+  .container {
+    max-width: 1024px;
+  }
+}
+
+@media (min-width: 1280px) {
+  .container {
+    max-width: 1280px;
+  }
+}
+
+@media (min-width: 1536px) {
+  .container {
+    max-width: 1536px;
+  }
+}
+
+.title {
+  font-size: 3rem;
+  line-height: 1;
+  font-weight: 800;
+  letter-spacing: -0.025em;
+  margin: 0;
+  color: white;
+}
+
+@media (min-width: 640px) {
+  .title {
+    font-size: 5rem;
+  }
+}
+
+.pinkSpan {
+  color: hsl(280 100% 70%);
+}
+
+.cardRow {
+  display: grid;
+  grid-template-columns: repeat(1, minmax(0, 1fr));
+  gap: 1rem;
+}
+
+@media (min-width: 640px) {
+  .cardRow {
+    grid-template-columns: repeat(2, minmax(0, 1fr));
+  }
+}
+
+@media (min-width: 768px) {
+  .cardRow {
+    gap: 2rem;
+  }
+}
+
+.card {
+  max-width: 20rem;
+  display: flex;
+  flex-direction: column;
+  gap: 1rem;
+  padding: 1rem;
+  border-radius: 0.75rem;
+  color: white;
+  background-color: rgb(255 255 255 / 0.1);
+}
+
+.card:hover {
+  background-color: rgb(255 255 255 / 0.2);
+  transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);
+}
+
+.cardTitle {
+  font-size: 1.5rem;
+  line-height: 2rem;
+  font-weight: 700;
+  margin: 0;
+}
+
+.cardText {
+  font-size: 1.125rem;
+  line-height: 1.75rem;
+}
+
+.showcaseContainer {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  gap: 0.5rem;
+}
+
+.showcaseText {
+  color: white;
+  text-align: center;
+  font-size: 1.5rem;
+  line-height: 2rem;
+}
+
+.authContainer {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  justify-content: center;
+  gap: 1rem;
+}
+
+.loginButton {
+  border-radius: 9999px;
+  background-color: rgb(255 255 255 / 0.1);
+  padding: 0.75rem 2.5rem;
+  font-weight: 600;
+  color: white;
+  text-decoration-line: none;
+  transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);
+}
+
+.loginButton:hover {
+  background-color: rgb(255 255 255 / 0.2);
+}
+
+.form {
+  display: flex;
+  flex-direction: column;
+  gap: 0.5rem;
+}
+
+.input {
+  width: 100%;
+  border-radius: 9999px;
+  padding: 0.5rem 1rem;
+  color: black;
+}
+
+.submitButton {
+  all: unset;
+  border-radius: 9999px;
+  background-color: rgb(255 255 255 / 0.1);
+  padding: 0.75rem 2.5rem;
+  font-weight: 600;
+  color: white;
+  text-align: center;
+  transition: background-color 150ms cubic-bezier(0.5, 0, 0.2, 1);
+}
+
+.submitButton:hover {
+  background-color: rgb(255 255 255 / 0.2);
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.tsx b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.tsx
new file mode 100644
index 000000000..50a3d3e7d
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/pages/index.tsx
@@ -0,0 +1,23 @@
+import { api } from '~/utils/api';
+import styles from './index.module.css';
+
+export default function Home() {
+    const hello = api.greet.hello.useQuery({ text: 'from tRPC' });
+    const posts = api.post.findMany.useQuery({ where: { published: true }, include: { author: true } });
+    const postsTransformed = api.post.findMany.useQuery({}, { select: (data) => data.map((p) => ({ title: p.name })) });
+
+    return (
+        <>
+            <main className={styles.main}>
+                {hello.data && <h1 className={styles.title}>{hello.data.greeting}</h1>}
+                {posts.data &&
+                    posts.data.map((post) => (
+                        <p>
+                            {post.name} by {post.author.email}
+                        </p>
+                    ))}
+                {postsTransformed.data && postsTransformed.data.map((post) => <p>{post.title}</p>)}
+            </main>
+        </>
+    );
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/root.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/root.ts
new file mode 100644
index 000000000..397c562bf
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/root.ts
@@ -0,0 +1,16 @@
+import { greetRouter } from '~/server/api/routers/greet';
+import { createTRPCRouter } from '~/server/api/trpc';
+import { postRouter } from './routers/post';
+
+/**
+ * This is the primary router for your server.
+ *
+ * All routers added in /api/routers should be manually added here.
+ */
+export const appRouter = createTRPCRouter({
+    greet: greetRouter,
+    post: postRouter,
+});
+
+// export type definition of API
+export type AppRouter = typeof appRouter;
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/client/next.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/client/next.ts
new file mode 100644
index 000000000..982ab7980
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/client/next.ts
@@ -0,0 +1,17 @@
+/* eslint-disable */
+
+import type { AnyRouter } from '@trpc/server';
+import type { NextPageContext } from 'next';
+import { type CreateTRPCNext, createTRPCNext as _createTRPCNext } from '@trpc/next';
+import type { DeepOverrideAtPath } from './utils';
+import type { ClientType } from '../routers';
+
+export function createTRPCNext<
+    TRouter extends AnyRouter,
+    TPath extends string | undefined = undefined,
+    TSSRContext extends NextPageContext = NextPageContext,
+    TFlags = null,
+>(opts: Parameters<typeof _createTRPCNext>[0]) {
+    const r: CreateTRPCNext<TRouter, TSSRContext, TFlags> = _createTRPCNext<TRouter, TSSRContext, TFlags>(opts);
+    return r as DeepOverrideAtPath<CreateTRPCNext<TRouter, TSSRContext, TFlags>, ClientType<TRouter>, TPath>;
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/client/utils.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/client/utils.ts
new file mode 100644
index 000000000..223fde54d
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/client/utils.ts
@@ -0,0 +1,32 @@
+/* eslint-disable */
+
+// inspired by: https://stackoverflow.com/questions/70632026/generic-to-recursively-modify-a-given-type-interface-in-typescript
+
+type Primitive = string | Function | number | boolean | Symbol | undefined | null;
+
+/**
+ * Recursively merges `T` and `R`. If there's a shared key, use `R`'s field type to overwrite `T`.
+ */
+export type DeepOverride<T, R> = T extends Primitive
+    ? R
+    : R extends Primitive
+    ? R
+    : {
+          [K in keyof T]: K extends keyof R ? DeepOverride<T[K], R[K]> : T[K];
+      } & {
+          [K in Exclude<keyof R, keyof T>]: R[K];
+      };
+
+/**
+ * Traverse to `Path` (denoted by dot separated string literal type) in `T`, and starting from there,
+ * recursively merge with `R`.
+ */
+export type DeepOverrideAtPath<T, R, Path extends string | undefined = undefined> = Path extends undefined
+    ? DeepOverride<T, R>
+    : Path extends `${infer P1}.${infer P2}`
+    ? P1 extends keyof T
+        ? Omit<T, P1> & Record<P1, DeepOverride<T[P1], DeepOverrideAtPath<T[P1], R, P2>>>
+        : never
+    : Path extends keyof T
+    ? Omit<T, Path> & Record<Path, DeepOverride<T[Path], R>>
+    : never;
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/helper.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/helper.ts
new file mode 100644
index 000000000..45e24e20e
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/helper.ts
@@ -0,0 +1,67 @@
+/* eslint-disable */
+import { TRPCError } from '@trpc/server';
+import { isPrismaClientKnownRequestError } from '@zenstackhq/runtime';
+
+export async function checkMutate<T>(promise: Promise<T>): Promise<T | undefined> {
+    try {
+        return await promise;
+    } catch (err: any) {
+        if (isPrismaClientKnownRequestError(err)) {
+            if (err.code === 'P2004') {
+                if (err.meta?.reason === 'RESULT_NOT_READABLE') {
+                    // unable to readback data
+                    return undefined;
+                } else {
+                    // rejected by policy
+                    throw new TRPCError({
+                        code: 'FORBIDDEN',
+                        message: err.message,
+                        cause: err,
+                    });
+                }
+            } else {
+                // request error
+                throw new TRPCError({
+                    code: 'BAD_REQUEST',
+                    message: err.message,
+                    cause: err,
+                });
+            }
+        } else {
+            throw err;
+        }
+    }
+}
+
+export async function checkRead<T>(promise: Promise<T>): Promise<T> {
+    try {
+        return await promise;
+    } catch (err: any) {
+        if (isPrismaClientKnownRequestError(err)) {
+            if (err.code === 'P2004') {
+                // rejected by policy
+                throw new TRPCError({
+                    code: 'FORBIDDEN',
+                    message: err.message,
+                    cause: err,
+                });
+            } else if (err.code === 'P2025') {
+                // not found
+                throw new TRPCError({
+                    code: 'NOT_FOUND',
+                    message: err.message,
+                    cause: err,
+                });
+            } else {
+                // request error
+                throw new TRPCError({
+                    code: 'BAD_REQUEST',
+                    message: err.message,
+                    cause: err,
+                });
+            }
+        } else {
+            throw err;
+        }
+    }
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/routers/Post.router.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/routers/Post.router.ts
new file mode 100644
index 000000000..e7fa40292
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/routers/Post.router.ts
@@ -0,0 +1,451 @@
+/* eslint-disable */
+import { type RouterFactory, type ProcBuilder, type BaseConfig, db } from '.';
+import $Schema from '@zenstackhq/runtime/zod/input';
+import { checkRead, checkMutate } from '../helper';
+import type { Prisma } from '@prisma/client';
+import type {
+    UseTRPCMutationOptions,
+    UseTRPCMutationResult,
+    UseTRPCQueryOptions,
+    UseTRPCQueryResult,
+    UseTRPCInfiniteQueryOptions,
+    UseTRPCInfiniteQueryResult,
+} from '@trpc/react-query/shared';
+import type { TRPCClientErrorLike } from '@trpc/client';
+import type { AnyRouter } from '@trpc/server';
+
+export default function createRouter<Config extends BaseConfig>(
+    router: RouterFactory<Config>,
+    procedure: ProcBuilder<Config>,
+) {
+    return router({
+        aggregate: procedure
+            .input($Schema.PostInputSchema.aggregate)
+            .query(({ ctx, input }) => checkRead(db(ctx).post.aggregate(input as any))),
+
+        create: procedure
+            .input($Schema.PostInputSchema.create)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.create(input as any))),
+
+        deleteMany: procedure
+            .input($Schema.PostInputSchema.deleteMany)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.deleteMany(input as any))),
+
+        delete: procedure
+            .input($Schema.PostInputSchema.delete)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.delete(input as any))),
+
+        findFirst: procedure
+            .input($Schema.PostInputSchema.findFirst)
+            .query(({ ctx, input }) => checkRead(db(ctx).post.findFirst(input as any))),
+
+        findFirstOrThrow: procedure
+            .input($Schema.PostInputSchema.findFirst)
+            .query(({ ctx, input }) => checkRead(db(ctx).post.findFirstOrThrow(input as any))),
+
+        findMany: procedure
+            .input($Schema.PostInputSchema.findMany)
+            .query(({ ctx, input }) => checkRead(db(ctx).post.findMany(input as any))),
+
+        findUnique: procedure
+            .input($Schema.PostInputSchema.findUnique)
+            .query(({ ctx, input }) => checkRead(db(ctx).post.findUnique(input as any))),
+
+        findUniqueOrThrow: procedure
+            .input($Schema.PostInputSchema.findUnique)
+            .query(({ ctx, input }) => checkRead(db(ctx).post.findUniqueOrThrow(input as any))),
+
+        groupBy: procedure
+            .input($Schema.PostInputSchema.groupBy)
+            .query(({ ctx, input }) => checkRead(db(ctx).post.groupBy(input as any))),
+
+        updateMany: procedure
+            .input($Schema.PostInputSchema.updateMany)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.updateMany(input as any))),
+
+        update: procedure
+            .input($Schema.PostInputSchema.update)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.update(input as any))),
+
+        upsert: procedure
+            .input($Schema.PostInputSchema.upsert)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).post.upsert(input as any))),
+
+        count: procedure
+            .input($Schema.PostInputSchema.count)
+            .query(({ ctx, input }) => checkRead(db(ctx).post.count(input as any))),
+    });
+}
+
+export interface ClientType<AppRouter extends AnyRouter, Context = AppRouter['_def']['_config']['$types']['ctx']> {
+    aggregate: {
+        useQuery: <T extends Prisma.PostAggregateArgs, TData = Prisma.GetPostAggregateType<T>>(
+            input: Prisma.Subset<T, Prisma.PostAggregateArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.GetPostAggregateType<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.PostAggregateArgs>(
+            input: Omit<Prisma.Subset<T, Prisma.PostAggregateArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.GetPostAggregateType<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.GetPostAggregateType<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    create: {
+        useMutation: <T extends Prisma.PostCreateArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.PostCreateArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.PostGetPayload<T>,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.PostGetPayload<T>,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.PostCreateArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.PostCreateArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.PostGetPayload<T>, Context>,
+            ) => Promise<Prisma.PostGetPayload<T>>;
+        };
+    };
+    deleteMany: {
+        useMutation: <T extends Prisma.PostDeleteManyArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.PostDeleteManyArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.BatchPayload,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.BatchPayload,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.PostDeleteManyArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.PostDeleteManyArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.BatchPayload, Context>,
+            ) => Promise<Prisma.BatchPayload>;
+        };
+    };
+    delete: {
+        useMutation: <T extends Prisma.PostDeleteArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.PostDeleteArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.PostGetPayload<T>,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.PostGetPayload<T>,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.PostDeleteArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.PostDeleteArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.PostGetPayload<T>, Context>,
+            ) => Promise<Prisma.PostGetPayload<T>>;
+        };
+    };
+    findFirst: {
+        useQuery: <T extends Prisma.PostFindFirstArgs, TData = Prisma.PostGetPayload<T>>(
+            input: Prisma.SelectSubset<T, Prisma.PostFindFirstArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.PostGetPayload<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.PostFindFirstArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.PostFindFirstArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.PostGetPayload<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.PostGetPayload<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    findFirstOrThrow: {
+        useQuery: <T extends Prisma.PostFindFirstOrThrowArgs, TData = Prisma.PostGetPayload<T>>(
+            input: Prisma.SelectSubset<T, Prisma.PostFindFirstOrThrowArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.PostGetPayload<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.PostFindFirstOrThrowArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.PostFindFirstOrThrowArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.PostGetPayload<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.PostGetPayload<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    findMany: {
+        useQuery: <T extends Prisma.PostFindManyArgs, TData = Array<Prisma.PostGetPayload<T>>>(
+            input: Prisma.SelectSubset<T, Prisma.PostFindManyArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Array<Prisma.PostGetPayload<T>>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.PostFindManyArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.PostFindManyArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Array<Prisma.PostGetPayload<T>>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Array<Prisma.PostGetPayload<T>>, TRPCClientErrorLike<AppRouter>>;
+    };
+    findUnique: {
+        useQuery: <T extends Prisma.PostFindUniqueArgs, TData = Prisma.PostGetPayload<T>>(
+            input: Prisma.SelectSubset<T, Prisma.PostFindUniqueArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.PostGetPayload<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.PostFindUniqueArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.PostFindUniqueArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.PostGetPayload<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.PostGetPayload<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    findUniqueOrThrow: {
+        useQuery: <T extends Prisma.PostFindUniqueOrThrowArgs, TData = Prisma.PostGetPayload<T>>(
+            input: Prisma.SelectSubset<T, Prisma.PostFindUniqueOrThrowArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.PostGetPayload<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.PostFindUniqueOrThrowArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.PostFindUniqueOrThrowArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.PostGetPayload<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.PostGetPayload<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    groupBy: {
+        useQuery: <
+            T extends Prisma.PostGroupByArgs,
+            HasSelectOrTake extends Prisma.Or<
+                Prisma.Extends<'skip', Prisma.Keys<T>>,
+                Prisma.Extends<'take', Prisma.Keys<T>>
+            >,
+            OrderByArg extends Prisma.True extends HasSelectOrTake
+                ? { orderBy: Prisma.PostGroupByArgs['orderBy'] }
+                : { orderBy?: Prisma.PostGroupByArgs['orderBy'] },
+            OrderFields extends Prisma.ExcludeUnderscoreKeys<Prisma.Keys<Prisma.MaybeTupleToUnion<T['orderBy']>>>,
+            ByFields extends Prisma.MaybeTupleToUnion<T['by']>,
+            ByValid extends Prisma.Has<ByFields, OrderFields>,
+            HavingFields extends Prisma.GetHavingFields<T['having']>,
+            HavingValid extends Prisma.Has<ByFields, HavingFields>,
+            ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False,
+            InputErrors extends ByEmpty extends Prisma.True
+                ? `Error: "by" must not be empty.`
+                : HavingValid extends Prisma.False
+                ? {
+                      [P in HavingFields]: P extends ByFields
+                          ? never
+                          : P extends string
+                          ? `Error: Field "${P}" used in "having" needs to be provided in "by".`
+                          : [Error, 'Field ', P, ` in "having" needs to be provided in "by"`];
+                  }[HavingFields]
+                : 'take' extends Prisma.Keys<T>
+                ? 'orderBy' extends Prisma.Keys<T>
+                    ? ByValid extends Prisma.True
+                        ? {}
+                        : {
+                              [P in OrderFields]: P extends ByFields
+                                  ? never
+                                  : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                          }[OrderFields]
+                    : 'Error: If you provide "take", you also need to provide "orderBy"'
+                : 'skip' extends Prisma.Keys<T>
+                ? 'orderBy' extends Prisma.Keys<T>
+                    ? ByValid extends Prisma.True
+                        ? {}
+                        : {
+                              [P in OrderFields]: P extends ByFields
+                                  ? never
+                                  : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                          }[OrderFields]
+                    : 'Error: If you provide "skip", you also need to provide "orderBy"'
+                : ByValid extends Prisma.True
+                ? {}
+                : {
+                      [P in OrderFields]: P extends ByFields
+                          ? never
+                          : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                  }[OrderFields],
+            TData = {} extends InputErrors ? Prisma.GetPostGroupByPayload<T> : InputErrors,
+        >(
+            input: Prisma.SubsetIntersection<T, Prisma.PostGroupByArgs, OrderByArg> & InputErrors,
+            opts?: UseTRPCQueryOptions<
+                string,
+                T,
+                {} extends InputErrors ? Prisma.GetPostGroupByPayload<T> : InputErrors,
+                TData,
+                Error
+            >,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <
+            T extends Prisma.PostGroupByArgs,
+            HasSelectOrTake extends Prisma.Or<
+                Prisma.Extends<'skip', Prisma.Keys<T>>,
+                Prisma.Extends<'take', Prisma.Keys<T>>
+            >,
+            OrderByArg extends Prisma.True extends HasSelectOrTake
+                ? { orderBy: Prisma.PostGroupByArgs['orderBy'] }
+                : { orderBy?: Prisma.PostGroupByArgs['orderBy'] },
+            OrderFields extends Prisma.ExcludeUnderscoreKeys<Prisma.Keys<Prisma.MaybeTupleToUnion<T['orderBy']>>>,
+            ByFields extends Prisma.MaybeTupleToUnion<T['by']>,
+            ByValid extends Prisma.Has<ByFields, OrderFields>,
+            HavingFields extends Prisma.GetHavingFields<T['having']>,
+            HavingValid extends Prisma.Has<ByFields, HavingFields>,
+            ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False,
+            InputErrors extends ByEmpty extends Prisma.True
+                ? `Error: "by" must not be empty.`
+                : HavingValid extends Prisma.False
+                ? {
+                      [P in HavingFields]: P extends ByFields
+                          ? never
+                          : P extends string
+                          ? `Error: Field "${P}" used in "having" needs to be provided in "by".`
+                          : [Error, 'Field ', P, ` in "having" needs to be provided in "by"`];
+                  }[HavingFields]
+                : 'take' extends Prisma.Keys<T>
+                ? 'orderBy' extends Prisma.Keys<T>
+                    ? ByValid extends Prisma.True
+                        ? {}
+                        : {
+                              [P in OrderFields]: P extends ByFields
+                                  ? never
+                                  : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                          }[OrderFields]
+                    : 'Error: If you provide "take", you also need to provide "orderBy"'
+                : 'skip' extends Prisma.Keys<T>
+                ? 'orderBy' extends Prisma.Keys<T>
+                    ? ByValid extends Prisma.True
+                        ? {}
+                        : {
+                              [P in OrderFields]: P extends ByFields
+                                  ? never
+                                  : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                          }[OrderFields]
+                    : 'Error: If you provide "skip", you also need to provide "orderBy"'
+                : ByValid extends Prisma.True
+                ? {}
+                : {
+                      [P in OrderFields]: P extends ByFields
+                          ? never
+                          : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                  }[OrderFields],
+        >(
+            input: Omit<Prisma.SubsetIntersection<T, Prisma.PostGroupByArgs, OrderByArg> & InputErrors, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<
+                string,
+                T,
+                {} extends InputErrors ? Prisma.GetPostGroupByPayload<T> : InputErrors,
+                Error
+            >,
+        ) => UseTRPCInfiniteQueryResult<
+            {} extends InputErrors ? Prisma.GetPostGroupByPayload<T> : InputErrors,
+            TRPCClientErrorLike<AppRouter>
+        >;
+    };
+    updateMany: {
+        useMutation: <T extends Prisma.PostUpdateManyArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.PostUpdateManyArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.BatchPayload,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.BatchPayload,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.PostUpdateManyArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.PostUpdateManyArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.BatchPayload, Context>,
+            ) => Promise<Prisma.BatchPayload>;
+        };
+    };
+    update: {
+        useMutation: <T extends Prisma.PostUpdateArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.PostUpdateArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.PostGetPayload<T>,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.PostGetPayload<T>,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.PostUpdateArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.PostUpdateArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.PostGetPayload<T>, Context>,
+            ) => Promise<Prisma.PostGetPayload<T>>;
+        };
+    };
+    upsert: {
+        useMutation: <T extends Prisma.PostUpsertArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.PostUpsertArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.PostGetPayload<T>,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.PostGetPayload<T>,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.PostUpsertArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.PostUpsertArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.PostGetPayload<T>, Context>,
+            ) => Promise<Prisma.PostGetPayload<T>>;
+        };
+    };
+    count: {
+        useQuery: <
+            T extends Prisma.PostCountArgs,
+            TData = 'select' extends keyof T
+                ? T['select'] extends true
+                    ? number
+                    : Prisma.GetScalarType<T['select'], Prisma.PostCountAggregateOutputType>
+                : number,
+        >(
+            input: Prisma.Subset<T, Prisma.PostCountArgs>,
+            opts?: UseTRPCQueryOptions<
+                string,
+                T,
+                'select' extends keyof T
+                    ? T['select'] extends true
+                        ? number
+                        : Prisma.GetScalarType<T['select'], Prisma.PostCountAggregateOutputType>
+                    : number,
+                TData,
+                Error
+            >,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.PostCountArgs>(
+            input: Omit<Prisma.Subset<T, Prisma.PostCountArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<
+                string,
+                T,
+                'select' extends keyof T
+                    ? T['select'] extends true
+                        ? number
+                        : Prisma.GetScalarType<T['select'], Prisma.PostCountAggregateOutputType>
+                    : number,
+                Error
+            >,
+        ) => UseTRPCInfiniteQueryResult<
+            'select' extends keyof T
+                ? T['select'] extends true
+                    ? number
+                    : Prisma.GetScalarType<T['select'], Prisma.PostCountAggregateOutputType>
+                : number,
+            TRPCClientErrorLike<AppRouter>
+        >;
+    };
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/routers/User.router.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/routers/User.router.ts
new file mode 100644
index 000000000..15bd74328
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/routers/User.router.ts
@@ -0,0 +1,451 @@
+/* eslint-disable */
+import { type RouterFactory, type ProcBuilder, type BaseConfig, db } from '.';
+import $Schema from '@zenstackhq/runtime/zod/input';
+import { checkRead, checkMutate } from '../helper';
+import type { Prisma } from '@prisma/client';
+import type {
+    UseTRPCMutationOptions,
+    UseTRPCMutationResult,
+    UseTRPCQueryOptions,
+    UseTRPCQueryResult,
+    UseTRPCInfiniteQueryOptions,
+    UseTRPCInfiniteQueryResult,
+} from '@trpc/react-query/shared';
+import type { TRPCClientErrorLike } from '@trpc/client';
+import type { AnyRouter } from '@trpc/server';
+
+export default function createRouter<Config extends BaseConfig>(
+    router: RouterFactory<Config>,
+    procedure: ProcBuilder<Config>,
+) {
+    return router({
+        aggregate: procedure
+            .input($Schema.UserInputSchema.aggregate)
+            .query(({ ctx, input }) => checkRead(db(ctx).user.aggregate(input as any))),
+
+        create: procedure
+            .input($Schema.UserInputSchema.create)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.create(input as any))),
+
+        deleteMany: procedure
+            .input($Schema.UserInputSchema.deleteMany)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.deleteMany(input as any))),
+
+        delete: procedure
+            .input($Schema.UserInputSchema.delete)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.delete(input as any))),
+
+        findFirst: procedure
+            .input($Schema.UserInputSchema.findFirst)
+            .query(({ ctx, input }) => checkRead(db(ctx).user.findFirst(input as any))),
+
+        findFirstOrThrow: procedure
+            .input($Schema.UserInputSchema.findFirst)
+            .query(({ ctx, input }) => checkRead(db(ctx).user.findFirstOrThrow(input as any))),
+
+        findMany: procedure
+            .input($Schema.UserInputSchema.findMany)
+            .query(({ ctx, input }) => checkRead(db(ctx).user.findMany(input as any))),
+
+        findUnique: procedure
+            .input($Schema.UserInputSchema.findUnique)
+            .query(({ ctx, input }) => checkRead(db(ctx).user.findUnique(input as any))),
+
+        findUniqueOrThrow: procedure
+            .input($Schema.UserInputSchema.findUnique)
+            .query(({ ctx, input }) => checkRead(db(ctx).user.findUniqueOrThrow(input as any))),
+
+        groupBy: procedure
+            .input($Schema.UserInputSchema.groupBy)
+            .query(({ ctx, input }) => checkRead(db(ctx).user.groupBy(input as any))),
+
+        updateMany: procedure
+            .input($Schema.UserInputSchema.updateMany)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.updateMany(input as any))),
+
+        update: procedure
+            .input($Schema.UserInputSchema.update)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.update(input as any))),
+
+        upsert: procedure
+            .input($Schema.UserInputSchema.upsert)
+            .mutation(async ({ ctx, input }) => checkMutate(db(ctx).user.upsert(input as any))),
+
+        count: procedure
+            .input($Schema.UserInputSchema.count)
+            .query(({ ctx, input }) => checkRead(db(ctx).user.count(input as any))),
+    });
+}
+
+export interface ClientType<AppRouter extends AnyRouter, Context = AppRouter['_def']['_config']['$types']['ctx']> {
+    aggregate: {
+        useQuery: <T extends Prisma.UserAggregateArgs, TData = Prisma.GetUserAggregateType<T>>(
+            input: Prisma.Subset<T, Prisma.UserAggregateArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.GetUserAggregateType<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.UserAggregateArgs>(
+            input: Omit<Prisma.Subset<T, Prisma.UserAggregateArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.GetUserAggregateType<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.GetUserAggregateType<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    create: {
+        useMutation: <T extends Prisma.UserCreateArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.UserCreateArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.UserGetPayload<T>,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.UserGetPayload<T>,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.UserCreateArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.UserCreateArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.UserGetPayload<T>, Context>,
+            ) => Promise<Prisma.UserGetPayload<T>>;
+        };
+    };
+    deleteMany: {
+        useMutation: <T extends Prisma.UserDeleteManyArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.UserDeleteManyArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.BatchPayload,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.BatchPayload,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.UserDeleteManyArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.UserDeleteManyArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.BatchPayload, Context>,
+            ) => Promise<Prisma.BatchPayload>;
+        };
+    };
+    delete: {
+        useMutation: <T extends Prisma.UserDeleteArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.UserDeleteArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.UserGetPayload<T>,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.UserGetPayload<T>,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.UserDeleteArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.UserDeleteArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.UserGetPayload<T>, Context>,
+            ) => Promise<Prisma.UserGetPayload<T>>;
+        };
+    };
+    findFirst: {
+        useQuery: <T extends Prisma.UserFindFirstArgs, TData = Prisma.UserGetPayload<T>>(
+            input: Prisma.SelectSubset<T, Prisma.UserFindFirstArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.UserGetPayload<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.UserFindFirstArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.UserFindFirstArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.UserGetPayload<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.UserGetPayload<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    findFirstOrThrow: {
+        useQuery: <T extends Prisma.UserFindFirstOrThrowArgs, TData = Prisma.UserGetPayload<T>>(
+            input: Prisma.SelectSubset<T, Prisma.UserFindFirstOrThrowArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.UserGetPayload<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.UserFindFirstOrThrowArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.UserFindFirstOrThrowArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.UserGetPayload<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.UserGetPayload<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    findMany: {
+        useQuery: <T extends Prisma.UserFindManyArgs, TData = Array<Prisma.UserGetPayload<T>>>(
+            input: Prisma.SelectSubset<T, Prisma.UserFindManyArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Array<Prisma.UserGetPayload<T>>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.UserFindManyArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.UserFindManyArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Array<Prisma.UserGetPayload<T>>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Array<Prisma.UserGetPayload<T>>, TRPCClientErrorLike<AppRouter>>;
+    };
+    findUnique: {
+        useQuery: <T extends Prisma.UserFindUniqueArgs, TData = Prisma.UserGetPayload<T>>(
+            input: Prisma.SelectSubset<T, Prisma.UserFindUniqueArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.UserGetPayload<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.UserFindUniqueArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.UserFindUniqueArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.UserGetPayload<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.UserGetPayload<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    findUniqueOrThrow: {
+        useQuery: <T extends Prisma.UserFindUniqueOrThrowArgs, TData = Prisma.UserGetPayload<T>>(
+            input: Prisma.SelectSubset<T, Prisma.UserFindUniqueOrThrowArgs>,
+            opts?: UseTRPCQueryOptions<string, T, Prisma.UserGetPayload<T>, TData, Error>,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.UserFindUniqueOrThrowArgs>(
+            input: Omit<Prisma.SelectSubset<T, Prisma.UserFindUniqueOrThrowArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<string, T, Prisma.UserGetPayload<T>, Error>,
+        ) => UseTRPCInfiniteQueryResult<Prisma.UserGetPayload<T>, TRPCClientErrorLike<AppRouter>>;
+    };
+    groupBy: {
+        useQuery: <
+            T extends Prisma.UserGroupByArgs,
+            HasSelectOrTake extends Prisma.Or<
+                Prisma.Extends<'skip', Prisma.Keys<T>>,
+                Prisma.Extends<'take', Prisma.Keys<T>>
+            >,
+            OrderByArg extends Prisma.True extends HasSelectOrTake
+                ? { orderBy: Prisma.UserGroupByArgs['orderBy'] }
+                : { orderBy?: Prisma.UserGroupByArgs['orderBy'] },
+            OrderFields extends Prisma.ExcludeUnderscoreKeys<Prisma.Keys<Prisma.MaybeTupleToUnion<T['orderBy']>>>,
+            ByFields extends Prisma.MaybeTupleToUnion<T['by']>,
+            ByValid extends Prisma.Has<ByFields, OrderFields>,
+            HavingFields extends Prisma.GetHavingFields<T['having']>,
+            HavingValid extends Prisma.Has<ByFields, HavingFields>,
+            ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False,
+            InputErrors extends ByEmpty extends Prisma.True
+                ? `Error: "by" must not be empty.`
+                : HavingValid extends Prisma.False
+                ? {
+                      [P in HavingFields]: P extends ByFields
+                          ? never
+                          : P extends string
+                          ? `Error: Field "${P}" used in "having" needs to be provided in "by".`
+                          : [Error, 'Field ', P, ` in "having" needs to be provided in "by"`];
+                  }[HavingFields]
+                : 'take' extends Prisma.Keys<T>
+                ? 'orderBy' extends Prisma.Keys<T>
+                    ? ByValid extends Prisma.True
+                        ? {}
+                        : {
+                              [P in OrderFields]: P extends ByFields
+                                  ? never
+                                  : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                          }[OrderFields]
+                    : 'Error: If you provide "take", you also need to provide "orderBy"'
+                : 'skip' extends Prisma.Keys<T>
+                ? 'orderBy' extends Prisma.Keys<T>
+                    ? ByValid extends Prisma.True
+                        ? {}
+                        : {
+                              [P in OrderFields]: P extends ByFields
+                                  ? never
+                                  : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                          }[OrderFields]
+                    : 'Error: If you provide "skip", you also need to provide "orderBy"'
+                : ByValid extends Prisma.True
+                ? {}
+                : {
+                      [P in OrderFields]: P extends ByFields
+                          ? never
+                          : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                  }[OrderFields],
+            TData = {} extends InputErrors ? Prisma.GetUserGroupByPayload<T> : InputErrors,
+        >(
+            input: Prisma.SubsetIntersection<T, Prisma.UserGroupByArgs, OrderByArg> & InputErrors,
+            opts?: UseTRPCQueryOptions<
+                string,
+                T,
+                {} extends InputErrors ? Prisma.GetUserGroupByPayload<T> : InputErrors,
+                TData,
+                Error
+            >,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <
+            T extends Prisma.UserGroupByArgs,
+            HasSelectOrTake extends Prisma.Or<
+                Prisma.Extends<'skip', Prisma.Keys<T>>,
+                Prisma.Extends<'take', Prisma.Keys<T>>
+            >,
+            OrderByArg extends Prisma.True extends HasSelectOrTake
+                ? { orderBy: Prisma.UserGroupByArgs['orderBy'] }
+                : { orderBy?: Prisma.UserGroupByArgs['orderBy'] },
+            OrderFields extends Prisma.ExcludeUnderscoreKeys<Prisma.Keys<Prisma.MaybeTupleToUnion<T['orderBy']>>>,
+            ByFields extends Prisma.MaybeTupleToUnion<T['by']>,
+            ByValid extends Prisma.Has<ByFields, OrderFields>,
+            HavingFields extends Prisma.GetHavingFields<T['having']>,
+            HavingValid extends Prisma.Has<ByFields, HavingFields>,
+            ByEmpty extends T['by'] extends never[] ? Prisma.True : Prisma.False,
+            InputErrors extends ByEmpty extends Prisma.True
+                ? `Error: "by" must not be empty.`
+                : HavingValid extends Prisma.False
+                ? {
+                      [P in HavingFields]: P extends ByFields
+                          ? never
+                          : P extends string
+                          ? `Error: Field "${P}" used in "having" needs to be provided in "by".`
+                          : [Error, 'Field ', P, ` in "having" needs to be provided in "by"`];
+                  }[HavingFields]
+                : 'take' extends Prisma.Keys<T>
+                ? 'orderBy' extends Prisma.Keys<T>
+                    ? ByValid extends Prisma.True
+                        ? {}
+                        : {
+                              [P in OrderFields]: P extends ByFields
+                                  ? never
+                                  : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                          }[OrderFields]
+                    : 'Error: If you provide "take", you also need to provide "orderBy"'
+                : 'skip' extends Prisma.Keys<T>
+                ? 'orderBy' extends Prisma.Keys<T>
+                    ? ByValid extends Prisma.True
+                        ? {}
+                        : {
+                              [P in OrderFields]: P extends ByFields
+                                  ? never
+                                  : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                          }[OrderFields]
+                    : 'Error: If you provide "skip", you also need to provide "orderBy"'
+                : ByValid extends Prisma.True
+                ? {}
+                : {
+                      [P in OrderFields]: P extends ByFields
+                          ? never
+                          : `Error: Field "${P}" in "orderBy" needs to be provided in "by"`;
+                  }[OrderFields],
+        >(
+            input: Omit<Prisma.SubsetIntersection<T, Prisma.UserGroupByArgs, OrderByArg> & InputErrors, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<
+                string,
+                T,
+                {} extends InputErrors ? Prisma.GetUserGroupByPayload<T> : InputErrors,
+                Error
+            >,
+        ) => UseTRPCInfiniteQueryResult<
+            {} extends InputErrors ? Prisma.GetUserGroupByPayload<T> : InputErrors,
+            TRPCClientErrorLike<AppRouter>
+        >;
+    };
+    updateMany: {
+        useMutation: <T extends Prisma.UserUpdateManyArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.UserUpdateManyArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.BatchPayload,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.BatchPayload,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.UserUpdateManyArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.UserUpdateManyArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.BatchPayload, Context>,
+            ) => Promise<Prisma.BatchPayload>;
+        };
+    };
+    update: {
+        useMutation: <T extends Prisma.UserUpdateArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.UserUpdateArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.UserGetPayload<T>,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.UserGetPayload<T>,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.UserUpdateArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.UserUpdateArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.UserGetPayload<T>, Context>,
+            ) => Promise<Prisma.UserGetPayload<T>>;
+        };
+    };
+    upsert: {
+        useMutation: <T extends Prisma.UserUpsertArgs>(
+            opts?: UseTRPCMutationOptions<
+                Prisma.UserUpsertArgs,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.UserGetPayload<T>,
+                Context
+            >,
+        ) => Omit<
+            UseTRPCMutationResult<
+                Prisma.UserGetPayload<T>,
+                TRPCClientErrorLike<AppRouter>,
+                Prisma.SelectSubset<T, Prisma.UserUpsertArgs>,
+                Context
+            >,
+            'mutateAsync'
+        > & {
+            mutateAsync: <T extends Prisma.UserUpsertArgs>(
+                variables: T,
+                opts?: UseTRPCMutationOptions<T, TRPCClientErrorLike<AppRouter>, Prisma.UserGetPayload<T>, Context>,
+            ) => Promise<Prisma.UserGetPayload<T>>;
+        };
+    };
+    count: {
+        useQuery: <
+            T extends Prisma.UserCountArgs,
+            TData = 'select' extends keyof T
+                ? T['select'] extends true
+                    ? number
+                    : Prisma.GetScalarType<T['select'], Prisma.UserCountAggregateOutputType>
+                : number,
+        >(
+            input: Prisma.Subset<T, Prisma.UserCountArgs>,
+            opts?: UseTRPCQueryOptions<
+                string,
+                T,
+                'select' extends keyof T
+                    ? T['select'] extends true
+                        ? number
+                        : Prisma.GetScalarType<T['select'], Prisma.UserCountAggregateOutputType>
+                    : number,
+                TData,
+                Error
+            >,
+        ) => UseTRPCQueryResult<TData, TRPCClientErrorLike<AppRouter>>;
+        useInfiniteQuery: <T extends Prisma.UserCountArgs>(
+            input: Omit<Prisma.Subset<T, Prisma.UserCountArgs>, 'cursor'>,
+            opts?: UseTRPCInfiniteQueryOptions<
+                string,
+                T,
+                'select' extends keyof T
+                    ? T['select'] extends true
+                        ? number
+                        : Prisma.GetScalarType<T['select'], Prisma.UserCountAggregateOutputType>
+                    : number,
+                Error
+            >,
+        ) => UseTRPCInfiniteQueryResult<
+            'select' extends keyof T
+                ? T['select'] extends true
+                    ? number
+                    : Prisma.GetScalarType<T['select'], Prisma.UserCountAggregateOutputType>
+                : number,
+            TRPCClientErrorLike<AppRouter>
+        >;
+    };
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/routers/index.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/routers/index.ts
new file mode 100644
index 000000000..bcb767b6f
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/generated/routers/index.ts
@@ -0,0 +1,48 @@
+/* eslint-disable */
+import {
+    unsetMarker,
+    type AnyRouter,
+    type AnyRootConfig,
+    type CreateRouterInner,
+    type Procedure,
+    type ProcedureBuilder,
+    type ProcedureParams,
+    type ProcedureRouterRecord,
+    type ProcedureType,
+} from '@trpc/server';
+import { type PrismaClient } from '@prisma/client';
+import createUserRouter from './User.router';
+import createPostRouter from './Post.router';
+import { ClientType as UserClientType } from './User.router';
+import { ClientType as PostClientType } from './Post.router';
+
+export type BaseConfig = AnyRootConfig;
+
+export type RouterFactory<Config extends BaseConfig> = <ProcRouterRecord extends ProcedureRouterRecord>(
+    procedures: ProcRouterRecord,
+) => CreateRouterInner<Config, ProcRouterRecord>;
+
+export type UnsetMarker = typeof unsetMarker;
+
+export type ProcBuilder<Config extends BaseConfig> = ProcedureBuilder<
+    ProcedureParams<Config, any, any, any, UnsetMarker, UnsetMarker, any>
+>;
+
+export function db(ctx: any) {
+    if (!ctx.prisma) {
+        throw new Error('Missing "prisma" field in trpc context');
+    }
+    return ctx.prisma as PrismaClient;
+}
+
+export function createRouter<Config extends BaseConfig>(router: RouterFactory<Config>, procedure: ProcBuilder<Config>) {
+    return router({
+        user: createUserRouter(router, procedure),
+        post: createPostRouter(router, procedure),
+    });
+}
+
+export interface ClientType<AppRouter extends AnyRouter> {
+    user: UserClientType<AppRouter>;
+    post: PostClientType<AppRouter>;
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/greet.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/greet.ts
new file mode 100644
index 000000000..2d1fbbbea
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/greet.ts
@@ -0,0 +1,11 @@
+import { z } from 'zod';
+
+import { createTRPCRouter, publicProcedure } from '~/server/api/trpc';
+
+export const greetRouter = createTRPCRouter({
+    hello: publicProcedure.input(z.object({ text: z.string() })).query(({ input }) => {
+        return {
+            greeting: `Hello ${input.text}`,
+        };
+    }),
+});
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/post.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/post.ts
new file mode 100644
index 000000000..04067d65c
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/routers/post.ts
@@ -0,0 +1,4 @@
+import { createTRPCRouter, publicProcedure } from '../trpc';
+import { createRouter } from './generated/routers';
+
+export const postRouter = createRouter(createTRPCRouter, publicProcedure);
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/trpc.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/trpc.ts
new file mode 100644
index 000000000..dc3b40b24
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/api/trpc.ts
@@ -0,0 +1,95 @@
+/**
+ * YOU PROBABLY DON'T NEED TO EDIT THIS FILE, UNLESS:
+ * 1. You want to modify request context (see Part 1).
+ * 2. You want to create a new middleware or type of procedure (see Part 3).
+ *
+ * TL;DR - This is where all the tRPC server stuff is created and plugged in. The pieces you will
+ * need to use are documented accordingly near the end.
+ */
+import { initTRPC } from "@trpc/server";
+import { type CreateNextContextOptions } from "@trpc/server/adapters/next";
+import superjson from "superjson";
+import { ZodError } from "zod";
+
+import { db } from "~/server/db";
+
+/**
+ * 1. CONTEXT
+ *
+ * This section defines the "contexts" that are available in the backend API.
+ *
+ * These allow you to access things when processing a request, like the database, the session, etc.
+ */
+
+type CreateContextOptions = Record<string, never>;
+
+/**
+ * This helper generates the "internals" for a tRPC context. If you need to use it, you can export
+ * it from here.
+ *
+ * Examples of things you may need it for:
+ * - testing, so we don't have to mock Next.js' req/res
+ * - tRPC's `createSSGHelpers`, where we don't have req/res
+ *
+ * @see https://create.t3.gg/en/usage/trpc#-serverapitrpcts
+ */
+const createInnerTRPCContext = (_opts: CreateContextOptions) => {
+  return {
+    db,
+  };
+};
+
+/**
+ * This is the actual context you will use in your router. It will be used to process every request
+ * that goes through your tRPC endpoint.
+ *
+ * @see https://trpc.io/docs/context
+ */
+export const createTRPCContext = (_opts: CreateNextContextOptions) => {
+  return createInnerTRPCContext({});
+};
+
+/**
+ * 2. INITIALIZATION
+ *
+ * This is where the tRPC API is initialized, connecting the context and transformer. We also parse
+ * ZodErrors so that you get typesafety on the frontend if your procedure fails due to validation
+ * errors on the backend.
+ */
+
+const t = initTRPC.context<typeof createTRPCContext>().create({
+  transformer: superjson,
+  errorFormatter({ shape, error }) {
+    return {
+      ...shape,
+      data: {
+        ...shape.data,
+        zodError:
+          error.cause instanceof ZodError ? error.cause.flatten() : null,
+      },
+    };
+  },
+});
+
+/**
+ * 3. ROUTER & PROCEDURE (THE IMPORTANT BIT)
+ *
+ * These are the pieces you use to build your tRPC API. You should import these a lot in the
+ * "/src/server/api/routers" directory.
+ */
+
+/**
+ * This is how you create new routers and sub-routers in your tRPC API.
+ *
+ * @see https://trpc.io/docs/router
+ */
+export const createTRPCRouter = t.router;
+
+/**
+ * Public (unauthenticated) procedure
+ *
+ * This is the base piece you use to build new queries and mutations on your tRPC API. It does not
+ * guarantee that a user querying is authorized, but you can still access user session data if they
+ * are logged in.
+ */
+export const publicProcedure = t.procedure;
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/db.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/db.ts
new file mode 100644
index 000000000..02696bcc3
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/server/db.ts
@@ -0,0 +1,16 @@
+import { PrismaClient } from "@prisma/client";
+
+import { env } from "~/env";
+
+const globalForPrisma = globalThis as unknown as {
+  prisma: PrismaClient | undefined;
+};
+
+export const db =
+  globalForPrisma.prisma ??
+  new PrismaClient({
+    log:
+      env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"],
+  });
+
+if (env.NODE_ENV !== "production") globalForPrisma.prisma = db;
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/styles/globals.css b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/styles/globals.css
new file mode 100644
index 000000000..e5e2dcc23
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/styles/globals.css
@@ -0,0 +1,16 @@
+html,
+body {
+  padding: 0;
+  margin: 0;
+  font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
+    Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
+}
+
+a {
+  color: inherit;
+  text-decoration: none;
+}
+
+* {
+  box-sizing: border-box;
+}
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/utils/api.ts b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/utils/api.ts
new file mode 100644
index 000000000..abbfef8de
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/src/utils/api.ts
@@ -0,0 +1,68 @@
+/**
+ * This is the client-side entrypoint for your tRPC API. It is used to create the `api` object which
+ * contains the Next.js App-wrapper, as well as your type-safe React Query hooks.
+ *
+ * We also create a few inference helpers for input and output types.
+ */
+import { httpBatchLink, loggerLink } from '@trpc/client';
+import { createTRPCNext } from '~/server/api/routers/generated/client/next';
+import { type inferRouterInputs, type inferRouterOutputs } from '@trpc/server';
+import superjson from 'superjson';
+
+import { type AppRouter } from '~/server/api/root';
+
+const getBaseUrl = () => {
+    if (typeof window !== 'undefined') return ''; // browser should use relative url
+    if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // SSR should use vercel url
+    return `http://localhost:${process.env.PORT ?? 3000}`; // dev SSR should use localhost
+};
+
+/** A set of type-safe react-query hooks for your tRPC API. */
+export const api = createTRPCNext<AppRouter>({
+    config() {
+        return {
+            /**
+             * Transformer used for data de-serialization from the server.
+             *
+             * @see https://trpc.io/docs/data-transformers
+             */
+            transformer: superjson,
+
+            /**
+             * Links used to determine request flow from client to server.
+             *
+             * @see https://trpc.io/docs/links
+             */
+            links: [
+                loggerLink({
+                    enabled: (opts) =>
+                        process.env.NODE_ENV === 'development' ||
+                        (opts.direction === 'down' && opts.result instanceof Error),
+                }),
+                httpBatchLink({
+                    url: `${getBaseUrl()}/api/trpc`,
+                }),
+            ],
+        };
+    },
+    /**
+     * Whether tRPC should await queries when server rendering pages.
+     *
+     * @see https://trpc.io/docs/nextjs#ssr-boolean-default-false
+     */
+    ssr: false,
+});
+
+/**
+ * Inference helper for inputs.
+ *
+ * @example type HelloInput = RouterInputs['example']['hello']
+ */
+export type RouterInputs = inferRouterInputs<AppRouter>;
+
+/**
+ * Inference helper for outputs.
+ *
+ * @example type HelloOutput = RouterOutputs['example']['hello']
+ */
+export type RouterOutputs = inferRouterOutputs<AppRouter>;
diff --git a/packages/plugins/trpc/tests/projects/t3-trpc-v10/tsconfig.json b/packages/plugins/trpc/tests/projects/t3-trpc-v10/tsconfig.json
new file mode 100644
index 000000000..905062ded
--- /dev/null
+++ b/packages/plugins/trpc/tests/projects/t3-trpc-v10/tsconfig.json
@@ -0,0 +1,42 @@
+{
+  "compilerOptions": {
+    /* Base Options: */
+    "esModuleInterop": true,
+    "skipLibCheck": true,
+    "target": "es2022",
+    "allowJs": true,
+    "resolveJsonModule": true,
+    "moduleDetection": "force",
+    "isolatedModules": true,
+
+    /* Strictness */
+    "strict": true,
+    "noUncheckedIndexedAccess": true,
+    "checkJs": true,
+
+    /* Bundled projects */
+    "lib": ["dom", "dom.iterable", "ES2022"],
+    "noEmit": true,
+    "module": "ESNext",
+    "moduleResolution": "Bundler",
+    "jsx": "preserve",
+    "plugins": [{ "name": "next" }],
+    "incremental": true,
+
+    /* Path Aliases */
+    "baseUrl": ".",
+    "paths": {
+      "~/*": ["./src/*"]
+    }
+  },
+  "include": [
+    ".eslintrc.cjs",
+    "next-env.d.ts",
+    "**/*.ts",
+    "**/*.tsx",
+    "**/*.cjs",
+    "**/*.js",
+    ".next/types/**/*.ts"
+  ],
+  "exclude": ["node_modules"]
+}
diff --git a/packages/plugins/trpc/tests/t3.test.ts b/packages/plugins/trpc/tests/t3.test.ts
new file mode 100644
index 000000000..1c808de23
--- /dev/null
+++ b/packages/plugins/trpc/tests/t3.test.ts
@@ -0,0 +1,30 @@
+/* eslint-disable @typescript-eslint/no-var-requires */
+import { run } from '@zenstackhq/testtools';
+import path from 'path';
+
+describe('tRPC plugin tests with create-t3-app', () => {
+    let origDir: string | undefined;
+
+    beforeEach(() => {
+        origDir = process.cwd();
+    });
+
+    afterEach(() => {
+        if (origDir) {
+            process.chdir(origDir);
+        }
+    });
+
+    it('project test trpc v10', () => {
+        const ver = require(path.join(__dirname, '../package.json')).version;
+        process.chdir(path.join(__dirname, './projects/t3-trpc-v10'));
+
+        const deps = ['zenstackhq-language', 'zenstackhq-runtime', 'zenstackhq-sdk', 'zenstack'];
+        for (const dep of deps) {
+            run(`npm install ${path.join(__dirname, '../../../../.build/') + dep + '-' + ver + '.tgz'}`);
+        }
+
+        run('npx zenstack generate');
+        run('npm run build');
+    });
+});
diff --git a/packages/plugins/trpc/tests/trpc.test.ts b/packages/plugins/trpc/tests/trpc.test.ts
index cf43c9a49..ca4a9c14d 100644
--- a/packages/plugins/trpc/tests/trpc.test.ts
+++ b/packages/plugins/trpc/tests/trpc.test.ts
@@ -56,7 +56,7 @@ model Foo {
             {
                 provider: 'postgresql',
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server'],
+                extraDependencies: [`${path.join(__dirname, '../dist')}`, '@trpc/client', '@trpc/server'],
                 compile: true,
                 fullZod: true,
             }
@@ -98,7 +98,7 @@ model Foo {
         `,
             {
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server'],
+                extraDependencies: [`${path.join(__dirname, '../dist')}`, '@trpc/client', '@trpc/server'],
                 compile: true,
                 fullZod: true,
             }
@@ -128,7 +128,7 @@ model Post {
         `,
             {
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server'],
+                extraDependencies: [`${path.join(__dirname, '../dist')}`, '@trpc/client', '@trpc/server'],
                 compile: true,
                 fullZod: true,
                 customSchemaFilePath: 'zenstack/schema.zmodel',
@@ -153,7 +153,7 @@ model Post {
         `,
             {
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server'],
+                extraDependencies: [`${path.join(__dirname, '../dist')}`, '@trpc/client', '@trpc/server'],
                 compile: true,
                 fullZod: true,
                 customSchemaFilePath: 'zenstack/schema.zmodel',
@@ -183,7 +183,7 @@ model Post {
         `,
             {
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server'],
+                extraDependencies: [`${path.join(__dirname, '../dist')}`, '@trpc/client', '@trpc/server'],
                 compile: true,
                 fullZod: true,
                 customSchemaFilePath: 'zenstack/schema.zmodel',
@@ -229,7 +229,12 @@ model Post {
             `,
             {
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server', '@trpc/react-query'],
+                extraDependencies: [
+                    `${path.join(__dirname, '../dist')}`,
+                    '@trpc/client',
+                    '@trpc/server',
+                    '@trpc/react-query',
+                ],
                 compile: true,
                 fullZod: true,
             }
@@ -249,7 +254,7 @@ model Post {
             `,
             {
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server', '@trpc/next'],
+                extraDependencies: [`${path.join(__dirname, '../dist')}`, '@trpc/client', '@trpc/server', '@trpc/next'],
                 compile: true,
                 fullZod: true,
             }
@@ -279,7 +284,7 @@ model post_item {
         `,
             {
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server'],
+                extraDependencies: [`${path.join(__dirname, '../dist')}`, '@trpc/client', '@trpc/server'],
                 compile: true,
                 fullZod: true,
             }
@@ -326,7 +331,7 @@ model Foo {
             {
                 addPrelude: false,
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server'],
+                extraDependencies: [`${path.join(__dirname, '../dist')}`, '@trpc/client', '@trpc/server'],
                 compile: true,
             }
         );
@@ -397,7 +402,7 @@ model Foo {
             {
                 addPrelude: false,
                 pushDb: false,
-                extraDependencies: [`${origDir}/dist`, '@trpc/client', '@trpc/server'],
+                extraDependencies: [`${path.join(__dirname, '../dist')}`, '@trpc/client', '@trpc/server'],
                 compile: true,
             }
         );
diff --git a/packages/runtime/package.json b/packages/runtime/package.json
index 7a2ac77f9..9249d387d 100644
--- a/packages/runtime/package.json
+++ b/packages/runtime/package.json
@@ -1,7 +1,7 @@
 {
     "name": "@zenstackhq/runtime",
     "displayName": "ZenStack Runtime Library",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "description": "Runtime of ZenStack for both client-side and server-side environments.",
     "repository": {
         "type": "git",
diff --git a/packages/schema/package.json b/packages/schema/package.json
index c9ae37484..011aa42bc 100644
--- a/packages/schema/package.json
+++ b/packages/schema/package.json
@@ -3,7 +3,7 @@
     "publisher": "zenstack",
     "displayName": "ZenStack Language Tools",
     "description": "Build scalable web apps with minimum code by defining authorization and validation rules inside the data schema that closer to the database",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "author": {
         "name": "ZenStack Team"
     },
diff --git a/packages/schema/src/cli/cli-util.ts b/packages/schema/src/cli/cli-util.ts
index 000e92ca7..85c38e82a 100644
--- a/packages/schema/src/cli/cli-util.ts
+++ b/packages/schema/src/cli/cli-util.ts
@@ -7,15 +7,15 @@ import { AstNode, getDocument, LangiumDocument, LangiumDocuments, Mutable } from
 import { NodeFileSystem } from 'langium/node';
 import path from 'path';
 import semver from 'semver';
+import { TextDocument } from 'vscode-languageserver-textdocument';
 import { URI } from 'vscode-uri';
 import { PLUGIN_MODULE_NAME, STD_LIB_MODULE_NAME } from '../language-server/constants';
+import { ZModelFormatter } from '../language-server/zmodel-formatter';
 import { createZModelServices, ZModelServices } from '../language-server/zmodel-module';
 import { mergeBaseModel, resolveImport, resolveTransitiveImports } from '../utils/ast-utils';
+import { findPackageJson } from '../utils/pkg-utils';
 import { getVersion } from '../utils/version-utils';
 import { CliError } from './cli-error';
-import { ZModelFormatter } from '../language-server/zmodel-formatter';
-import { TextDocument } from 'vscode-languageserver-textdocument';
-import { getPackageJson } from '../utils/pkg-utils';
 
 // required minimal version of Prisma
 export const requiredPrismaVersion = '4.8.0';
@@ -279,13 +279,19 @@ export async function formatDocument(fileName: string) {
 }
 
 export function getDefaultSchemaLocation() {
-    let location = path.resolve('schema.zmodel');
-
     // handle override from package.json
-    const pkgJson = getPackageJson();
-    if (typeof pkgJson?.zenstack?.schema === 'string') {
-        location = path.resolve(pkgJson.zenstack.schema);
+    const pkgJsonPath = findPackageJson();
+    if (pkgJsonPath) {
+        const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
+        if (typeof pkgJson?.zenstack?.schema === 'string') {
+            if (path.isAbsolute(pkgJson.zenstack.schema)) {
+                return pkgJson.zenstack.schema;
+            } else {
+                // resolve relative to package.json
+                return path.resolve(path.dirname(pkgJsonPath), pkgJson.zenstack.schema);
+            }
+        }
     }
 
-    return location;
+    return path.resolve('schema.zmodel');
 }
diff --git a/packages/schema/src/plugins/prisma/schema-generator.ts b/packages/schema/src/plugins/prisma/schema-generator.ts
index 508e379f3..1d59f7429 100644
--- a/packages/schema/src/plugins/prisma/schema-generator.ts
+++ b/packages/schema/src/plugins/prisma/schema-generator.ts
@@ -48,7 +48,7 @@ import { name } from '.';
 import { getStringLiteral } from '../../language-server/validator/utils';
 import telemetry from '../../telemetry';
 import { execSync } from '../../utils/exec-utils';
-import { getPackageJson } from '../../utils/pkg-utils';
+import { findPackageJson } from '../../utils/pkg-utils';
 import {
     ModelFieldType,
     AttributeArg as PrismaAttributeArg,
@@ -441,15 +441,19 @@ export default class PrismaSchemaGenerator {
 }
 
 export function getDefaultPrismaOutputFile(schemaPath: string) {
-    let result: string | undefined;
-
     // handle override from package.json
-    const pkgJson = getPackageJson();
-    if (typeof pkgJson.zenstack?.prisma === 'string') {
-        result = path.resolve(pkgJson.zenstack.prisma);
-    } else {
-        result = './prisma/schema.prisma';
+    const pkgJsonPath = findPackageJson(path.dirname(schemaPath));
+    if (pkgJsonPath) {
+        const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
+        if (typeof pkgJson?.zenstack?.prisma === 'string') {
+            if (path.isAbsolute(pkgJson.zenstack.prisma)) {
+                return pkgJson.zenstack.prisma;
+            } else {
+                // resolve relative to package.json
+                return path.resolve(path.dirname(pkgJsonPath), pkgJson.zenstack.prisma);
+            }
+        }
     }
 
-    return resolvePath(result, { schemaPath });
+    return resolvePath('./prisma/schema.prisma', { schemaPath });
 }
diff --git a/packages/schema/src/telemetry.ts b/packages/schema/src/telemetry.ts
index 3067063e1..3166a5f9b 100644
--- a/packages/schema/src/telemetry.ts
+++ b/packages/schema/src/telemetry.ts
@@ -3,13 +3,13 @@ import { getPrismaVersion } from '@zenstackhq/sdk';
 import exitHook from 'async-exit-hook';
 import { CommanderError } from 'commander';
 import { init, Mixpanel } from 'mixpanel';
-import { machineIdSync } from 'node-machine-id';
 import * as os from 'os';
 import sleep from 'sleep-promise';
 import { CliError } from './cli/cli-error';
 import { TELEMETRY_TRACKING_TOKEN } from './constants';
 import isDocker from './utils/is-docker';
 import { getVersion } from './utils/version-utils';
+import { getMachineId } from './utils/machine-id-utils';
 
 /**
  * Telemetry events
@@ -32,7 +32,7 @@ export type TelemetryEvents =
  */
 export class Telemetry {
     private readonly mixpanel: Mixpanel | undefined;
-    private readonly hostId = machineIdSync();
+    private readonly hostId = getMachineId();
     private readonly sessionid = createId();
     private readonly _os_type = os.type();
     private readonly _os_release = os.release();
diff --git a/packages/schema/src/utils/machine-id-utils.ts b/packages/schema/src/utils/machine-id-utils.ts
new file mode 100644
index 000000000..db07f3ed3
--- /dev/null
+++ b/packages/schema/src/utils/machine-id-utils.ts
@@ -0,0 +1,11 @@
+import { machineIdSync } from "node-machine-id";
+import { v4 as uuid } from 'uuid';
+
+export function getMachineId() {
+    // machineIdSync() is not compatible with non-shell hosts such as Vercel
+    try {
+        return machineIdSync();
+    } catch {
+        return uuid();
+    }
+}
diff --git a/packages/schema/src/utils/pkg-utils.ts b/packages/schema/src/utils/pkg-utils.ts
index ffb9b0aea..ca4ca127d 100644
--- a/packages/schema/src/utils/pkg-utils.ts
+++ b/packages/schema/src/utils/pkg-utils.ts
@@ -85,9 +85,25 @@ export function ensurePackage(
     }
 }
 
-export function getPackageJson() {
-    const pkgJsonPath = path.join(process.cwd(), 'package.json');
-    if (fs.existsSync(pkgJsonPath)) {
+export function findPackageJson(searchPath?: string) {
+    let currDir = searchPath ?? process.cwd();
+    while (currDir) {
+        const pkgJsonPath = path.join(currDir, 'package.json');
+        if (fs.existsSync(pkgJsonPath)) {
+            return pkgJsonPath;
+        }
+        const up = path.resolve(currDir, '..');
+        if (up === currDir) {
+            return undefined;
+        }
+        currDir = up;
+    }
+    return undefined;
+}
+
+export function getPackageJson(searchPath?: string) {
+    const pkgJsonPath = findPackageJson(searchPath);
+    if (pkgJsonPath) {
         return JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
     } else {
         return undefined;
diff --git a/packages/sdk/package.json b/packages/sdk/package.json
index 878d3fa5f..0b20aaa15 100644
--- a/packages/sdk/package.json
+++ b/packages/sdk/package.json
@@ -1,6 +1,6 @@
 {
     "name": "@zenstackhq/sdk",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "description": "ZenStack plugin development SDK",
     "main": "index.js",
     "scripts": {
diff --git a/packages/server/package.json b/packages/server/package.json
index 9f13ec6ed..4ed8f512e 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -1,6 +1,6 @@
 {
     "name": "@zenstackhq/server",
-    "version": "1.7.1",
+    "version": "1.8.0",
     "displayName": "ZenStack Server-side Adapters",
     "description": "ZenStack server-side adapters",
     "homepage": "https://zenstack.dev",
diff --git a/packages/testtools/package.json b/packages/testtools/package.json
index 66ac699be..ca9d0da60 100644
--- a/packages/testtools/package.json
+++ b/packages/testtools/package.json
@@ -1,6 +1,6 @@
 {
   "name": "@zenstackhq/testtools",
-  "version": "1.7.1",
+  "version": "1.8.0",
   "description": "ZenStack Test Tools",
   "main": "index.js",
   "private": true,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1736e7bba..88968bb7f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1,4 +1,4 @@
-lockfileVersion: '6.0'
+lockfileVersion: '6.1'
 
 settings:
   autoInstallPeers: true
@@ -2816,7 +2816,7 @@ packages:
     hasBin: true
     dependencies:
       detect-libc: 2.0.1
-      https-proxy-agent: 5.0.0
+      https-proxy-agent: 5.0.1
       make-dir: 3.1.0
       node-fetch: 2.6.12
       nopt: 5.0.0
@@ -6609,7 +6609,7 @@ packages:
     dev: true
 
   /concat-map@0.0.1:
-    resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
+    resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
 
   /concurrently@7.4.0:
     resolution: {integrity: sha512-M6AfrueDt/GEna/Vg9BqQ+93yuvzkSKmoTixnwEJkH0LlcGrRC2eCmjeG1tLLHIYfpYJABokqSGyMcXjm96AFA==}
@@ -8149,6 +8149,7 @@ packages:
       glob-parent: 5.1.2
       merge2: 1.4.1
       micromatch: 4.0.5
+    dev: false
 
   /fast-glob@3.3.2:
     resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
@@ -8159,7 +8160,6 @@ packages:
       glob-parent: 5.1.2
       merge2: 1.4.1
       micromatch: 4.0.5
-    dev: false
 
   /fast-json-stable-stringify@2.1.0:
     resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
@@ -8717,7 +8717,7 @@ packages:
     dependencies:
       array-union: 2.1.0
       dir-glob: 3.0.1
-      fast-glob: 3.3.1
+      fast-glob: 3.3.2
       ignore: 5.2.4
       merge2: 1.4.1
       slash: 3.0.0
@@ -8727,7 +8727,7 @@ packages:
     engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
     dependencies:
       dir-glob: 3.0.1
-      fast-glob: 3.3.1
+      fast-glob: 3.3.2
       ignore: 5.2.4
       merge2: 1.4.1
       slash: 4.0.0
@@ -9010,6 +9010,7 @@ packages:
       debug: 4.3.4
     transitivePeerDependencies:
       - supports-color
+    dev: false
 
   /https-proxy-agent@5.0.1:
     resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
@@ -11535,7 +11536,7 @@ packages:
     hasBin: true
     dependencies:
       ansi-colors: 4.1.3
-      fast-glob: 3.3.1
+      fast-glob: 3.3.2
       js-yaml: 4.1.0
       supports-color: 9.4.0
       undici: 5.26.3
@@ -14446,7 +14447,7 @@ packages:
     dependencies:
       '@rollup/pluginutils': 5.0.5(rollup@3.29.4)
       escape-string-regexp: 5.0.0
-      fast-glob: 3.3.1
+      fast-glob: 3.3.2
       local-pkg: 0.4.3
       magic-string: 0.30.4
       mlly: 1.4.2
@@ -14498,7 +14499,7 @@ packages:
       '@vue-macros/common': 1.8.0(vue@3.3.4)
       ast-walker-scope: 0.5.0
       chokidar: 3.5.3
-      fast-glob: 3.3.1
+      fast-glob: 3.3.2
       json5: 2.2.3
       local-pkg: 0.4.3
       mlly: 1.4.2
@@ -14808,7 +14809,7 @@ packages:
       chokidar: 3.5.3
       commander: 8.3.0
       eslint: 8.55.0
-      fast-glob: 3.3.1
+      fast-glob: 3.3.2
       fs-extra: 11.1.1
       lodash.debounce: 4.0.8
       lodash.pick: 4.4.0