valtyr/prisma-kysely

generating wrong type after update

Closed this issue · 12 comments

model User {
  id            BigInt         @id @default(autoincrement())
  publicId      String         @unique @map("public_id") @db.VarChar(30)
  email         String         @unique
  password      String?
  name          String
  photo         String?
  userProviders UserProvider[]
  createdAt     DateTime       @default(now()) @map("create_at")
  updatedAt     DateTime       @default(dbgenerated("CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)")) @map("updated_at")

  @@map("user")
}

BigInt is being generated as number

export type User = {
  id: Generated<number>;
  publicId: string;
  email: string;
  password: string | null;
  name: string;
  photo: string | null;
  createAt: Generated<Timestamp>;
  updatedAt: Generated<Timestamp>;
};

on 1.0.11 is correct generated

export type User = {
  id: Generated<bigint>;
  publicId: string;
  email: string;
  password: string | null;
  name: string;
  photo: string | null;
  createdAt: Generated<Timestamp>;
  updatedAt: Generated<Timestamp>;
};

deps version

 "devDependencies": {
    "prisma": "4.13.0",
    "prisma-kysely": "1.2.0"
 }
valtyr commented

Hey there. A few versions back I ran some real life tests and made sure the types we generate matched the ones returned by the database driver. So in all likelihood the old types (the ones that included bigint) were wrong. Could you tell me what database you're using?

Here's an example of the JS types returned from the SQLite driver:

CleanShot 2023-04-28 at 13 55 47@2x

valtyr commented

According to my tests, the only database driver that doesn't return a number for BigInt is the one for Postgres... and it returns a string.

CleanShot 2023-04-28 at 14 03 57@2x

hello, thanks for the fast response! Im using mysql/planetscale

valtyr commented

Okay and are you using the serverless Planetscale Kysely driver or are you using the MySQL driver. Also, could you verify that typeof user.id is "bigint" when you actually query the database.

using Planetscale Kysely driver, typeof user.id is number on prisma-kysely@1.2.0

valtyr commented

I'd like to clarify some points to ensure we're on the same page. Prisma Kysely only impacts TypeScript types, not the actual runtime types. The determining factor for the runtime types returned by a query is the database driver used by Kysely, rather than the dialect. Consequently, even within a single database type defined in a Prisma schema (e.g., MySQL), there can be various runtime types corresponding to a Prisma type (e.g., BigInt) depending on what driver you're using. This means that Prisma Kysely needs to choose one "sane default" to support for each dialect, and in this case it's the default MySQL driver that Kysely uses out of the box.

Consider the following code:

// Assuming your Kysely instance is called db
const user = await db.selectFrom('User').selectAll().executeTakeFirstOrThrow();
console.log(typeof user.id);

If what you say is true and it outputs "number", it means the database driver returns a number instead of a BigInt, despite having BigInt specified as the database type in your Prisma schema. In this case Prisma Kysely would be generating the correct type.

However, if it outputs "bigint", it indicates the PlanetScale driver behaves differently from the default Kysely MySQL driver. To address this, add an override in your Prisma schema:

generator kysely {
    provider = "prisma-kysely"
    bigIntTypeOverride = "BigInt" // ⬅️ This line here
}

My practical tests show that the correct JavaScript type for Prisma's BigInt type when using the default MySQL driver should be number. Changing it to BigInt would be incorrect for users working with standard MySQL.

valtyr commented

@luccasr73 Check out the source code for the PlanetScale driver's cast function:

https://github.com/planetscale/database-js/blob/8b1a360abd9b7b28ab953984e2aa9bd242d8a169/src/index.ts#L332-L368

It seems to me that it casts all INT types to number.

sorry for the confusion, I did a test by running a select query in the db, the type of the returned id is a string, seems like bigInt is cast as string

running this
Screenshot 2023-04-28 at 17 15 18

return this
Screenshot 2023-04-28 at 17 14 46

in contrast, kysely result.insertedId returns a bigint https://github.com/kysely-org/kysely/blob/dd0319a8/src/query-builder/insert-result.ts#LL39C1-L39C1
Screenshot 2023-04-28 at 17 17 01
Screenshot 2023-04-28 at 17 20 32

planetscale/database-js#86 (comment) this clarify the question about bigInt as string

valtyr commented

Okay wow interesting. Thank you for clarifying. I'll take a better look at this over the weekend and see if there's any recommended approach to this for Kysely. In the meantime, you might be able to use the override I mentioned, or even kysely-planetscale's custom cast function feature https://github.com/depot/kysely-planetscale#custom-cast-function to get around the problem.

by now i will change my pk types to INT, that's enough for the moment, while analyzing the problem I saw that bigint is a cannonball for my problem, I believe that the returned bigInt can be safely converted to number in this way

valtyr commented

I'm not sure whatprisma-kysely can do to support the insertedId type so I'm closing the issue for now.