vercel / storage

Vercel Postgres, KV, Blob, and Edge Config
https://vercel.com/storage
Apache License 2.0
517 stars 58 forks source link

VercelPostgresError: VercelPostgresError - 'missing_connection_string' - parameter for connectionString #708

Open AJR07 opened 5 months ago

AJR07 commented 5 months ago

Issue

Currently, in @vercel/postgres/src/create-pool.ts, it checks for the connection string using

const connectionString = config?.connectionString ?? postgresConnectionString('pool');
  1. config?.connectionString would be undefined when called from @vercel/postgres/src/index.ts', as createPool() is called without any parameters, as seen below
export const sql = new Proxy(
  // eslint-disable-next-line @typescript-eslint/no-empty-function -- [@vercel/style-guide@5 migration]
  () => {},
  {
    get(_, prop) {
      if (!pool) {
        pool = createPool();
      }

      // keep an eye on this -- it'll fail on certain cases, like private property access, which can
      // require weird things like binding or calling with an explicit `this` arg.
      // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- [@vercel/style-guide@5 migration]
      const val = Reflect.get(pool, prop);
      if (typeof val === 'function') {
        // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-call -- [@vercel/style-guide@5 migration]
        return val.bind(pool);
      }
      // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- [@vercel/style-guide@5 migration]
      return val;
    },
    apply(_, __, argumentsList) {
      if (!pool) {
        pool = createPool();
      }

      // @ts-expect-error - we're breaking all kinds of rules
      // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- [@vercel/style-guide@5 migration]
      return pool.sql(...argumentsList);
    },
  },
) as unknown as VercelPool &
  (<O extends QueryResultRow>(
    strings: TemplateStringsArray,
    ...values: Primitive[]
  ) => Promise<QueryResult<O>>);

export const db = sql;
  1. postgresConnectionString('pool') returns process.env.POSTGRES_URL;. However, in Vite, process.env cannot be used as it is not exposed. We are told to use import.meta.env.[ENV_NAME] instead, and the environment variable's name has to be prefixed with VITE_, as seen here. While we are theoretically able to expose to process.env through
export default ({ mode }: { mode: string }) => {
    const env = loadEnv(mode, process.cwd(), "");

    return defineConfig({
        ...,
        define: {
            "process.env": env,
        },
    });
};

in vite.config.ts, it doesn't seem to work as of now. What I've observed is that process.env.POSTGRES_URL is undefined when vercel/postgres accesses it, but after the initial paint, it becomes defined. I will have to find a workaround to this.

Tech Stack

This issue is encountered when using Vercel's vercel/postgres with drizzle-orm/vercel-postgres and Vite.

Reproduction of Issue

import { sql } from '@vercel/postgres';
import { drizzle } from 'drizzle-orm/vercel-postgres';

const db = drizzle(sql);

Solution

Edit: I realized that checking for import.meta.env.POSTGRES_URL won't even work because vite restricts environment variables to be named with the prefix of VITE_.

Hence, it would be good to allow us to directly pass the connection string into the connectionPool function directly.