-
-
Notifications
You must be signed in to change notification settings - Fork 62
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
Generating iterable union types with kanel-kysely #567
Comments
Searching through the code, I discovered the // invokeKanelProgrammatically.js
import kanel from "kanel";
import config from "../.kanelrc";
const { processDatabase } = kanel;
async function run() {
await processDatabase({ ...config, enumStyle: "type" });
}
run(); For some reason, I can't use it in my The result is: type EntityType =
| 'person'
| 'company';
export default EntityType; Which gets us really close! Could we just simply add a And could we also allow setting |
I thought it was, that's strange! But this is a good point. I was actually contemplating removing the I guess this could be a third enum style. I would also want to rename the type |
Maybe you can set it from the config file? I just know that it doesn't show up in IntelliSense 😛, so at least the types are missing.
Works for me! That would be great. I hope it doesn't go against your design goals too much 😅. |
It's really good if the feature is natively implemented! Current my workaround hook is here: const extractEnumValuesHook = (path, lines) => {
let isEnumFile = lines.some((line) => line.includes('Represents the enum'))
if (!isEnumFile) {
return lines
}
const l = lines.length
for (let i = 0; i < l; i++) {
{
const match = lines[i].match(/export type (.+) =/)
if (match) {
lines.push(`export const ${match[1]}Values = [`)
}
}
{
const match = lines[i].match(/\| '(.+)'/)
if (match) {
lines.push(` '${match[1]}', `)
}
}
}
lines.push('] as const')
return lines
}
module.exports = {
connection: process.env['DATABASE_URL'],
preRenderHooks: [makeKyselyHook(), kyselyCamelCaseHook],
postRenderHooks: [
extractEnumValuesHook,
],
enumStyle: 'type',
} Outputs this: /** Represents the enum public.gender_enum */
export type GenderEnum =
| 'MALE'
| 'FEMALE'
| 'UNKNOWN';
export const GenderEnumValues = [
'MALE',
'FEMALE',
'UNKNOWN',
] as const |
@acro5piano's hook didn't work for me. I'm not sure about his setup, but it looks to me like the type files are exported using I expanded on @acro5piano's hook:
// .kanelrc.ts
const extractEnumValuesHook = (_path: string, lines: string[]) => {
let l = lines.length;
const isTableFile = lines.some((line: string) =>
line.includes("Represents the table")
);
const isEnumFile = lines.some((line: string) =>
line.includes("Represents the enum")
);
if (isTableFile) {
for (let i = 0; i < l; i++) {
const match = lines[i].match(/^import type { default as (.+) }/);
if (match) {
lines[i] = `import type { ${match[1]} } from './${match[1]}';`;
}
}
}
if (isEnumFile) {
for (let i = 0; i < l; i++) {
{
const match = lines[i].match(/^type (.+) =/);
if (match) {
lines[i] = `export const ${match[1]} = [`;
lines.push(`export type ${match[1]} = (typeof ${match[1]})[number];`);
}
}
{
const match = lines[i].match(/^export default/);
if (match) {
lines.splice(i, 1);
l--;
}
}
{
const match = lines[i].match(/\| '(.+)'$/);
if (match) {
lines[i] = ` '${match[1]}', `;
}
}
{
const match = lines[i].match(/\| '(.+)';$/);
if (match) {
lines[i] = ` '${match[1]}',`;
lines.splice(i + 1, 0, `] as const;`);
l++;
}
}
}
}
return lines;
};
// Kanel config
export default {
...,
postRenderHooks: [extractEnumValuesHook],
enumStyle: "type",
}; Example output: EntityType.ts (enum file) /** Represents the enum public.entity_type */
export const EntityType = [
'person',
'sole-proprietorship',
'gp',
'lp',
'corporation',
'llc',
'llp',
'cooperative',
'other',
] as const;
export type EntityType = (typeof EntityType)[number]; Entity.ts (table file) import type { EntityType } from './EntityType';
/** Represents the table public.entity */
export default interface EntityTable {
type: ColumnType<EntityType, EntityType, EntityType>;
...
} Would be great to have this built into Kanel 😄 |
Nice work! I'm happy you got it working. |
I've switched from using enums to iterable type unions, as outlined in this post. I find them much more ergonomic than traditional TS enums and they have the benefit of being iterable.
Any chance that we could get an option in the kanel-kysely plugin to generate this kind of union for PostgreSQL enums instead of native TS enums when using a custom type? For example, instead of generating:
We could generate:
Opt-in API:
The text was updated successfully, but these errors were encountered: