kristiandupont / kanel

Generate Typescript types from Postgres
https://kristiandupont.github.io/kanel/
MIT License
880 stars 62 forks source link

Allow customizing enum properties #310

Open ozonep opened 2 years ago

ozonep commented 2 years ago

Just wanted to ask if you plan to allow customizing enum generator? :) Something similar to getPropertyMetaData? In our flow we use capitalised and slightly altered 'property' names, example: enum column with possible values 'dog', 'cat', 'one-of-a-kind' is supposed to be generated to:

enum enumValues {
  Dog = 'dog'
  Cat = 'cat'
 OneOfAKind = 'one-of-a-kind'
}

Currently we use custom logic for doing this (we're still on v2). In v3 it's hardcoded, so it always outputs this:

enum enumValues {
  dog = 'dog'
  cat = 'cat'
 'one-of-a-kind' = 'one-of-a-kind'
}

This means I have to use postRenderHook to go over processed files and change lines manually in case it's enum, which is not very readable. I can help with PR if this is something you want to add.

kristiandupont commented 2 years ago

Ah, interesting. The only variation I could think of was people wanting to use type x = 'a' | 'b' ..., but I can see yours being valuable as well. As you can see here, I had started to work in this direction but it didn't seem priority so I left it there.

I would be happy to accept a PR if you have the time. Can you think of an intuitive way to allow for people to select the type style, or give names like you want with one configuration option?

ozonep commented 2 years ago

I'll have a closer look later this week :) Initially I only considered it to be done through an extra hook, let's say "getEnumMetaData" that would allow passing custom logic altering names (uppercasing/camelCasing etc.). But I guess it could also be done through comments? Having pre-defined options like "CapitalizeCamelCase", "camelCase", "default (as-is)" that you add through "@type: CapitalizeCamelCase".
What else would you want to do with enums anyway?

Update: Actually, it's not good approach. Enum naming needs to be consistent, so it doesn't make sense to add comments to every enum column in the DB. It should be defined somewhere at the top-level, for the whole DB.

kristiandupont commented 2 years ago

Well, one thing I am just recalling (which was why I even considered using enum instead of type) is that you could have comments above each item:

enum Status {
  /** When connected */
  ONLINE,

  /** When disconnected */
  OFFLINE
}

Now, this is one of the very few cases where Postgres doesn't have support natively which is why I didn't implement anything for it. But one could imagine a scenario where the comments could come from somewhere else, like a file or an array parsed from a comment on the enum itself.

So, I can see three approaches, off the top of my head: 1) We extend getMetadata to return enum-specific data for enums. That could be style: 'enum' | 'type', as well as items: { name: string, comment?: string[] }[] (which would only be valid if style was enum). 2) We introduce getEnumMetadata which returns something similar to the above, or finally 3) We introduce getEnumItemMetadata which would simply return name and comment for one item in an enum. With this solution, it would not be possible to use type, but maybe that's overengineering it anyway..

I am not sure which I prefer, or if there is a fourth solution that I am missing. Do you have a preference?

ozonep commented 2 years ago

Personally I'd go with the 3rd approach for now, just to make it simpler :) Can be refactored later based on new feedback etc.

kristiandupont commented 2 years ago

Well, the "refactor later" argument is a bit less valid for a public library. The v3 release had major breaking changes, I hope I won't have to do that again anytime soon.

That said, I think approach 3 will work just fine for most people for a long time, so I can live with that. If you would like to take a stab at it, go ahead!