The `contract` Package
Relevant source files
The following files were used as context for generating this wiki page:
The contract package is a crucial shared module within the contract-based-monorepo. Its primary purpose is to define a strict, type-safe API contract between the frontend (web) and backend (api) applications. This "contract-first" approach ensures that both the client and server have a single source of truth for API endpoints, request/response shapes, and data models, which helps prevent integration errors and enables robust type-checking across the entire monorepo.
This package leverages oRPC for defining Remote Procedure Call (RPC) endpoints and Zod for schema definition and validation. It serves as a central hub for all API contracts and schemas, making it a foundational piece of the project's architecture.
Sources: README.md, packages/contract/README.md, packages/contract/package.json
Core Technologies
The package relies on a few key libraries to establish the API contract.
| Dependency | Purpose |
|---|---|
@orpc/contract | Core library for defining the oRPC contract. |
@orpc/zod | Integrates Zod for schema validation in oRPC. |
zod | A TypeScript-first schema declaration and validation library. |
Sources: packages/contract/package.json:13-17
The following diagram illustrates the relationship between these technologies.
Package Structure
The contract package has a simple structure, exporting its entire public API from the root index.ts file. This file re-exports all definitions from the contract and schemas subdirectories.
// packages/contract/src/index.ts
export * from "./contract";
export * from "./schemas";
Sources: packages/contract/src/index.ts:1-2
This structure is visualized below:
Sources: packages/contract/src/index.ts:1-2
API Contract Definition
The core of the package is the contract object, which defines all available API procedures. These procedures are grouped by domain (auth, planet) or functionality (sse).
Sources: packages/contract/src/contract/index.ts
Contract Procedures
The contract object is composed of nested objects that organize the API endpoints.
// packages/contract/src/contract/index.ts
import { me, signin, signup } from "./auth";
import { createPlanet, findPlanet, listPlanets, updatePlanet } from "./planet";
import { sse } from "./sse";
export const contract = {
auth: {
signup,
signin,
me,
},
planet: {
list: listPlanets,
create: createPlanet,
find: findPlanet,
update: updatePlanet,
},
sse,
};
Sources: packages/contract/src/contract/index.ts:1-19
The table below summarizes the defined procedures.
| Group | Procedure | Description (Inferred from name) |
|---|---|---|
auth | signup | Handles user registration. |
auth | signin | Handles user login. |
auth | me | Fetches the current user's profile. |
planet | list | Lists available planets. |
planet | create | Creates a new planet. |
planet | find | Finds a single planet by ID. |
planet | update | Updates an existing planet. |
sse | sse | A Server-Sent Events endpoint. |
Sources: packages/contract/src/contract/index.ts:4-18
Schema Definitions
While packages/contract/src/schemas/index.ts is the designated location for Zod schemas, the actual type definitions are consumed in other parts of the monorepo, such as the api server's middleware. These types are exported from the contract package and represent the data models used in API requests and responses.
Key data types imported from the contract include:
UserPlanetNewPlanetUpdatePlanet
Sources: apps/api/src/middlewares/db.ts:2-7
The structure of the Planet and User types can be inferred from their usage.
This diagram shows the relationship between a Planet and its creator, which is a User.
Sources: apps/api/src/middlewares/db.ts:37-45, apps/api/src/middlewares/db.ts:8-15
Usage and Integration
The contract package is a workspace dependency for the api application, allowing the backend to use the defined contract for routing, validation, and generating API documentation.
Sources: apps/api/package.json:12
OpenAPI Specification Generation
The api server uses the contract object to automatically generate an OpenAPI specification. An OpenAPIGenerator instance is configured to use a ZodToJsonSchemaConverter, which translates the Zod schemas from the contract into a JSON Schema compatible with OpenAPI.
This flow is illustrated below:
This diagram shows how the contract object is processed to produce interactive API documentation.
Sources: apps/api/src/handlers/openapi.ts:1-29
Data Type Consumption
The data types defined in the contract are used throughout the api application's logic. For example, the fake database middleware in apps/api/src/middlewares/db.ts uses the Planet, NewPlanet, and UpdatePlanet types for its function signatures and internal data structures. This ensures that the data manipulation logic adheres to the contract.
// apps/api/src/middlewares/db.ts
export interface DB {
planets: {
find: (id: number) => Promise<Planet | undefined>;
list: (limit: number, cursor: number) => Promise<Planet[]>;
create: (newPlanet: NewPlanet, creator: User) => Promise<Planet>;
update: (updatePlanet: UpdatePlanet) => Promise<Planet>;
};
}
Sources: apps/api/src/middlewares/db.ts:8-15
Conclusion
The @contract-based-monorepo/contract package is the cornerstone of this project's architecture. By providing a single, type-safe definition for the API, it enables seamless and error-resistant communication between the frontend and backend. Its use of oRPC and Zod facilitates clear API design, automatic validation, and streamlined generation of developer-friendly documentation, embodying the principles of a modern, contract-first development workflow.
Sources: README.md, packages/contract/package.json