kysely-org / kysely

A type-safe typescript SQL query builder
https://kysely.dev
MIT License
9.81k stars 249 forks source link

CamelCasePlugin messes up complex type mappings with setTypeParser #1036

Closed ersinakinci closed 2 weeks ago

ersinakinci commented 3 weeks ago

I'm using Postgres and the pg driver, and I want to map numeric to complex objects using bignumber.js:

// Map numeric to BigNumber.
PG.types.setTypeParser(1700, "text", (value) =>
  null ? null : BigNumber(value)
);

However, when I use CamelCasePlugin, it seems to serialize my mapped values and strip them of any methods:

import {
  Kysely,
  PostgresDialect,
  CamelCasePlugin,
  Transaction,
  sql,
} from "kysely";
import PG from "pg";
import { BigNumber } from "bignumber.js";

const { Pool } = PG;

// Map numeric to BigNumber.
PG.types.setTypeParser(1700, "text", (value) =>
  null ? null : BigNumber(value)
);

export const db = new Kysely<any>({
  dialect: new PostgresDialect({
    pool: new Pool({
      connectionString:
        "postgres://postgres:postgres@localhost:5432/scrappy-cash",
    }),
  }),
  plugins: [new CamelCasePlugin()],
  log(event) {
    if (event.level === "query") {
      console.log(event.query.sql);
      console.log(event.query.parameters);
    }
  },
});

export type DB = Kysely<any>;
export type DBClient = Kysely<any> | Transaction<any>;

const res = await sql`SELECT 0.1::numeric as num`.execute(db);

// Expected: num 0.1
// Actual: num { s: 1, e: -1, c: [ 10000000000000 ] }
console.log("num", res.rows[0].num);

// Expected: num op 0.3
// Actual: TypeError: res.rows[0].num.plus is not a function
console.log("num op", res.rows[0].num.plus(0.2).toString());

I originally created an issue upstream before realizing that CamelCasePlugin was the culprit.

ersinakinci commented 3 weeks ago

Interesting. I messed around a bit and found that setting maintainNestedObjectKeys: true on the plugin config results in the type mapping working correctly.

ersinakinci commented 3 weeks ago

Here's the culprit: https://github.com/kysely-org/kysely/blob/9519ffd2b6ebb6a3e6ed95724f8c171fc4bec6cc/src/plugin/camel-case/camel-case-plugin.ts#L171-L176

isPlainObject is too permissive. https://github.com/kysely-org/kysely/pull/1037 addresses the issue.