Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Related data not present in result when specifying include. #62

Open
vikt0r0 opened this issue Feb 4, 2023 · 3 comments
Open

Related data not present in result when specifying include. #62

vikt0r0 opened this issue Feb 4, 2023 · 3 comments
Labels
bug Something isn't working help wanted Extra attention is needed

Comments

@vikt0r0
Copy link

vikt0r0 commented Feb 4, 2023

Bug description

Related data when using include in queries not available.

When issuing a query, e.g.:

const jobsQuery = trpc.job.findManyJob.useQuery({
  take: 40,
  include: { employer: true },
});

the logs show that the correct database queries are made to retrieve the model specified in the include directive from the DB.

However the related data is not present in the result-object, rather just the fields of basic types relationships. This is despite the relations being properly defined in the schema (i.e. the relationships work in Prisma studio). In particular I can do the following:

{jobsQuery.data?.map((job) => {
  <p>{job.employerId}</p>;
})}

while the following does not work:

{jobsQuery.data?.map((job) => {
  <p>{job.employer}</p>;
})}

In the past, that is, before include and select was a feature, the returned type was that of the model generated from the Prisma schema, in this case Job. Now it is SerializeObject<UndefinedToOptional<Job>>. I do not know if this is related to the issue.

I may be doing something wrong, but another person is experiencing this as well, so it may be version-specific or perhaps the docs are hard to understand (or I am just bad at reading), but I tried numerous times to get it to work to no avail.

How to reproduce

  1. Create bare-bones trpc-prisma-starter project using the setup guide and the dependencies listed in "Environment and Setup".
  2. Generate the model.
  3. Run a query with include.

If you let me know I can share the project in question, since it includes a lot of boilerplate.

Expected behavior

I expect that upon invoking the following query:

const jobsQuery = trpc.job.findManyJob.useQuery({
  take: 40,
  include: { employer: true },
});

I should be able to do things like:

{jobsQuery.data?.map((job) => {
  <p>{job.employer.name}</p>;
})}

however the field is not present in the object.

Prisma information

datasource db {
  provider = "postgres"
  url      = env("DATABASE_URL")
}

generator trpc {
  provider       = "prisma-trpc-generator"
  withMiddleware = false
  withShield     = false
  contextPath       = "../src/server/context"
  isGenerateSelect   = true
  isGenerateInclude  = true
}

generator client {
  provider = "prisma-client-js"
}

generator erd {
  provider = "prisma-erd-generator"
  theme = "default"
}

model Post {
  id    String @id @default(uuid())
  title String
  text  String

  // To return `Date`s intact through the API we use transformers
  // https://trpc.io/docs/data-transformers
  // This is unique so it can be used for cursor-based pagination
  createdAt DateTime @default(now())
  updatedAt DateTime @default(now()) @updatedAt
}

model Job {
  id          String     @id @default(cuid())
  title       String     @db.VarChar(255)
  description String     @db.Text
  employerId  String
  employer    User       @relation(fields: [employerId], references: [id], onDelete: Cascade)
  addressId   String
  address     Address    @relation(fields: [addressId], references: [id], onDelete: Cascade)
  fields      JobField[]
  createdAt   DateTime   @default(now()) @map(name: "created_at")
  updatedAt   DateTime   @updatedAt @map(name: "updated_at")
}

model JobField {
  id   String @id @default(cuid())
  text String @unique
  jobs Job[]
}

model Address {
  id        String    @id @default(cuid())
  name      String?   @db.Text
  street    String    @db.Text
  city      String    @db.Text
  zip       String    @db.Text
  latitude  String?   @db.Text
  longitude String?   @db.Text
  countryId String
  country   Country   @relation(fields: [countryId], references: [id])
  jobs      Job[]
}

model Country {
  id      String    @id @default(cuid())
  name    String    @unique
  Address Address[]
}

model Session {
  id           Int      @id @default(autoincrement())
  sessionToken String   @unique @map("session_token")
  userId       String   @map("user_id")
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@map("sessions")
}

model User {
  id            String    @id @default(cuid())
  role          Role
  name          String    @db.VarChar(255)
  description   String
  imageUrl      String?   @db.Text
  email         String?   @unique
  emailVerified DateTime? @map("email_verified")
  jobs          Job[]
  createdAt     DateTime  @default(now()) @map(name: "created_at")
  updatedAt     DateTime  @updatedAt @map(name: "updated_at")
  sessions      Session[]

  @@map(name: "users")
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
  @@map("verificationtokens")
}

enum Role {
  EMPLOYER
  APPLICANT
}

Environment & setup

  • OS: Mac OS
  • Database: PostgreSQL
  • Node.js version: v16.15.1

Using package.yaml:

{
  "name": "@examples/trpc-next-prisma-starter",
  "version": "10.9.0",
  "private": true,
  "scripts": {
    "migrate-postgres": "prisma migrate dev",
    "generate-postgres": "prisma generate",
    "prisma-studio-postgres": "prisma studio",
    "db-seed": "prisma db seed",
    "db-reset": "prisma migrate reset",
    "dx:next": "run-s migrate-postgres generate-postgres && next dev",
    "dx:prisma-studio": "pnpm prisma-studio-postgres",
    "dx": "run-p dx:* --print-label",
    "dev": "pnpm dx:next",
    "build-postgres": "run-s generate-postgres migrate && next build",
    "build": "pnpm build-postgres",
    "start": "next start",
    "lint": "eslint --ext \".js,.ts,.tsx\" --report-unused-disable-directives --report-unused-disable-directives src",
    "lint-fix": "pnpm lint --fix",
    "migrate-dev": "prisma migrate dev",
    "migrate": "prisma migrate deploy",
    "test": "run-s test:*",
    "test:unit": "vitest run",
    "test:e2e": "playwright test",
    "test-dev": "start-server-and-test 'next dev' http://127.0.0.1:3000 test",
    "test-start": "start-server-and-test start http://127.0.0.1:3000 test",
    "postinstall": "prisma generate"
  },
  "prisma": {
    "seed": "tsx prisma/seed.ts"
  },
  "prettier": {
    "printWidth": 80,
    "trailingComma": "all",
    "singleQuote": true
  },
  "dependencies": {
    "@prisma/client": "^4.7.1",
    "@tanstack/react-query": "^4.3.8",
    "@trpc/client": "^10.9.0",
    "@trpc/next": "^10.9.0",
    "@trpc/react-query": "^10.9.0",
    "@trpc/server": "^10.9.0",
    "clsx": "^1.1.1",
    "next": "^13.0.0",
    "prisma-trpc-generator": "^1.0.2",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "superjson": "^1.7.4",
    "zod": "^3.0.0"
  },
  "devDependencies": {
    "@faker-js/faker": "^7.6.0",
    "@mermaid-js/mermaid-cli": "^9.3.0",
    "@playwright/test": "^1.26.1",
    "@types/node": "^18.7.20",
    "@types/react": "^18.0.9",
    "@typescript-eslint/eslint-plugin": "^5.47.0",
    "@typescript-eslint/parser": "^5.47.0",
    "eslint": "^8.30.0",
    "eslint-config-next": "^13.1.0",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-react": "^7.31.11",
    "eslint-plugin-react-hooks": "^4.6.0",
    "npm-run-all": "^4.1.5",
    "prettier": "^2.7.1",
    "prisma": "^4.7.1",
    "prisma-erd-generator": "^1.2.5",
    "start-server-and-test": "^1.12.0",
    "tsx": "^3.9.0",
    "typescript": "^4.8.3",
    "vite": "^3.1.3",
    "vitest": "^0.23.4"
  },
  "publishConfig": {
    "access": "restricted"
  }
}

Prisma Version

Environment variables loaded from .env
prisma                  : 4.8.1
@prisma/client          : 4.8.1
Current platform        : darwin-arm64
Query Engine (Node-API) : libquery-engine d6e67a83f971b175a593ccc12e15c4a757f93ffe (at node_modules/@prisma/engines/libquery_engine-darwin-arm64.dylib.node)
Migration Engine        : migration-engine-cli d6e67a83f971b175a593ccc12e15c4a757f93ffe (at node_modules/@prisma/engines/migration-engine-darwin-arm64)
Introspection Engine    : introspection-core d6e67a83f971b175a593ccc12e15c4a757f93ffe (at node_modules/@prisma/engines/introspection-engine-darwin-arm64)
Format Binary           : prisma-fmt d6e67a83f971b175a593ccc12e15c4a757f93ffe (at node_modules/@prisma/engines/prisma-fmt-darwin-arm64)
Format Wasm             : @prisma/prisma-fmt-wasm 4.8.0-61.d6e67a83f971b175a593ccc12e15c4a757f93ffe
Default Engines Hash    : d6e67a83f971b175a593ccc12e15c4a757f93ffe
Studio                  : 0.479.0
@omar-dulaimi omar-dulaimi added the bug Something isn't working label Feb 10, 2023
@omar-dulaimi
Copy link
Owner

Hey, I think this is related to your issue: #61
The user seems to have found a workaround

@omar-dulaimi omar-dulaimi added the help wanted Extra attention is needed label Feb 10, 2023
@just-maik
Copy link

I think we could integrate this "workaround" which gets the PayloadType by inferring the query parameters as said in #61
Maybe when enabling "include" the generator should add this inference. so that included or selected relational fields show up in the procedures return type. Definitely a pretty important thing to offer for typescript users.

@just-maik
Copy link

just-maik commented Oct 11, 2023

I went into a little rabbithole.
I tried to get the Payload type with Prisma.TableGetPayload<typeof input> which does work when passing it to useQuery<myPayloadTyle> and infers my types when including in a predefined query input. Then I tried to add this to a generated FindFirst procedure but because at this scope it cannot infer the type given the input. It seems to me this is an intricate typescript inference story...

At this point I think it could only be done by some genetic payload wrapper type in the useQuery call to pass down the type of the query input directly to the Prisma call and back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

3 participants