In this post, we will guide you through setting up a Node.js project using TypeORM with Apollo Federation. This combination allows you to create a scalable and performant GraphQL API by leveraging TypeORM’s robust ORM capabilities and Apollo Federation’s powerful schema stitching and microservices architecture.

Introduction

TypeORM is an ORM for TypeScript and JavaScript (ES7, ES6, ES5). It supports various databases like MySQL, PostgreSQL, MariaDB, SQLite, and more. Apollo Federation is a powerful tool for building a distributed GraphQL architecture, allowing multiple GraphQL services to work together as a single data graph.

By combining these two technologies, you can build a robust backend service that efficiently manages data with TypeORM while serving it through a federated GraphQL API using Apollo Federation.

Prerequisites

  • Node.js and npm installed on your machine
  • Basic knowledge of TypeScript
  • Basic understanding of GraphQL and Apollo Federation
  • A PostgreSQL database up and running

Setting Up the Project

Step 1: Initialize the Project

First, create a new Node.js project:

1
2
3
mkdir typeorm-apollo-federation
cd typeorm-apollo-federation
npm init -y

Step 2: Install Dependencies

Install the necessary packages:

1
2
npm install typeorm reflect-metadata pg @apollo/server graphql @apollo/federation @apollo/subgraph apollo-datasource @apollo/federation-directives
npm install typescript ts-node @types/node @types/graphql --save-dev

Step 3: Configure TypeScript

Create a tsconfig.json file:

1
2
3
4
5
6
7
8
9
10
11
12
{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}

Step 4: Set Up TypeORM

Create a ormconfig.json file to configure TypeORM:

1
2
3
4
5
6
7
8
9
10
11
{
  "type": "postgres",
  "host": "localhost",
  "port": 5432,
  "username": "your_username",
  "password": "your_password",
  "database": "your_database",
  "synchronize": true,
  "logging": false,
  "entities": ["src/entity/**/*.ts"]
}

Create a directory structure for the project:

1
mkdir -p src/entity

Step 5: Create an Entity

Create a User entity in src/entity/User.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity } from "typeorm";

@Entity()
export class User extends BaseEntity {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  firstName: string;

  @Column()
  lastName: string;
}

Step 6: Set Up Apollo Server with Federation

Create a new file src/index.ts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import "reflect-metadata";
import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";
import { buildFederatedSchema } from "@apollo/federation";
import { typeDefs, resolvers } from "./schema";
import { DataSource } from "typeorm";
import { User } from "./entity/User";

// Initialize TypeORM
const AppDataSource = new DataSource({
  type: "postgres",
  host: "localhost",
  port: 5432,
  username: "your_username",
  password: "your_password",
  database: "your_database",
  synchronize: true,
  logging: false,
  entities: [User],
});

AppDataSource.initialize().then(async () => {
  // Create Apollo Federation schema
  const schema = buildFederatedSchema([
    {
      typeDefs,
      resolvers,
    },
  ]);

  // Create Apollo Server
  const server = new ApolloServer({ schema });

  // Start Apollo Server
  const { url } = await startStandaloneServer(server, {
    context: async () => ({
      dataSource: AppDataSource,
    }),
  });

  console.log(`🚀 Server ready at ${url}`);
}).catch(error => console.log(error));

Step 7: Define GraphQL Schema and Resolvers

Create a src/schema.ts file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { gql } from "apollo-server";
import { User } from "./entity/User";

export const typeDefs = gql`
  type User @key(fields: "id") {
    id: ID!
    firstName: String!
    lastName: String!
  }

  extend type Query {
    users: [User]
    user(id: ID!): User
  }

  extend type Mutation {
    createUser(firstName: String!, lastName: String!): User
  }
`;

export const resolvers = {
  Query: {
    users: async () => User.find(),
    user: async (_, { id }) => User.findOneBy({ id }),
  },
  Mutation: {
    createUser: async (_, { firstName, lastName }) => {
      const user = User.create({ firstName, lastName });
      await user.save();
      return user;
    },
  },
};

Running the Project

To run the project, compile the TypeScript files and start the server:

1
npx ts-node src/index.ts

Your Apollo Federation server with TypeORM is now running. You can interact with it through the GraphQL playground at the server URL, typically http://localhost:4000.

Conclusion

By following these steps, you’ve set up a Node.js project using TypeORM with Apollo Federation. This setup allows you to efficiently manage your database and serve it through a scalable and performant GraphQL API. As your application grows, you can easily add more federated services to your architecture, maintaining a seamless and integrated data graph.

For further reading, you can check the official TypeORM documentation and Apollo Federation documentation.


[alex_rocha] by alex

🇧🇷Senior Software Developer