drizzle-orm icon indicating copy to clipboard operation
drizzle-orm copied to clipboard

[FEATURE]: Better migration creation error messaging with improper schema.ts design

Open Wisieneu opened this issue 1 year ago • 3 comments

Describe what you want

I was very confused with how i should setup my schema.ts files - if I export some functions/config objects there, apart from the main pgTable and run drizzle-kit generate:pg --config=drizzle.config.ts I'm getting a ReferenceError: Cannot access 'users' before initialization (this applies to the first declared variable in the schema.ts file(s) mentioned in drizzle.config file) In my opinion there could be a better message informing about what is happening, I tried debugging this for very long taking the ReferenceError into consideration before even trying to run the command with the exported functions commented out. Something like a Warning: Improperly configurated file would be great

Example: this works (migrations are generated):

import { InferInsertModel, InferSelectModel, eq, relations } from 'drizzle-orm';
import { ...columntypes... } from 'drizzle-orm/pg-core';

// User Schema
export const users = pgTable('users', {
  id: uuid('id').defaultRandom().primaryKey(),
  // other colums
});

export type User = InferSelectModel<typeof users>;
export type NewUser = InferInsertModel<typeof users>;

This does not work (getting an error ReferenceError: Cannot access 'users' before initialization):

import { InferInsertModel, InferSelectModel, eq, relations } from 'drizzle-orm';
import { ...columntypes... } from 'drizzle-orm/pg-core';

export const userConfig = {
  minUsernameLength: 5,
  maxUsernameLength: 32,
  maxEmailLength: 256,
  maxPasswordLength: 128,
  minPasswordLength: 128,
  roleEnum: pgEnum('role', ['user', 'mod', 'admin']),
};

// User Schema
export const users = pgTable('users', {
  id: uuid('id').defaultRandom().primaryKey(),
  username: varchar('username', { length: userConfig.maxUsernameLength }).notNull().unique(),
  // other colums
});

export type User = InferSelectModel<typeof users>;
export type NewUser = InferInsertModel<typeof users>;


export function validateNewUser(
  newUserData: Partial<NewUser>
): AppError | null {
  const { username, email, password } = newUserData;
  // function logic
}

Both the function and the config object cause the ReferenceError, it just points to the first variable declared in the schema file (in the code above it points to the userConfig being accessed before initialization, if the export is removed it points to the pgTable). The problem is resolved when the only exported variable is the schema itself (the types are okay)

Wisieneu avatar Feb 09 '24 17:02 Wisieneu

I think the part that made me confused is this part of the documentation: https://orm.drizzle.team/docs/sql-schema-declaration The last code example contains a insertUser function which made me think it's okay to put other functions in the schema file

Wisieneu avatar Feb 09 '24 17:02 Wisieneu

I also noticed today - when running into the same error - that when there are circular dependencies between two files, where one of them is the schema, the same error is outputted. In this case I was completely helpless, wouldn't make it out alive if not for phind.com chatbot :ppp

Wisieneu avatar Feb 10 '24 17:02 Wisieneu

This issue could have been easily avoided if that schema documentation had been properly proofread. Just wasted many hours debugging this issue :/

ironheart122 avatar Sep 28 '24 06:09 ironheart122

This should be addressed better in newer versions of Drizzle ORM and Kit. Kit will filter for only DB entities (tables, enums, etc.) and the documentation now recommends having the schema declaration separate from custom logic. If anything can be improved then anyone can feel free to open a new issue.

L-Mario564 avatar Oct 18 '24 15:10 L-Mario564