330 lines
9.9 KiB
Markdown
330 lines
9.9 KiB
Markdown
---
|
|
name: powersync-js-vue
|
|
description: PowerSync Vue and Nuxt integration — composables, plugin setup, Kysely ORM, and diagnostics panel
|
|
metadata:
|
|
tags: vue, nuxt, composables, useQuery, javascript, typescript, offline-first
|
|
---
|
|
|
|
# PowerSync Vue & Nuxt
|
|
|
|
> **Load this when** building a Vue app or Nuxt app with PowerSync. Always load `powersync-js.md` first.
|
|
|
|
## Table of Contents
|
|
- [Vue](#vue) (Plugin, Composables, Watchers)
|
|
- [Nuxt](#nuxt) (Module, Auto-imports, SSR)
|
|
|
|
Vue-specific integration for the PowerSync JavaScript SDK. Use this reference alongside `references/sdks/powersync-js.md` when building Vue apps or Nuxt apps.
|
|
|
|
| Resource | Description |
|
|
|----------|-------------|
|
|
| [Vue Composables Reference](https://docs.powersync.com/client-sdks/frameworks/vue.md) | Full Vue composables guide, consult for details beyond the inline examples. |
|
|
| [Vue SDK API Reference](https://powersync-ja.github.io/powersync-js/vue-sdk) | Full API reference for `@powersync/vue`, consult only when the inline examples don't cover your case. |
|
|
| [Nuxt Integration Guide](https://docs.powersync.com/client-sdks/frameworks/nuxt.md) | Full Nuxt setup guide. |
|
|
| [Nuxt Module API Reference](https://powersync-ja.github.io/powersync-js/nuxt-sdk) | API reference for `@powersync/nuxt`. |
|
|
|
|
## Vue
|
|
|
|
### 1. Install
|
|
|
|
```bash
|
|
# npm (v7+ installs peer dependencies automatically)
|
|
npm install @powersync/vue@latest
|
|
|
|
# pnpm (must install peer dependencies explicitly)
|
|
pnpm add @powersync/vue@latest @powersync/web@latest @journeyapps/wa-sqlite@latest
|
|
```
|
|
|
|
### 2. Plugin Setup
|
|
|
|
```ts
|
|
import { createPowerSyncPlugin } from '@powersync/vue';
|
|
import { PowerSyncDatabase } from '@powersync/web';
|
|
import { AppSchema } from './AppSchema';
|
|
import { PowerSyncConnector } from './PowerSyncConnector';
|
|
import { createApp } from 'vue';
|
|
import App from './App.vue';
|
|
|
|
const db = new PowerSyncDatabase({
|
|
database: { dbFilename: 'app.db' },
|
|
schema: AppSchema
|
|
});
|
|
|
|
const connector = new PowerSyncConnector();
|
|
db.connect(connector);
|
|
|
|
const app = createApp(App);
|
|
app.use(createPowerSyncPlugin({ database: db }));
|
|
app.mount('#app');
|
|
```
|
|
|
|
### Composables
|
|
|
|
In a standalone Vue app, composables are imported from `@powersync/vue`. In Nuxt, all composables are auto-imported — no import statement is needed.
|
|
|
|
#### `useQuery`
|
|
|
|
Reactive query — re-renders the component automatically when underlying data changes.
|
|
|
|
```ts
|
|
import { useQuery } from '@powersync/vue'; // omit import in Nuxt
|
|
|
|
const { data: lists, isLoading, isFetching, error } = useQuery(
|
|
'SELECT * FROM lists ORDER BY created_at DESC'
|
|
);
|
|
```
|
|
|
|
With parameters (parameters are reactive — can be a `ref` or `computed`):
|
|
|
|
```ts
|
|
const { data: todos } = useQuery(
|
|
'SELECT * FROM todos WHERE list_id = ?',
|
|
[listId]
|
|
);
|
|
```
|
|
|
|
Return shape: `{ data: Ref<RowType[]>, isLoading: Ref<boolean>, isFetching: Ref<boolean>, error: Ref<Error | undefined> }`.
|
|
|
|
For advanced watch query features including incremental updates and differential results, see [Live Queries / Watch Queries](https://docs.powersync.com/client-sdks/watch-queries.md).
|
|
|
|
#### `useStatus`
|
|
|
|
Reactive connectivity status. Same shape as the React `useStatus` hook — see `references/sdks/powersync-js.md` for the full status field reference.
|
|
|
|
```ts
|
|
import { useStatus } from '@powersync/vue'; // omit import in Nuxt
|
|
|
|
const status = useStatus();
|
|
// status.connected, status.hasSynced, status.lastSyncedAt, etc.
|
|
```
|
|
|
|
#### `usePowerSync`
|
|
|
|
Access the `PowerSyncDatabase` instance directly for imperative operations.
|
|
|
|
```ts
|
|
import { usePowerSync } from '@powersync/vue'; // omit import in Nuxt
|
|
import { v4 as uuid } from 'uuid';
|
|
|
|
const powersync = usePowerSync();
|
|
|
|
await powersync.value.execute(
|
|
'INSERT INTO lists (id, created_at, name, owner_id) VALUES (?, ?, ?, ?)',
|
|
[uuid(), new Date().toISOString(), 'My List', currentUserId]
|
|
);
|
|
```
|
|
|
|
`usePowerSync()` returns a `Ref<AbstractPowerSyncDatabase>` — access the database via `.value`.
|
|
|
|
### Setup Context Requirement
|
|
|
|
`usePowerSync`, `useQuery`, and `useStatus` all rely on Vue's `inject()` internally and must be called at the top level of a `<script setup>` block (or the synchronous `setup()` function). They must not be called inside nested functions, async functions, event handlers, or lifecycle hooks.
|
|
|
|
```vue
|
|
<script setup>
|
|
import { usePowerSync } from '@powersync/vue';
|
|
|
|
// ✅ Correct — called at the top level of setup
|
|
const powerSync = usePowerSync();
|
|
|
|
const handleClick = async () => {
|
|
// ✅ Use the ref returned from the top-level call
|
|
const result = await powerSync.value.getAll('SELECT * FROM lists');
|
|
console.log(result);
|
|
};
|
|
|
|
// ❌ Wrong — usePowerSync() called inside a nested function
|
|
const handleClickBad = async () => {
|
|
const result = await usePowerSync().value.getAll('SELECT * FROM lists');
|
|
};
|
|
</script>
|
|
```
|
|
|
|
Calling these composables outside of a setup context throws an error. If you need to access the PowerSync database outside a component (e.g. in a store or utility module), export the database instance directly instead of using the composable.
|
|
|
|
### Example Component
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
import { usePowerSync, useQuery, useStatus } from '@powersync/vue';
|
|
|
|
const powersync = usePowerSync();
|
|
const { data: lists, isLoading } = useQuery('SELECT * FROM lists ORDER BY created_at DESC');
|
|
const status = useStatus();
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<p>Status: {{ status.connected ? 'Connected' : 'Offline' }}</p>
|
|
<p v-if="isLoading">Loading...</p>
|
|
<ul v-else>
|
|
<li v-for="list in lists" :key="list.id">{{ list.name }}</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
---
|
|
|
|
## Nuxt
|
|
|
|
> Alpha: `@powersync/nuxt` is currently in Alpha. APIs and behavior may change.
|
|
|
|
`@powersync/nuxt` is a Nuxt module that wraps `@powersync/vue` and re-exports all its composables. It also adds a Nuxt Devtools integration with a PowerSync diagnostics panel.
|
|
|
|
PowerSync is tailored for client-side applications. Nuxt evaluates plugins server-side unless you use the `.client.ts` suffix. The PowerSync Web SDK requires browser APIs not available in Node.js — it performs no-ops in Node.js rather than throwing errors, but no data is available during SSR. Always create your PowerSync plugin as `plugins/powersync.client.ts`.
|
|
|
|
### 1. Install
|
|
|
|
```bash
|
|
# npm (v7+ installs peer dependencies automatically)
|
|
npm install @powersync/nuxt@latest
|
|
|
|
# pnpm (must install peer dependencies explicitly)
|
|
pnpm add @powersync/nuxt@latest @powersync/vue@latest @powersync/web@latest
|
|
```
|
|
|
|
### 2. `nuxt.config.ts`
|
|
|
|
Add `@powersync/nuxt` to the `modules` array and include the required Vite configuration:
|
|
|
|
```typescript
|
|
export default defineNuxtConfig({
|
|
modules: ['@powersync/nuxt'],
|
|
vite: {
|
|
optimizeDeps: {
|
|
exclude: ['@powersync/web']
|
|
},
|
|
worker: {
|
|
format: 'es'
|
|
}
|
|
}
|
|
});
|
|
```
|
|
|
|
### 3. Create the Plugin
|
|
|
|
Create `plugins/powersync.client.ts`. The `.client.ts` suffix ensures this only runs in the browser.
|
|
|
|
```typescript
|
|
import { NuxtPowerSyncDatabase, createPowerSyncPlugin } from '@powersync/nuxt';
|
|
import { AppSchema } from '~/powersync/AppSchema';
|
|
import { PowerSyncConnector } from '~/powersync/PowerSyncConnector';
|
|
|
|
export default defineNuxtPlugin({
|
|
async setup(nuxtApp) {
|
|
const db = new NuxtPowerSyncDatabase({
|
|
database: {
|
|
dbFilename: 'my-app.sqlite'
|
|
},
|
|
schema: AppSchema
|
|
});
|
|
|
|
const connector = new PowerSyncConnector();
|
|
|
|
await db.init();
|
|
await db.connect(connector);
|
|
|
|
const plugin = createPowerSyncPlugin({ database: db });
|
|
nuxtApp.vueApp.use(plugin);
|
|
}
|
|
});
|
|
```
|
|
|
|
### Using Composables
|
|
|
|
All `@powersync/vue` composables (`usePowerSync`, `useQuery`, `useStatus`) are auto-imported in Nuxt — no import statement is needed in components or composables.
|
|
|
|
```vue
|
|
<script setup lang="ts">
|
|
// No imports needed — composables are auto-imported by @powersync/nuxt
|
|
|
|
const powersync = usePowerSync();
|
|
const { data: lists, isLoading } = useQuery('SELECT * FROM lists ORDER BY created_at DESC');
|
|
const status = useStatus();
|
|
</script>
|
|
```
|
|
|
|
The same [setup context requirement](#setup-context-requirement) as standalone Vue applies — call composables at the top level of `<script setup>`, not inside nested or async functions.
|
|
|
|
### Kysely ORM (Optional)
|
|
|
|
The module optionally exposes a `usePowerSyncKysely()` composable for type-safe query building.
|
|
|
|
Install the driver:
|
|
|
|
```bash
|
|
npm install @powersync/kysely-driver@latest
|
|
```
|
|
|
|
Enable it in `nuxt.config.ts`:
|
|
|
|
```typescript
|
|
export default defineNuxtConfig({
|
|
modules: ['@powersync/nuxt'],
|
|
powersync: {
|
|
kysely: true
|
|
},
|
|
vite: {
|
|
optimizeDeps: {
|
|
exclude: ['@powersync/web']
|
|
},
|
|
worker: {
|
|
format: 'es'
|
|
}
|
|
}
|
|
});
|
|
```
|
|
|
|
Use in components — `usePowerSyncKysely` is auto-imported. Import only your schema's `Database` type for full type safety:
|
|
|
|
```typescript
|
|
import { type Database } from '~/powersync/AppSchema';
|
|
|
|
const db = usePowerSyncKysely<Database>();
|
|
|
|
const lists = await db.selectFrom('lists').selectAll().execute();
|
|
```
|
|
|
|
### Diagnostics Panel
|
|
|
|
`@powersync/nuxt` includes a PowerSync diagnostics panel that shows sync status, local data, bucket contents, config, and logs. Must be explicitly enabled.
|
|
|
|
Enable in `nuxt.config.ts`:
|
|
|
|
```typescript
|
|
export default defineNuxtConfig({
|
|
modules: ['@powersync/nuxt'],
|
|
powersync: {
|
|
useDiagnostics: true
|
|
},
|
|
vite: {
|
|
optimizeDeps: {
|
|
exclude: ['@powersync/web']
|
|
},
|
|
worker: {
|
|
format: 'es'
|
|
}
|
|
}
|
|
});
|
|
```
|
|
|
|
When `useDiagnostics: true` is set, `NuxtPowerSyncDatabase` automatically extends the schema with the diagnostics schema, sets up recording and logging, and stores the connector internally. No changes to the plugin file are needed.
|
|
|
|
Access the inspector:
|
|
- Nuxt Devtools: open browser Devtools and look for the PowerSync tab
|
|
- Direct URL: navigate to `http://localhost:3000/__powersync-inspector`
|
|
|
|
### Known Issues
|
|
|
|
#### Tailwind CSS conflict
|
|
|
|
PowerSync Inspector uses `unocss` as a transitive dependency, which conflicts with Tailwind CSS. If you use Tailwind, add the following to `nuxt.config.ts`:
|
|
|
|
```typescript
|
|
export default defineNuxtConfig({
|
|
unocss: {
|
|
autoImport: false
|
|
}
|
|
});
|
|
```
|