https://github.com/sandros94/nuxt-pglite
A Nuxt module aimed to simplify the use of PGlite.
https://github.com/sandros94/nuxt-pglite
modules nuxt pglite postgres
Last synced: 6 months ago
JSON representation
A Nuxt module aimed to simplify the use of PGlite.
- Host: GitHub
- URL: https://github.com/sandros94/nuxt-pglite
- Owner: sandros94
- License: mit
- Created: 2024-08-29T07:31:13.000Z (about 1 year ago)
- Default Branch: main
- Last Pushed: 2025-02-04T17:22:51.000Z (8 months ago)
- Last Synced: 2025-03-20T22:05:01.332Z (7 months ago)
- Topics: modules, nuxt, pglite, postgres
- Language: TypeScript
- Homepage: https://www.npmjs.com/package/nuxt-pglite
- Size: 581 KB
- Stars: 19
- Watchers: 1
- Forks: 0
- Open Issues: 4
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# Nuxt PGlite
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![License][license-src]][license-href]
[![Nuxt][nuxt-src]][nuxt-href]A Nuxt module aimed to simplify the use of [PGlite](https://pglite.dev).
> PGlite, an Embeddable Postgres
> Run a full Postgres database locally in WASM with reactivity and live sync.- [✨ Release Notes](/CHANGELOG.md)
> [!WARNING]
> No docs are available (although planned), please refer to the [playground code](/playground).## Features
- ⚡️ Server-side `usePGlite`, running in your Node or Bun server.
- 🧑💻 Client-side `usePGlite`, running inside Web Workers.
- 🪢 Client-side `useLiveQuery` and `useLiveIncrementalQuery` to subscribe to live changes.## Quick Setup
Install the module to your Nuxt application with one command:
```bash
npx nuxi module add nuxt-pglite
```That's it! You can now use Nuxt PGlite in your Nuxt app ✨
### Storage
You can configure where to store data in your `nuxt.config.ts`. Server-side storage accepts relative baths:
```ts
export default defineNuxtConfig({
modules: ['nuxt-pglite'],pglite: {
client: {
options: {
dataDir: 'idb://nuxt-pglite',
},
},
server: {
options: {
dataDir: './database/pglite', // will use `~~/server/database/pglite`
},
},
},
})
```For supported filesystem please refer to the [official documentation](https://pglite.dev/docs/filesystems).
### Extensions
Extensions are automatically configured with full type support and can be added via `nuxt.config.ts`:
```ts
export default defineNuxtConfig({
modules: ['nuxt-pglite'],pglite: {
client: {
extensions: ['live', 'electricSync'],
},
},
})
```For a full list of available extensions please refer to [the official docs](https://pglite.dev/extensions). If a new extension is missing feel free to open up a new PR by adding it to [this file](/src/templates.ts#L62-L87). I do plan to support only official and contrib extensions.
> [!WARNING]
> Auto configuration for server-side extensions will be supported once Nuxt `v3.15` gets released. See below how to use hooks to add extensions server-side.## Live Queries
With Live Queries we can subscrive to events happening in the database and reactively update the user interface. This becomes particularly usefuly client-side thanks to Web Workers, allowing us to keep content in sync even when the user opens up multiple tabs.
To get started simply add `live` extension to your `nuxt.config.ts`:
```ts
export default defineNuxtConfig({
modules: ['nuxt-pglite'],pglite: {
client: {
extensions: [
// ...
'live',
],
},
},
})
```This will enable auto-import for `useLiveQuery` and `useLiveIncrementalQuery`. The quick implementation would be:
```vue
const maxNumber = ref(100)
const items = useLiveQuery.sql`
SELECT *
FROM my_table
WHERE number <= ${maxNumber.value}
ORDER BY number;
````
Live queries are currently a port of the upstream implementation, you can read more [here](https://pglite.dev/docs/framework-hooks/vue#uselivequery).
## Hooks
We can use hooks to customize or extend PGlite at runtime. This becomes particularly useful in conjunction with [`RLS`](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) or adding custom extensions server-side.
### RLS
PGlite supports RLS out of the box, but being a single-user/single-connection database it is more frequent to be used only client side. Lets take in example a basic implementation with `nuxt-auth-utils`. We'll need to create a client-only Nuxt plugin `/plugins/rls.client.ts`:
```ts
export default defineNuxtPlugin((nuxtApp) => {
const { user } = useUserSession()if (user) {
nuxtApp.hook('pglite:config', (options) => {
options.username = user.id
})
}
})
```This, in combination with [`Sync`](https://pglite.dev/docs/sync), will make us able to create an offline-first application with the ability for the users to save their data in a centralized postgres instance.
### Customizing extensions
We can also use hooks to pass custom options to extensions like [`Sync`](https://pglite.dev/docs/sync) as well as improve typing for the whole project.
In the following example we are creating a `/server/plugins/extend-pglite.ts` plugin that adds and configure `pgvector` and `Sync`:
```ts
import { vector } from '@electric-sql/pglite/vector'
import { electricSync } from '@electric-sql/pglite-sync'import { pgliteHooks } from '#pglite-utils'
export default defineNitroPlugin(() => {
pgliteHooks.hook('pglite:config', (options) => {
options.extensions = {
vector,
electric: electricSync({
metadataSchema: 'my-electric',
}),
}
})pgliteHooks.hookOnce('pglite', async (pg) => {
await pg.query('CREATE EXTENSION IF NOT EXISTS vector;')
})
})declare module '#pglite-utils' {
interface PGliteServerExtensions {
vector: typeof vector
electric: ReturnType
}
}
```> [!WARNING]
> Until Nuxt `v3.15` gets released this is the only way to add extensions server-side.### Hooking Notes
A few things to consider are that:
- we rely on `nuxtApp` hooks for client-side, while `pgliteHooks` imported from `#pglite-utils` for server-side, hooks available are:
- `pglite:config`: provides access to `PGliteOptions` before initializing a new PGlite instance.
- `pglite`: called on every PGlite execution.
- To improve types when manually adding extensions we use `PGliteClientExtensions` and `PGliteServerExtensions` for client and server respectively.## ORM support
Any ORM that accept a PGlite instance should be supported both server and client side.
### Drizzle
Drizzle integration is as simple as:
```ts
import { drizzle } from 'drizzle-orm/pglite'
import * as schema from '../my-path-to/schema'export function useDB() {
return drizzle(usePGlite(), { schema })
}
```## Contribution
Local development
```bash
# Install dependencies
pnpm install
# Generate type stubs
pnpm run dev:prepare
# Develop with the playground
pnpm run dev
# Build the playground
pnpm run dev:build
# Run ESLint
pnpm run lint
# Run Vitest
pnpm run test
pnpm run test:watch
# Release new version
pnpm run release
```## License
Published under the [MIT](/LICENSE) license.
[npm-version-src]: https://img.shields.io/npm/v/nuxt-pglite/latest.svg?style=flat&colorA=020420&colorB=00DC82
[npm-version-href]: https://npmjs.com/package/nuxt-pglite[npm-downloads-src]: https://img.shields.io/npm/dm/nuxt-pglite.svg?style=flat&colorA=020420&colorB=00DC82
[npm-downloads-href]: https://npmjs.com/package/nuxt-pglite[license-src]: https://img.shields.io/npm/l/nuxt-pglite.svg?style=flat&colorA=020420&colorB=00DC82
[license-href]: https://npmjs.com/package/nuxt-pglite[nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js
[nuxt-href]: https://nuxt.com