This guide explains how to implement a new entity in the Hypercerts API, from type definition to resolver implementation.
The Hypercerts API uses a modular architecture where each entity follows a consistent pattern:
- Type Definition
- Query Arguments
- Entity Service
- Resolver
Create a new file in src/graphql/schemas/typeDefs/ for your entity types:
// src/graphql/schemas/typeDefs/yourEntityTypeDefs.ts
import { Field, ObjectType } from "type-graphql";
import { BaseEntity } from "./baseTypes.js";
@ObjectType()
export class YourEntity extends BaseEntity {
@Field(() => String)
name: string;
@Field(() => String, { nullable: true })
description?: string;
// Add other fields as needed
}
@ObjectType()
export class GetYourEntitiesResponse {
@Field(() => [YourEntity])
data: YourEntity[];
@Field(() => Int)
count: number;
}Create a new file in src/graphql/schemas/args/ for your query arguments:
// src/graphql/schemas/args/yourEntityArgs.ts
import { ArgsType } from "type-graphql";
import { createEntityArgs } from "../../../lib/graphql/createEntityArgs.js";
import { EntityTypeDefs } from "../typeDefs/typeDefs.js";
// Define your entity fields
const fields = {
name: "string",
description: "string",
// Add other fields as needed
} as const;
// Create query arguments
export const { WhereInput, SortOptions } = createEntityArgs(
"YourEntity" as EntityTypeDefs,
fields,
);
@ArgsType()
export class GetYourEntitiesArgs {
first?: number;
offset?: number;
where?: typeof WhereInput;
sortBy?: typeof SortOptions;
}Create a new file in src/services/database/entities/ for your entity service:
// src/services/database/entities/YourEntityService.ts
import { injectable } from "tsyringe";
import { createEntityService } from "./EntityServiceFactory.js";
import { GetYourEntitiesArgs } from "../../../graphql/schemas/args/yourEntityArgs.js";
import { YourEntity } from "../../../graphql/schemas/typeDefs/yourEntityTypeDefs.js";
@injectable()
export class YourEntityService {
private service = createEntityService<YourEntity, GetYourEntitiesArgs>(
"your_entity_table",
{
// Add any custom query modifiers if needed
},
);
async getYourEntities(args: GetYourEntitiesArgs) {
return this.service.getMany(args);
}
async getYourEntity(args: GetYourEntitiesArgs) {
return this.service.getSingle(args);
}
}Create a new file in src/graphql/schemas/resolvers/ for your resolver:
// src/graphql/schemas/resolvers/yourEntityResolver.ts
import { inject, injectable } from "tsyringe";
import { Args, Query, Resolver } from "type-graphql";
import { YourEntityService } from "../../../services/database/entities/YourEntityService.js";
import { GetYourEntitiesArgs } from "../args/yourEntityArgs.js";
import {
GetYourEntitiesResponse,
YourEntity,
} from "../typeDefs/yourEntityTypeDefs.js";
@injectable()
@Resolver(() => YourEntity)
class YourEntityResolver {
constructor(
@inject(YourEntityService)
private yourEntityService: YourEntityService,
) {}
@Query(() => GetYourEntitiesResponse)
async yourEntities(@Args() args: GetYourEntitiesArgs) {
return this.yourEntityService.getYourEntities(args);
}
}Add your resolver to the list of resolvers in src/graphql/schemas/resolvers/index.ts:
export * from "./yourEntityResolver.js";- Type Safety: Always use TypeScript's type system to ensure type safety across your implementation.
- Consistent Naming: Follow the existing naming conventions in the codebase.
- Error Handling: Implement proper error handling in your service and resolver methods.
- Testing: Write unit tests for your new entity implementation.
- Documentation: Add JSDoc comments to document your types, methods, and classes.
For a complete example, you can look at the implementation of existing entities like Contract, Metadata, or AttestationSchema in the codebase.
- Type Registration: Ensure all your types are properly registered in the GraphQL schema.
- Dependency Injection: Use the
@injectable()and@inject()decorators correctly. - Query Arguments: Make sure your query arguments match the expected structure.
- Database Schema: Ensure your database table matches the entity structure.
- Start the development server:
pnpm dev - Access the GraphQL playground at
http://localhost:4000/v2/graphql - Test your queries and mutations
- Run the test suite:
pnpm test