neondatabase / serverless

Connect to Neon PostgreSQL from serverless/worker/edge functions
https://www.npmjs.com/package/@neondatabase/serverless
MIT License
343 stars 13 forks source link

Any ORM or Query builder example? #6

Closed shinebayar-g closed 1 year ago

shinebayar-g commented 1 year ago

Hi, thanks for the great package. It really solves the issue with Cloudflare workers. Is there any compatible ORM or Query builder type of library that works with neon serverless? Just tried Prisma looks like it doesn't work.

jawj commented 1 year ago

Thanks, that's a great question.

Yes, I believe Prisma uses its own driver to connect to the database, so it's not expected to work with this package.

It's an item on my TODO list to investigate (and document in the README) which libraries can be used on top of @neondatabase/serverless.

In the meantime, I'm pretty confident Zapatos (https://jawj.github.io/zapatos/) will be one of them (because it's my library). You may need to npm install @types/pg alongside Zapatos and this package, since Zapatos imports those types. If you do try Zapatos and have any trouble with it, please file an issue in the Zapatos repo and I'll take a look.

janpio commented 1 year ago

We at Prisma are tracking the request for support for this at https://github.com/prisma/prisma/issues/19409

jawj commented 1 year ago

Just to note that kysely also works — e.g. https://github.com/jawj/vercel-edge-minimal-test/blob/main/api/kysely.ts. And to use kysely-codegen, just add pg as a devDependency.

shinebayar-g commented 1 year ago

Oh nice, now is this possible? import { Pool } from '@neondatabase/serverless'; I thought this was not possible, remember it was mentioned somewhere. 🤔

jawj commented 1 year ago

It is possible. I'm not sure if it's efficient, though.

shinebayar-g commented 1 year ago

I see. Have you looked at Kysely's Deno and Browser example? Where do you put database credentials in this example?

const db = new Kysely<Database>({
  dialect: {
    createAdapter() {
      return new PostgresAdapter()
    },
    createDriver() {
      // You need a driver to be able to execute queries. In this example
      // we use the dummy driver that never does anything.
      return new DummyDriver()
    },
    createIntrospector(db: Kysely<unknown>) {
      return new PostgresIntrospector(db)
    },
    createQueryCompiler() {
      return new PostgresQueryCompiler()
    },
  },
})

Would you recommend ^ or import { Pool } from '@neondatabase/serverless'; approach to the users? :)

jawj commented 1 year ago

I'll need to investigate this further. It would be nice if we can stick to the simple Pool approach, so I need to see if this is just as quick as using Client directly — and if not, then see if I can make it so.

shinebayar-g commented 1 year ago

Yeah that makes sense. That way maybe we could provide out of box experience for other libraries as well.

jawj commented 1 year ago

OK, I found the problem with Pool — a Client created by the Pool wasn't getting its outgoing messages pipelined in the same way as a Client created directly, which made Pool connections slower. That's fixed now (npm package version 0.2.3), so now there's no reason not to use kysely with Pool in the normal way, as above.

mingfang commented 1 year ago

https://github.com/Suor/sql-bricks-postgres works great for me.

Also I find using Client can be problematic whenever the web socket gets disconnected. But using Pool solves the problem because it auto reconnects.

jokull commented 1 year ago

Using prisma-kysely and kysely-neon.

pyrossh commented 1 year ago

Drizzle orm example,

import { drizzle } from 'drizzle-orm/neon-serverless';
import { Pool } from '@neondatabase/serverless';
import { highlight } from 'sql-highlight';
import { eq, asc } from 'drizzle-orm';
import { boolean, date, pgTable, serial, text } from 'drizzle-orm/pg-core';

const todos = pgTable('todos', {
  id: serial('id').primaryKey(),
  text: text('text').notNull(),
  completed: boolean('completed').notNull(),
  createdAt: date('createdAt').notNull(),
  updatedAt: date('updatedAt'),
});

export const pool = new Pool({ connectionString: process.env.PG_CONN_URL });
const db = drizzle(pool, {
  logger: {
    logQuery: (query, params) => {
      const sqlString = params.reduce((acc, v, i) => acc.replaceAll("$" + (i + 1), v), query);
      console.log(highlight(sqlString));
    }
  }
});

const main = async () => {
  const todos =  await db.select().from(todos).orderBy(asc(todos.id));
  console.log(todos);
}

main();