Relations

Relations in URPC allow you to define connections between different entities using flexible callback functions. This approach enables you to query related data in a single request with complete control over the relation logic.

Using Regular Repo for Simple Relations

For straightforward relation queries where you have specific where conditions:

import { repo, URPC } from "@unilab/urpc";
import { PostEntity, UserEntity } from "./entities";

// Query a post with its author
const post = await repo<PostEntity>({
  entity: "post",
  source: "demo",
}).findOne({
  where: { id: "1" },
  include: {
    user: (post) => {
      const userId = post.userId;
      return repo<UserEntity>({
        entity: "user",
        source: "demo",
      }).findOne({
        where: { id: userId },
      });
    },
  },
});

Using joinRepo for Optimized Relations

When you need optimized relation mapping, especially for queries without specific where conditions, use joinRepo:

import { repo, URPC, joinRepo } from "@unilab/urpc";

// Query users with their posts using joinRepo
const fetchUser = async () => {
  const data = await repo<UserEntity>({
    entity: "user",
    source: "demo",
  }).findMany({
    include: {
      posts: (userList) => {
        const ids = userList.map((user) => user.id);

        // Use joinRepo for optimized relation mapping, if you don't set the where parameter, you must use joinRepo, but in other cases you can use repo directly.
        return joinRepo<PostEntity, UserEntity>({
          entity: "post",
          source: "demo",
          localField: "id", // User.id
          foreignField: "userId", // Post.userId
        }).findMany({
          where: {
            userId: {
              $in: ids,
            },
          },
        });
      },
    },
  });
  console.log("Users with posts:", JSON.stringify(data, null, 2));
};

One-to-One Relations (findOne)

// Query a post with its author
const post = await repo<PostEntity>({
  entity: "post",
  source: "demo",
}).findOne({
  where: { id: "2" },
  include: {
    user: (post) => {
      const userId = post.userId;
      return repo<UserEntity>({
        entity: "user",
        source: "demo",
      }).findOne({
        where: { id: userId },
      });
    },
  },
});

console.log("Post with author:", post);

One-to-Many Relations (findMany)

// Query users with their posts
const users = await repo<UserEntity>({
  entity: "user",
  source: "demo",
}).findMany({
  where: { id: "1" },
  include: {
    posts: (userList) => {
      const ids = userList.map((user) => user.id);
      return repo<PostEntity>({
        entity: "post",
        source: "demo",
      }).findMany({
        where: {
          userId: { $in: ids },
        },
      });
    },
  },
});

console.log("Users with posts:", users);