valtyr / prisma-kysely

🪄 Generate Kysely types directly from your Prisma schema!
https://www.npmjs.com/package/prisma-kysely
MIT License
949 stars 36 forks source link

[BUG] Prisma Decimal gets converted into kysely String #78

Closed wikes82 closed 9 months ago

wikes82 commented 1 year ago

When converting Decimal type of prisma, it converted into string instead of number.

Sample Schema:

generator kysely {
  provider     = "prisma-kysely"
  output       = "../src/kyselydb"
  fileName     = "kysely-types.ts"
  enumFileName = "kysely-enums.ts"
}

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

datasource db {
  provider = "cockroachdb"
  url      = env("DEMODEV_DATABASE_URL")
}
model TestModel {
    id                   String             @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
   credit_rate      Decimal
}

the generated kysely types:

export type TestModel = {
    id: Generated<string>;
    credit_rate: string;
}
valtyr commented 1 year ago

I think this is actually the result type returned by the driver. Can you check?

wikes82 commented 1 year ago

@valtyr No, the mapping on this file is wrong for postgresql and mysql -> https://github.com/valtyr/prisma-kysely/blob/main/src/helpers/generateFieldType.ts

Cockroachdb is using postgresql driver

delight commented 1 year ago

I can confirm the behavior:

prisma: expires BigInt?

results in kysely: expires: string | null

Using provider = "postgresql" here.

cahnory commented 1 year ago

The node pg driver will in fact return a string for decimal and bigint types for technical reason (MAX_SAFE_INTEGER): https://github.com/brianc/node-postgres/issues/811#issuecomment-116644535

You can setup pg driver to typecast numeric value:

import { types } from "pg";

types.setTypeParser(types.builtins.NUMERIC, (value) => Number(value));

And override types in your schema generator config:

generator kysely {
  provider            = "prisma-kysely"
  output              = "../src/kyselydb"
  fileName            = "kysely-types.ts"
  enumFileName        = "kysely-enums.ts"
  decimalTypeOverride = "number"
  bigIntTypeOverride  = "number"
}
delight commented 1 year ago

I understand the MAX_SAFE_INTEGER problem in JS - but right here I don't think that is the problem.

I assume if you'd have a BigInt or similar in the database and you wouldn't use string in the kysely-types definition. And this is what this is about, translation of a prisma schema to kysely types.

valtyr commented 1 year ago

@delight There's a file called src/dialectTests/postgresql.ts that runs a very simple test. It creates the database with all the types supported by prisma-kysely, queries all the fields, and prints out the typeof for all the fields. I used this to verify the types for each dialect when I wrote the initial versions of prisma-kysely. It confirms that the driver indeed returns a string type when querying a BigInt. Remember that prisma-kysely only operates in type land and has to be opinionated by default to support the types returned by the standard kysely driver for each dialect. If you want the string to be parsed into a BigInt object after a query, or if it turns out that you're using some non-standard driver or have configured it differently then I refer to @cahnory's solution above. If we were to change the type we would break prisma-kysely for everyone else. If you are interested in running the test for yourself, you can run docker compose up -d postgres in the root directory to boot a database and run yarn run build && node dist/dialectTests/postgresql.js to run the tests.

CleanShot 2023-11-01 at 10 19 49@2x
valtyr commented 1 year ago

Oh and here are the results for mysql:

CleanShot 2023-11-01 at 10 29 31@2x
valtyr commented 9 months ago

Closing this as per my comments above.