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.