-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(react-query): Generate polymorphic route/mutation/query interfac…
…es (#3646)
- Loading branch information
1 parent
a4b195f
commit 3b11de8
Showing
11 changed files
with
910 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export * from './mutationLike'; | ||
export * from './queryLike'; | ||
export * from './routerLike'; | ||
export * from './utilsLike'; |
31 changes: 31 additions & 0 deletions
31
packages/react-query/src/shared/polymorphism/mutationLike.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { AnyProcedure, inferProcedureInput } from '@trpc/server'; | ||
import { inferTransformedProcedureOutput } from '@trpc/server/shared'; | ||
import { | ||
InferMutationOptions, | ||
InferMutationResult, | ||
} from '../../utils/inferReactQueryProcedure'; | ||
|
||
/** | ||
* Use to describe a mutation route which matches a given mutation procedure's interface | ||
*/ | ||
export type MutationLike<TProcedure extends AnyProcedure = AnyProcedure> = { | ||
useMutation: ( | ||
opts?: InferMutationOptions<TProcedure>, | ||
) => InferMutationResult<TProcedure>; | ||
}; | ||
|
||
/** | ||
* Use to unwrap a MutationLike's input | ||
*/ | ||
export type InferMutationLikeInput<TMutationLike extends MutationLike> = | ||
TMutationLike extends MutationLike<infer TProcedure> | ||
? inferProcedureInput<TProcedure> | ||
: never; | ||
|
||
/** | ||
* Use to unwrap a MutationLike's data output | ||
*/ | ||
export type InferMutationLikeData<TMutationLike extends MutationLike> = | ||
TMutationLike extends MutationLike<infer TProcedure> | ||
? inferTransformedProcedureOutput<TProcedure> | ||
: never; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { AnyProcedure, inferProcedureInput } from '@trpc/server'; | ||
import { inferTransformedProcedureOutput } from '@trpc/server/shared'; | ||
import { | ||
InferQueryOptions, | ||
InferQueryResult, | ||
} from '../../utils/inferReactQueryProcedure'; | ||
|
||
/** | ||
* Use to request a query route which matches a given query procedure's interface | ||
*/ | ||
export type QueryLike<TProcedure extends AnyProcedure = AnyProcedure> = { | ||
useQuery: ( | ||
variables: inferProcedureInput<TProcedure>, | ||
opts?: InferQueryOptions<TProcedure, any>, | ||
) => InferQueryResult<TProcedure>; | ||
}; | ||
|
||
/** | ||
* Use to unwrap a QueryLike's input | ||
*/ | ||
export type InferQueryLikeInput<TQueryLike extends QueryLike> = | ||
TQueryLike extends QueryLike<infer TProcedure> | ||
? inferProcedureInput<TProcedure> | ||
: never; | ||
|
||
/** | ||
* Use to unwrap a QueryLike's data output | ||
*/ | ||
export type InferQueryLikeData<TQueryLike extends QueryLike> = | ||
TQueryLike extends QueryLike<infer TProcedure> | ||
? inferTransformedProcedureOutput<TProcedure> | ||
: never; |
23 changes: 23 additions & 0 deletions
23
packages/react-query/src/shared/polymorphism/routerLike.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { | ||
AnyMutationProcedure, | ||
AnyQueryProcedure, | ||
AnyRouter, | ||
} from '@trpc/server'; | ||
import { MutationLike } from './mutationLike'; | ||
import { QueryLike } from './queryLike'; | ||
|
||
/** | ||
* Use to describe a route path which matches a given route's interface | ||
*/ | ||
export type RouterLike< | ||
TRouter extends AnyRouter, | ||
TRecord extends TRouter['_def']['record'] = TRouter['_def']['record'], | ||
> = { | ||
[key in keyof TRecord]: TRecord[key] extends AnyRouter | ||
? RouterLike<TRecord[key]> | ||
: TRecord[key] extends AnyQueryProcedure | ||
? QueryLike<TRecord[key]> | ||
: TRecord[key] extends AnyMutationProcedure | ||
? MutationLike<TRecord[key]> | ||
: never; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { AnyRouter } from '@trpc/server'; | ||
import { DecoratedProcedureUtilsRecord } from '../proxy/utilsProxy'; | ||
|
||
/** | ||
* Use to describe a Utils/Context path which matches the given route's interface | ||
*/ | ||
export type UtilsLike<TRouter extends AnyRouter> = | ||
DecoratedProcedureUtilsRecord<TRouter>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
// | ||
// This file contains a useful pattern in tRPC, | ||
// building factories which can produce common functionality over a homologous data source. | ||
// | ||
import { RouterLike, UtilsLike } from '@trpc/react-query/shared'; | ||
import { AnyRootConfig, TRPCError } from '@trpc/server'; | ||
import { createBuilder } from '@trpc/server/core/internals/procedureBuilder'; | ||
import { createRouterFactory } from '@trpc/server/core/router'; | ||
import z from 'zod'; | ||
|
||
// | ||
// DTOs | ||
// | ||
|
||
export const FileExportRequest = z.object({ | ||
name: z.string().min(0), | ||
filter: z.string().min(0), | ||
}); | ||
|
||
export const FileExportStatus = z.object({ | ||
id: z.number().min(0), | ||
name: z.string().min(0), | ||
downloadUri: z.string().optional(), | ||
createdAt: z.date(), | ||
}); | ||
export type FileExportStatusType = z.infer<typeof FileExportStatus>; | ||
|
||
// | ||
// Dependencies | ||
// | ||
|
||
type RouterFactory<TConfig extends AnyRootConfig> = ReturnType< | ||
typeof createRouterFactory<TConfig> | ||
>; | ||
type BaseProcedure<TConfig extends AnyRootConfig> = ReturnType< | ||
typeof createBuilder<TConfig> | ||
>; | ||
|
||
export type DataProvider = FileExportStatusType[]; | ||
|
||
// | ||
// Set up a route factory which can be re-used for different data sources. | ||
// In this case just with a simple array data source a POC | ||
// | ||
|
||
let COUNTER = 1; | ||
|
||
export function createExportRoute< | ||
TConfig extends AnyRootConfig, | ||
TRouterFactory extends RouterFactory<TConfig>, | ||
TBaseProcedure extends BaseProcedure<TConfig>, | ||
>( | ||
createRouter: TRouterFactory, | ||
baseProcedure: TBaseProcedure, | ||
dataProvider: DataProvider, | ||
) { | ||
return createRouter({ | ||
start: baseProcedure | ||
.input(FileExportRequest) | ||
.output(FileExportStatus) | ||
.mutation(async (opts) => { | ||
const exportInstance: FileExportStatusType = { | ||
id: COUNTER++, | ||
name: opts.input.name, | ||
createdAt: new Date(), | ||
downloadUri: undefined, | ||
}; | ||
|
||
dataProvider.push(exportInstance); | ||
|
||
return exportInstance; | ||
}), | ||
list: baseProcedure.output(z.array(FileExportStatus)).query(async () => { | ||
return dataProvider; | ||
}), | ||
status: baseProcedure | ||
.input(z.object({ id: z.number().min(0) })) | ||
.output(FileExportStatus) | ||
.query(async (opts) => { | ||
const index = dataProvider.findIndex( | ||
(item) => item.id === opts.input.id, | ||
); | ||
|
||
const exportInstance = dataProvider[index]; | ||
|
||
if (!exportInstance) { | ||
throw new TRPCError({ | ||
code: 'NOT_FOUND', | ||
}); | ||
} | ||
|
||
// When status is polled a second time the download should be ready | ||
dataProvider[index] = { | ||
...exportInstance, | ||
downloadUri: `example.com/export-${exportInstance.name}.csv`, | ||
}; | ||
|
||
return exportInstance; | ||
}), | ||
}); | ||
} | ||
|
||
// | ||
// Generate abstract types which can be used by the client | ||
// | ||
|
||
type ExportRouteType = ReturnType<typeof createExportRoute>; | ||
|
||
export type ExportRouteLike = RouterLike<ExportRouteType>; | ||
|
||
export type ExportUtilsLike = UtilsLike<ExportRouteType>; |
Oops, something went wrong.
3b11de8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
www – ./www
www.trpc.io
www-trpc.vercel.app
www-git-main-trpc.vercel.app
trpc.io
beta.trpc.io
alpha.trpc.io
3b11de8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
og-image – ./www/og-image
og-image-three-neon.vercel.app
og-image-trpc.vercel.app
og-image-git-main-trpc.vercel.app
og-image.trpc.io
3b11de8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
next-prisma-starter – ./examples/next-prisma-starter
next-prisma-starter-trpc.vercel.app
nextjs.trpc.io
next-prisma-starter-git-main-trpc.vercel.app