Resolvers
Defining the Resolver
Section intitulée « Defining the Resolver »Auto Generated Resolver
Section intitulée « Auto Generated Resolver »The easiest way to get started is to use buildSchema or buildTypeDefsAndResolvers from @lib/type-graphql-query. These functions will automatically create a CRUD resolver for you based on the options you provide.
When you pass resolver options to buildSchema or buildTypeDefsAndResolvers, a CRUD resolver will be automatically generated for each DTO you specify.
import { buildTypeDefsAndResolvers } from '@lib/type-graphql-query';import { Product } from './dto/product.type';import { product as productTable } from '@lib/db';
const { resolvers, typeDefs } = await buildTypeDefsAndResolvers({ resolvers: [ { DTOClass: Product, EntityClass: productTable, enableTotalCount: true, }, ], // ... other options});Generated Endpoints
Section intitulée « Generated Endpoints »When using auto-generated resolvers, the following methods will be exposed for your DTO:
{entityName}- Find a single entity by id (e.g.,product){entityName}s- Filter, sort, and page entities (e.g.,products)createOne{EntityName}- Create a single entity (e.g.,createOneProduct)createMany{EntityNames}- Create multiple entities (e.g.,createManyProducts)updateOne{EntityName}- Update a single entity by id (e.g.,updateOneProduct)updateMany{EntityNames}- Update multiple entities using a filter (e.g.,updateManyProducts)upsertOne{EntityName}- Upsert a single entity (e.g.,upsertOneProduct)upsertMany{EntityNames}- Upsert multiple entities (e.g.,upsertManyProducts)deleteOne{EntityName}- Delete a single entity by id (e.g.,deleteOneProduct)deleteMany{EntityNames}- Delete multiple entities using a filter (e.g.,deleteManyProducts)
You can read more about these methods in the Queries and Mutations documentation.
When defining auto-generated resolvers, you can specify a number of options to control your endpoints.
Basic Options
Section intitulée « Basic Options »DTOClass- The DTO class that the resolver is for. All methods will use types derived from this class.EntityClass- The entity class (usually a Drizzle table) that represents the database entity.enableTotalCount?- When set totrue, enables thetotalCountfield on cursor or offset connections.enableAggregate?- When set totrue, enables aggregate queries on the type and all relations.enableSubscriptions?- Set totrueto enable GraphQL subscriptions. See Subscriptions.pagingStrategy?- The paging strategy to use:PagingStrategies.CURSORorPagingStrategies.OFFSET.
Create Options
Section intitulée « Create Options »CreateDTOClass- The input DTO to use for create mutations. See Create and Update DTOs.create- Options to customize create endpoints:disabled?- Set totrueto disable create endpoints.one?- Options forcreateOneendpoint:name?- Custom name for the mutation.description?- Description for the mutation.authorize?- Authorization options. See Authorization.
many?- Options forcreateManyendpoint (same options asone).
Update Options
Section intitulée « Update Options »UpdateDTOClass- The input DTO to use for update mutations.update- Options to customize update endpoints:disabled?- Set totrueto disable update endpoints.one?- Options forupdateOneendpoint.many?- Options forupdateManyendpoint.
Upsert Options
Section intitulée « Upsert Options »UpsertDTOClass- The input DTO to use for upsert mutations.upsert- Options to customize upsert endpoints:disabled?- Set totrueto disable upsert endpoints.one?- Options forupsertOneendpoint.many?- Options forupsertManyendpoint.
Delete Options
Section intitulée « Delete Options »delete- Options to customize delete endpoints:disabled?- Set totrueto disable delete endpoints.useSoftDelete?- When set totrue, uses soft delete instead of hard delete.one?- Options fordeleteOneendpoint.many?- Options fordeleteManyendpoint.
Read Options
Section intitulée « Read Options »read- Options to customize read endpoints:authorize?- Authorization options for read operations.one?- Options for the single entity query.many?- Options for the list query.
Examples
Section intitulée « Examples »Basic Example
Section intitulée « Basic Example »The simplest resolver configuration:
import { buildTypeDefsAndResolvers } from '@lib/type-graphql-query';import { Product } from './dto/product.type';import { product as productTable } from '@lib/db';
const { resolvers, typeDefs } = await buildTypeDefsAndResolvers({ resolvers: [ { DTOClass: Product, EntityClass: productTable, }, ],});Create and Update DTOs
Section intitulée « Create and Update DTOs »You can specify different DTOs for create and update operations:
import { buildTypeDefsAndResolvers } from '@lib/type-graphql-query';import { Product } from './dto/product.type';import { ProductInput } from './dto/product.input';import { product as productTable } from '@lib/db';
const { resolvers, typeDefs } = await buildTypeDefsAndResolvers({ resolvers: [ { DTOClass: Product, EntityClass: productTable, UpsertDTOClass: ProductInput, create: { disabled: true, // Disable create endpoints }, update: { disabled: true, // Disable update endpoints }, upsert: { // Upsert endpoints will use ProductInput }, }, ],});Disabling Endpoints
Section intitulée « Disabling Endpoints »You can disable specific endpoints:
import { buildTypeDefsAndResolvers } from '@lib/type-graphql-query';import { User } from './dto/user.type';import { user as userTable } from '@lib/db';
const { resolvers, typeDefs } = await buildTypeDefsAndResolvers({ resolvers: [ { DTOClass: User, EntityClass: userTable, create: { disabled: true, // Disable all create endpoints }, update: { disabled: true, // Disable all update endpoints }, delete: { disabled: true, // Disable all delete endpoints useSoftDelete: true, // Use soft delete if enabled }, }, ],});Authorization
Section intitulée « Authorization »You can add authorization to your resolvers:
import { buildTypeDefsAndResolvers, Permission } from '@lib/type-graphql-query';import { Product } from './dto/product.type';import { product as productTable } from '@lib/db';
const { resolvers, typeDefs } = await buildTypeDefsAndResolvers({ resolvers: [ { DTOClass: Product, EntityClass: productTable, read: { authorize: Permission('product.view'), }, create: { authorize: Permission('product.create'), }, update: { authorize: Permission('product.update'), }, delete: { authorize: Permission('product.delete'), }, }, ], auth: { // Authorization configuration // See Authorization documentation },});For more information about authorization, see the Authorization documentation.
Complete Example
Section intitulée « Complete Example »Here’s a complete example with all options:
import { buildTypeDefsAndResolvers, Permission, AllOf } from '@lib/type-graphql-query';import { Product } from './dto/product.type';import { ProductInput } from './dto/product.input';import { ProductAggregate } from './dto/product-aggregate.type';import { product as productTable } from '@lib/db';
const { resolvers, typeDefs } = await buildTypeDefsAndResolvers({ resolvers: [ { DTOClass: Product, EntityClass: productTable, UpsertDTOClass: ProductInput, enableTotalCount: true, enableAggregate: true, AggregateDTOClass: ProductAggregate, enableSubscriptions: true, read: { authorize: Permission('product.view'), }, create: { disabled: true, authorize: Permission('product.create'), }, update: { disabled: true, authorize: Permission('product.update'), }, delete: { disabled: false, useSoftDelete: true, authorize: Permission('product.delete'), }, upsert: { authorize: AllOf(Permission('product.create'), Permission('product.update')), }, }, ], // ... other schema options});Module Pattern
Section intitulée « Module Pattern »You can organize your resolvers in separate modules:
import { TypeGraphqlQueryOptions } from '@lib/type-graphql-query';import { Product } from './dto/product.type';import { ProductInput } from './dto/product.input';import { product as productTable } from '@lib/db';
const resolvers = [ { DTOClass: Product, EntityClass: productTable, UpsertDTOClass: ProductInput, enableTotalCount: true, // ... other options },] satisfies TypeGraphqlQueryOptions['resolvers'];
export default resolvers;Then import them in your schema:
import { buildTypeDefsAndResolvers } from '@lib/type-graphql-query';import productModuleResolvers from './product/product.module';import userModuleResolvers from './user/user.module';
const { resolvers, typeDefs } = await buildTypeDefsAndResolvers({ resolvers: [ ...productModuleResolvers, ...userModuleResolvers, // ... other resolvers ], // ... other options});Custom Resolvers
Section intitulée « Custom Resolvers »You can also create custom resolvers alongside auto-generated ones. Simply pass your custom resolver class to the resolvers array:
import { buildTypeDefsAndResolvers } from '@lib/type-graphql-query';import { Resolver, Query } from '@lib/type-graphql';import { Product } from './dto/product.type';import { product as productTable } from '@lib/db';
@Resolver(() => Product)export class ProductResolver { @Query(() => [Product]) async featuredProducts(): Promise<Product[]> { // Custom implementation }}
const { resolvers, typeDefs } = await buildTypeDefsAndResolvers({ resolvers: [ ProductResolver, // Custom resolver { DTOClass: Product, EntityClass: productTable, }, ],});Next Steps
Section intitulée « Next Steps »- Queries - Query operations with filtering and sorting
- Mutations - Data modifications
- Authorization - Authorization and permissions
- Relations - Entity relationships