skoshx / pentagon

Prisma-like ORM built on top of Deno KV. Allows you to write your database schemas and relations using Zod schemas, and run queries using familiar syntax from Prisma.
https://dash.deno.com/playground/pentagon-demo
MIT License
155 stars 5 forks source link

How to dynamically include relations? #36

Closed waptik closed 8 months ago

waptik commented 1 year ago

So i'm creating a helper function that will include relations on demand. The issue is that with my approach, the relations are not included in the output


// function definition

type Include = "chats" | "members" | "subscriptions" | "plans";
export async function getProject(
  id: string,
  add: Include[] = []
) {
  const include: Record<Include, boolean> | undefined = undefined;

  if (add.length > 0) {
    add.forEach((i) => {
      Object.assign(include!, { [i]: true });
    });
  }
  const project = await pentagon.projects.findFirst({
    where: {
      id,
    },
    include: include? include : undefined,
  });

  if (!project) {
    throw new Error("Project not found");
  }

  return project;
}

// usage with where id is some valid uuid value
  const project = await getProject(id ["chats"]);

    project.chats;

I get the following intellisense typescript error in vscode when i hover to chats in project.chats

Property 'chats' does not exist on type 'QueryResponse<{ schema: ZodObject<{ id: ZodDefault<ZodString>; ... 7 more ...; updatedAt: ZodNullable<...>; }, "strip", ZodTypeAny, { ...; }, { ...; }>; relations: { ...; }; }, { ...; }>'.deno-ts(2339)
skoshx commented 1 year ago

Hello, dynamically including relations doesn't really work unfortunately, because TypeScript cannot then statically infer the types.

I think your approach can be made to work by adding some type constraints to the Include type, such that it would be Include extends X ... instead of just the strings chats etc.