drizzle-team / drizzle-orm

Headless TypeScript ORM with a head. Runs on Node, Bun and Deno. Lives on the Edge and yes, it's a JavaScript ORM too 😅
https://orm.drizzle.team
Apache License 2.0
21.84k stars 496 forks source link

[BUG]: #2080

Closed haocloo closed 3 months ago

haocloo commented 3 months ago

What version of drizzle-orm are you using?

0.30.0

What version of drizzle-kit are you using?

^0.20.14

Describe the Bug

I'm using Supabase too. I'm getting this error:

TypeError: Cannot read properties of undefined (reading 'findMany')
    at Module.getAllRestaurantsByVendor (projectfolder/src/modules/restaurant/db.ts:22:74)
    at Module.GET (projectfolder/src/pages/api/restaurant/index.ts:17:48)
    at eval (projectfolder/src/pages/restaurant/index.astro:27:46)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async callComponentAsTemplateResultOrResponse (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/runtime/server/render/astro/render.js:87:25)
    at async renderToAsyncIterable (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/runtime/server/render/astro/render.js:115:26)
    at async renderPage (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/runtime/server/render/page.js:31:24)
    at async Response.status (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/core/render-context.js:80:25)
    at async callMiddleware (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/core/middleware/callMiddleware.js:11:10)        
    at async RenderContext.render (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/core/render-context.js:96:22)
Error: Error in getAllRestaurantsByVendor: TypeError: Cannot read properties of undefined (reading 'findMany')
    at Module.getAllRestaurantsByVendor (projectfolder/src/modules/restaurant/db.ts:33:11)
    at Module.GET (projectfolder/src/pages/api/restaurant/index.ts:17:48)
    at eval (projectfolder/src/pages/restaurant/index.astro:27:46)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async callComponentAsTemplateResultOrResponse (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/runtime/server/render/astro/render.js:87:25)
    at async renderToAsyncIterable (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/runtime/server/render/astro/render.js:115:26)
    at async renderPage (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/runtime/server/render/page.js:31:24)
    at async Response.status (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/core/render-context.js:80:25)
    at async callMiddleware (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/core/middleware/callMiddleware.js:11:10)        
    at async RenderContext.render (file:///projectfolder/node_modules/.pnpm/astro@4.4.15_typescript@5.4.2/node_modules/astro/dist/core/render-context.js:96:22)

I'm trying to use findMany in @modules/restaurant/db.ts which is used in a GET request at /api/restaurant

import db from "@lib/db";
try {
  const result = await db.query.Restaurants.findMany({
    where: eq(restaurants.vendor_id, vendor_id),
    columns: {
      id: true,
    }
  })

  return result;
} catch (error) {
  throw new Error("Error in getAllRestaurantsByVendor: " + error);
}

this is my schema at @lib/schema.ts

import {
  timestamp,
  pgTable,
  text,
  integer,
  boolean,
  pgEnum,
  jsonb,
} from "drizzle-orm/pg-core";
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
import { serial } from "drizzle-orm/pg-core";
import { roles, subscription, paymentType } from "@/constant/db";
import type { constants } from "@/constant/db";

export const UserRoleEnum = pgEnum(
  "UserRole",
  roles.map((r: constants) => r.value) as [string, ...string[]]
);

export const SubscriptionEnum = pgEnum(
  "Subscription",
  subscription.map((s: constants) => s.value) as [string, ...string[]]
);

export const PaymentTypeEnum = pgEnum(
  "PaymentType",
  paymentType.map((p: constants) => p.value) as [string, ...string[]]
);

export const users = pgTable("Users", {
  id: text("ID").notNull().primaryKey(), // firebase auth uid
  name: text("Name").notNull(),
  email: text("Email").notNull().unique(),
  role: UserRoleEnum("Role").default("customer"),
  registration_date: timestamp("Registration_Date", {
    mode: "date",
  }).defaultNow(),
});

export const vendors = pgTable("Vendors", {
  id: serial("ID").notNull().primaryKey(),
  user_id: text("User_ID")
    .notNull()
    .references(() => users.id, { onDelete: "cascade" }),
  is_approved: boolean("Is_Approved").default(false),
  subscription_type: SubscriptionEnum("Subscription_Type")
    .default("Free Trial")
    .notNull(),
});

export const restaurants = pgTable("Restaurants", {
  id: serial("ID").notNull().primaryKey(),
  vendor_id: integer("Vendor_ID")
    .notNull()
    .references(() => vendors.id, { onDelete: "cascade" }),
  // order_phases : [{name: "lunch", from: "10:00", to: "09:00", delivery_time: "1 PM - 2 PM", }, {name: "dinner", from: "10:00", to: "10:00", delivery_time: "7 PM - 8 PM", }, ],
  order_phases: jsonb("Order_Phases").notNull(),
  delivery_location: jsonb("Delivery_Location").notNull(),
});

export type MyDatabase = NodePgDatabase<{
  Users: typeof users;
  Customers: typeof customers;
  Vendors: typeof vendors;
  Payments: typeof payments;
  Payments_DuitNow: typeof payments_duitnow;
  Payments_CreditCard: typeof payments_creditcard;
  Payments_Bank: typeof payments_bank;
  Vouchers: typeof vouchers;
  Comments: typeof comments;
  Restaurants: typeof restaurants;
  Menus: typeof menus;
  Receipts: typeof receipts;
  Carts: typeof carts;
  Refunds: typeof refunds;
}>;

this is my relation.ts at @lib/relation.ts

import { users, vendors, restaurants } from "@/lib/schema";

import { relations } from "drizzle-orm";

export const usersRelations = relations(users, ({ one, many }) => ({
  // a user can be  a vendor
  vendor: one(vendors, {
    fields: [users.id],
    references: [vendors.user_id],
  }),
}));

export const vendorsRelations = relations(vendors, ({ one, many }) => ({
  // a vendor is a user
  user: one(users, {
    fields: [vendors.user_id],
    references: [users.id],
  }),

  // a vendor can have multiple restaurants
  restaurants: many(restaurants),
}));

export const restaurantsRelations = relations(restaurants, ({ one, many }) => ({
  // a restaurant is owned by a vendor
  vendor: one(vendors, {
    fields: [restaurants.vendor_id],
    references: [vendors.id],
  }),
}));

this is my db.ts at @lib/db.ts

import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import type { MyDatabase } from "@/lib/schema";
import * as schema from "@/lib/schema";

export const connectionString = process.env.SECRET_SUPABASE_URL || import.meta.env.SECRET_SUPABASE_URL;

if (!connectionString) {
  throw new Error("DATABASE_URL is missing");
}

declare global {
  var db: MyDatabase | undefined;
}

let db: MyDatabase;

if (!global.db) {
  // Disable prefetch as it is not supported for "Transaction" pool mode
  const client = postgres(connectionString, { prepare: false });

  global.db = drizzle(client, { logger: true, schema });
}

db = global.db;

export default db;

Expected behavior

Even though I can just use db.select to achieve what I wanted, but I wonder if I'm using the findMany correctly to achieve the same thing (get all the restaurant ids of that vendor) and is my setup correct? Also, I'm not getting any autocomplete when inside the with curly braces as I saw on youtube that it's supposed to suggest the table names.

Environment & setup

No response

haocloo commented 3 months ago

I just need to make sure the tablename in query.tablename matches the tablename in export const tablename = pgTable