Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: experimental database layer #1351

Merged
merged 14 commits into from
Feb 26, 2024
Merged

feat: experimental database layer #1351

merged 14 commits into from
Feb 26, 2024

Conversation

pi0
Copy link
Member

@pi0 pi0 commented Jun 27, 2023

πŸ”— Linked issue

❓ Type of change

  • πŸ“– Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

πŸ“š Description

This PR adds support for experimental Database support with zero configuration, SQLite and multi-provider support powered by unjs/db0.

It is also possible to integrate this layer with extra ORMS such as drizzle-orm with built-in connectors from db0.

Example usage:*

Enable experimental flag:

export default defineNitroConfig({
  experimental: {
    database: true,
  },
});

For nuxt:

export default defineNuxtConfig({
  nitro: {
    experimental: {
        database: true,
      },
  }
});

Install better-sqlite3:

pnpm i -D better-sqlite3
npm i -D better-sqlite3
yarn add -D better-sqlite3

And then, voila!

export default defineEventHandler(async () => {
  const db = useDatabase();

  // Create users table
  await db.sql`DROP TABLE IF EXISTS users`;
  await db.sql`CREATE TABLE IF NOT EXISTS users ("id" TEXT PRIMARY KEY, "firstName" TEXT, "lastName" TEXT, "email" TEXT)`;

  // Add a new user
  const userId = String(Math.round(Math.random() * 10_000));
  await db.sql`INSERT INTO users VALUES (${userId}, 'John', 'Doe', '')`;

  // Query for users
  const { rows } = await db.sql`SELECT * FROM users WHERE id = ${userId}`;

  return {
    rows,
  };
});

TODO:

  • Add basic test
  • Support configurable connector
  • Opensource DB0
  • Add to the docs

Next steps:

  • Enable useDB without the flag once db0 is stable
  • Built-in Schema and Migration support
  • Auto-detect database connectors (vercel postgres and cloudflare D1)

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@pi0 pi0 mentioned this pull request Jun 27, 2023
7 tasks
@codecov
Copy link

codecov bot commented Jun 27, 2023

Codecov Report

Attention: Patch coverage is 44.44444% with 5 lines in your changes are missing coverage. Please review.

Project coverage is 76.64%. Comparing base (e8fa771) to head (760b4aa).
Report is 149 commits behind head on main.

❗ Current head 760b4aa differs from pull request most recent head bb23a68. Consider uploading reports for the commit bb23a68 to get more accurate results

Files Patch % Lines
src/options.ts 37.50% 5 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #1351       +/-   ##
===========================================
+ Coverage   51.94%   76.64%   +24.69%     
===========================================
  Files         174       70      -104     
  Lines       12035     7171     -4864     
  Branches      913      711      -202     
===========================================
- Hits         6252     5496      -756     
+ Misses       5686     1674     -4012     
+ Partials       97        1       -96     

β˜” View full report in Codecov by Sentry.
πŸ“’ Have feedback on the report? Share it here.

@Hebilicious Hebilicious added enhancement New feature or request database labels Jun 30, 2023 — with Volta.net
@pi0 pi0 mentioned this pull request Oct 5, 2023
@cayter
Copy link

cayter commented Nov 6, 2023

I'm new to how Nitro/Nuxt works but I have 2 questions:

  • In the case of multiple databases, how do we specify which one to use? Would it be better to support key-value or map? For example, this is how the famous web frameworks support multiple databases:

  • Does this take care of persistent DB instance to avoid leaking DB connections between HMRs during local development? This is a workaround we have to enable during local development when working with Prisma/Drizzle ORM in NextJS/Remix.

@pi0
Copy link
Member Author

pi0 commented Nov 6, 2023

In the case of multiple databases, how do we specify which one to use? Would it be better to support key-value or map?

I am thinking of useDatabase(name?) for multiple connections support

Does this take care of persistent DB instance to avoid leaking DB connections between HMRs during local development

Once we migrate to DB0, we can support reconnect support. As you mentioned, HMR is the tricky part because any (runtime) logic will be restarted. Another thing we have in plan, is a HTTTP driver this way we can initialize DBs in the builder namespace and expose it via HTTP (or another RPC channel) to the runtime to handle HMR.

@cayter
Copy link

cayter commented Nov 6, 2023

In the case of multiple databases, how do we specify which one to use? Would it be better to support key-value or map?

I am thinking of useDatabase(name?) for multiple connections support

Does this take care of persistent DB instance to avoid leaking DB connections between HMRs during local development

Once we migrate to DB0, we can support reconnect support. As you mentioned, HMR is the tricky part because any (runtime) logic will be restarted. Another thing we have in plan, is a HTTTP driver this way we can initialize DBs in the builder namespace and expose it via HTTP (or another RPC channel) to the runtime to handle HMR.

Got it, thanks for the quick reply!

@pi0 pi0 mentioned this pull request Nov 20, 2023
@imcm7
Copy link

imcm7 commented Nov 21, 2023

I don't know what is drizzle-orm, people use sequalize, typeorm, prism and mikro-orm.

@husayt
Copy link

husayt commented Nov 21, 2023

would it be possible to use with other orms, notably prisma

@pi0
Copy link
Member Author

pi0 commented Nov 21, 2023

It is on the track. As long as an ORM allow implementing external providers and compatible with SQLite dialects i don't see any reason we couldn't support any of them

(this PR is BTW placeholder actual work is under progress in a currently private repo)

@vinayakkulkarni
Copy link

vinayakkulkarni commented Feb 26, 2024

It is on the track. As long as an ORM allow implementing external providers and compatible with SQLite dialects i don't see any reason we couldn't support any of them

(this PR is BTW placeholder actual work is under progress in a currently private repo)

so basically, instead of using all the code here, i could directly use sql from useDatabase()

does useDatabase enable us to use different db servers? postgres for example? and passing args for db server like i've put in the codebase

//edit: yikes, seems node-postgres is the default client to connect postgres – https://db0.unjs.io/connectors/postgresql
I think we could/should provide ability to use different connectors like lucia does – https://lucia-auth.com/database/postgresql

@pi0 pi0 marked this pull request as ready for review February 26, 2024 20:39
@pi0 pi0 merged commit 693b23b into main Feb 26, 2024
5 checks passed
@pi0 pi0 deleted the feat/db0 branch February 26, 2024 20:57
@pi0 pi0 mentioned this pull request Feb 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
database enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants