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

Add support for overriding generated types #30

Open
daniel-gato opened this issue Sep 21, 2022 · 8 comments
Open

Add support for overriding generated types #30

daniel-gato opened this issue Sep 21, 2022 · 8 comments
Labels
feature request New feature or request

Comments

@daniel-gato
Copy link

daniel-gato commented Sep 21, 2022

We have many enums columns for which we already have a type defined in our code base.

We are fine with a database column of string type but we would like to be able to force the enum type on our generated sql schema.

Is this doable? Do you see a work around for now?

Upvote & Fund

  • We're using Polar.sh so you can upvote and help fund this issue.
  • We receive the funding once the issue is completed & confirmed by you.
  • Thank you in advance for helping prioritize & fund our backlog.
Fund with Polar
@RobinBlomberg
Copy link
Owner

RobinBlomberg commented Sep 21, 2022

Thanks for the issue!

This has been requested before, and it seems like a feature that needs to exist. I'm not sure how to best achieve this though.

I'm not sure, but perhaps it would be possible to (until it has been added) use a workaround with something like:

import { DB as CodegenDB } from 'kysely-codegen';
import { MyEnum } from './enums';

export type MyTable = Omit<CodegenDB[K], 'myEnum'> & {
  myEnum: MyEnum;
};

export type DB = {
  [K in keyof CodegenDB]: K extends 'myTable' ? MyTable : CodegenDB[K];
};

But I'm open to ideas on how to implement this in a proper way!

@RobinBlomberg
Copy link
Owner

RobinBlomberg commented Sep 29, 2022

First of all, if you're explicitly using user-defined Postgres enums or MySQL enums, it should be solved in this issue that I'm working on: #21.

Some users have reported having text columns that they want to generate as enums however, or want to override built-in types (e.g. if they have a custom parser), such as #31. So some solution may be necessary.


One idea on how to achieve this:

I haven't explicitly tried this, but it should already be possible to override adapter settings programmatically:

import {
  ColumnType,
  IdentifierNode,
  PostgresAdapter,
  UnionExpressionNode,
} from 'kysely-codegen';

class CustomAdapter extends PostgresAdapter {
  constructor() {
    super();

    this.definitions.Int8 = new ColumnType(
      new IdentifierNode('number'),
      new UnionExpressionNode([
        new IdentifierNode('number'),
        new IdentifierNode('bigint'),
      ]),
    )
  }
}

So we could use this to allow overrides using a JS or JSON file.
.kysely-codegen.js

const { ColumnType, IdentifierNode, UnionExpressionNode } = require('kysely-codegen');

module.exports = {
  extends: {
    definitions: {
      Int8: new ColumnType(
        new IdentifierNode('number'),
        new UnionExpressionNode([
          new IdentifierNode('number'),
          new IdentifierNode('bigint'),
        ]),
      ),
    },
  },
};

.kysely-codegen.json

{
  "extend": {
    "definitions": {
      "Int8": {
        "type": "GenericExpression",
        "name": "ColumnType",
        "args": [
          {
            "type": "Identifier",
            "name": "number"
          },
          {
            "type": "UnionExpressionNode",
            "args": [
              {
                "type": "Identifier",
                "name": "number"
              },
              {
                "type": "Identifier",
                "name": "bigint"
              }
            ]
          }
        ]
      }
    }
  }
}

Of course, this would be a difficult API to use, so one further idea would be to implement a very simple TypeScript parser (which would also make it easier to contribute to the code in general):

{
  "extend": {
    "definitions": {
      "Int8": "ColumnType<number, number, bigint>"
    }
  }
}

And some column-level overrides may be necessary:

{
  "columnOverrides": {
    "users.user_status": "\"CONFIRMED\" | \"NOT_CONFIRMED\""
  }
}

Added a separate issue for this: #34

@RobinBlomberg RobinBlomberg added feature request New feature or request and removed more info needed labels Oct 2, 2022
@daniel-gato
Copy link
Author

I'm still trying to figure it out on my side - I'll answer here as soon as I understand the scope of each tool (kysely, kysely-codegen, sst, dataapi)

@RobinBlomberg RobinBlomberg changed the title Migration with custom type field Add support for overriding generated types Oct 12, 2022
@bjornlll
Copy link

Did you get anywhere with this @daniel-gato ?

@thelinuxlich
Copy link

Any workaround for this?

@thelinuxlich
Copy link

My workaround, in this example I'm converting tinyints to SqlBool:

import {
  Generator,
  MysqlDialect,
  MysqlAdapter,
  IdentifierNode
} from 'kysely-codegen'
import { createDbClient } from '../helpers/createDBClient'
import { SCHEMAS } from '../helpers/schemas'

const adapter = new MysqlAdapter()
class _MysqlAdapter extends MysqlAdapter {
  override readonly scalars = {
    ...adapter.scalars,
    tinyint: new IdentifierNode('boolean | 0 | 1')
  }
}

class _MysqlDialect extends MysqlDialect {
  override readonly adapter = new _MysqlAdapter()
}

export const execute = async () => {
  for (const schema of SCHEMAS) {
    const gen = new Generator()
    const db = createDbClient(schema)
    await gen.generate({
      camelCase: false,
      outFile: 'schema.ts',
      schema: schema,
      db,
      dialect: new _MysqlDialect()
    })

    await db.destroy()
  }
  console.log('Kysely types generated.')
}

@elitan
Copy link
Contributor

elitan commented Jan 5, 2024

Why not the other way around? Why not use the types generated by Kysely Codegen and use them in your codebase instead? This way, you have one source of truth (your database) without having to sync enum values between your application code and database?

@thelinuxlich
Copy link

Anyway this should have room for customization, c'mon. I did something to replace kysely-codegen generated types with branded types wherever I needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants