I am starting out a new project with Drizzle ORM. Starting out with some assumptions:
The primary keys on all the tables in my database will be uniformly uniformly typed and they will all be called id.
All the foreign keys will be in the form of table_name_id in the database and the model property will always be tableNameId.
Since I can make these assumptions, I thought I could significantly reduce the amount of boilerplate required for specifying foreign keys:
import {
type PgColumn,
type PgTableWithColumns,
pgTableCreator,
serial,
} from "drizzle-orm/pg-core";
import { camelCase, snakeCase } from "lodash";
export const pgTable = pgTableCreator((name) => {
return `some-app_${name}`;
});
export function id() {
return serial("id").primaryKey();
}
type TableWithId = PgTableWithColumns<{
name: string;
schema: string | undefined;
dialect: "pg";
columns: {
id: PgColumn;
};
}>;
export function fk(...relations: (TableWithId | TableWithId[])[]) {
return Object.fromEntries(
relations.flatMap((entry) => {
const isOptional = Array.isArray(entry);
const tables = isOptional ? entry : [entry];
return tables.map((table) => {
const columnName = `${snakeCase(`)}_id`;
const propertyName = `${camelCase(table._.name)}Id`;
const column = bigint(columnName, { mode: "number" }).references(() => {
return table.id;
});
return [propertyName, isOptional ? column : column.notNull()];
});
}),
);
}
This code is intended to be used as such:
export const contact = pgTable("contacts", {
id: id(),
firstName: varchar("first_name", { length: 128 }).notNull(),
lastName: varchar("last_name", { length: 128 }).notNull(),
...fk(phone, [email], [address]),
...timestamps(),
});
Here a relation to the phone and email tables are mandatory (not null), but the relation to the email and address are optional.
The issue arises with accessing the name for a given PgTable. When I inspect the type of contact in my editor I see that they are type hinted with PgTableWithColumns. Which is what I used in the type hint to the fk function.
As a result as far as Typescript is concerned the function is correct. However when I run the code, I get the error:
TypeError: Cannot read properties of undefined (reading 'name')
This is referring to the expression: table._.name. When I log out table, I see that it does not match the type. The underscore property is infact missing, but the name provided to the table is present in a symbol key Symbol(drizzle:BaseName).
However, I am not sure how to access this property as I have not been able to import the symbol from anywhere.
It seems like the types for this package are broken and I might end up filing a bug with drizzle. But I kind of want to get this to work.
Any ideas?
How about getTableName?
import { getTableName } from "drizzle-orm";
const tableName = getTableName(table);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With