Skip to main content
Version: Next (2.x)

Extend modules

Modules don't have to own their types end-to-end. A second module can extend a type defined elsewhere — useful when different concerns live in different folders. Here we add a photos field to the existing User type from a separate user-photos module.

1. Define the schema

Create a new schema file at src/modules/user-photos/user-photos.gql:

type UserPhoto {
id: ID!
url: String!
}

extend type User {
photos: [UserPhoto!]
}
tip

The GraphQL extend keyword is what makes this cross-module: any module can add fields to a type declared elsewhere, and Baeta stitches them together at build time.

2. Generate the types

yarn build

The watcher (started via yarn start) regenerates types on save, so you only run yarn build manually.

3. Implement the resolvers

src/modules/user-photos/resolvers.ts:

import { UserPhotosModule } from "./typedef.ts";

const { UserPhoto, User } = UserPhotosModule;

export const userPhotosResolver = UserPhoto.$fields({
id: UserPhoto.id.key("id"),
url: UserPhoto.url.key("url"),
});

export const userResolver = User.$fields({
photos: User.photos.resolve(() => {
return [
{
id: "1",
url: "https://example.com/photo.jpg",
},
];
}),
});

4. Export the module

src/modules/user-photos/index.ts:

import { userPhotosResolver, userResolver } from "./resolvers.ts";
import { UserPhotosModule } from "./typedef.ts";

export default UserPhotosModule.$schema({
UserPhoto: userPhotosResolver,
User: userResolver,
});

Project structure

src/modules/
├── user/
│ ├── user.gql
│ ├── resolvers.ts
│ ├── typedef.ts
│ └── index.ts
├── user-photos/
│ ├── user-photos.gql
│ ├── resolvers.ts
│ ├── typedef.ts
│ └── index.ts
└── index.ts # generated; collects every module in this folder

Next

Wire everything into a running server.