From 446c2dfe7f62f2c80520f0c7ea7db454c875b54f Mon Sep 17 00:00:00 2001 From: Stefanos Mousafeiris Date: Wed, 14 Aug 2024 19:22:18 +0300 Subject: [PATCH] chore: Add vue docs (#197) * Add both static and typed injection tools to vue * Add Vue docs * Fix dead links * Fix style issues * Fix vue docs with type * Fix vue docs nits --- .changeset/shy-coins-give.md | 5 + docs/.vitepress/config.mts | 5 +- docs/docs/framework-hooks/vue.md | 149 ++++++++++++++++++ .../pglite-react/test/provider.test-d.tsx | 11 +- packages/pglite-vue/README.md | 9 +- packages/pglite-vue/package.json | 2 +- .../pglite-vue/src/dependency-injection.ts | 15 +- packages/pglite-vue/src/hooks.ts | 10 +- packages/pglite-vue/test/injection.test-d.ts | 11 +- 9 files changed, 189 insertions(+), 28 deletions(-) create mode 100644 .changeset/shy-coins-give.md create mode 100644 docs/docs/framework-hooks/vue.md diff --git a/.changeset/shy-coins-give.md b/.changeset/shy-coins-give.md new file mode 100644 index 00000000..ba3adbf4 --- /dev/null +++ b/.changeset/shy-coins-give.md @@ -0,0 +1,5 @@ +--- +'@electric-sql/pglite-vue': patch +--- + +Include both utility for typed injection and static injectors. diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 99c85c66..0644dde0 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -103,7 +103,10 @@ export default defineConfig({ link: '/react', base: '/docs/framework-hooks', collapsed: true, - items: [{ text: 'React', link: '/react' }], + items: [ + { text: 'React', link: '/react' }, + { text: 'Vue', link: '/vue' }, + ], }, { text: 'Multi-tab Worker', link: '/docs/multi-tab-worker' }, { text: 'REPL Component', link: '/docs/repl' }, diff --git a/docs/docs/framework-hooks/vue.md b/docs/docs/framework-hooks/vue.md new file mode 100644 index 00000000..b23e28e1 --- /dev/null +++ b/docs/docs/framework-hooks/vue.md @@ -0,0 +1,149 @@ +--- +outline: [2, 3] +--- + +# Vue + +To aid integration of PGlite into a [Vue](https://vuejs.org/) project we have a `providePGlite` with a corresponding `injectPGlite` and hooks for the [live query](../live-queries.md) plugin. + +### providePGlite + +The `providePGlite` API, which follows the [Vue provide / inject pattern](https://vuejs.org/guide/components/provide-inject), enables you to initiate a PGlite database and pass it to all child components for use with the corresponding [`injectPGlite`](#injectpglite) method, as well as with the [`useLiveQuery`](#uselivequery) and [`useLiveIncrementalQuery`](#useliveincrementalquery) hooks. + +To use it, pass a PGlite instance as the `db` property. + +```vue + +// ... +``` + +### injectPGlite + +You can retrieve the provided PGlite instance using `injectPGlite` and then query it from within your components. + +```vue + + + +``` + +### makePGliteDependencyInjector + +The `makePGliteDependencyInjector` function returns typed versions of `providePGlite` and `injectPGlite`, which enables you to provide a PGlite instance with all added extensions and retain then namespaces and types added to it. + +```ts +import { PGlite, PGliteInterfaceExtensions } from '@electric-sql/pglite' +import { live } from '@electric-sql/pglite/live' +import { vector } from '@electric-sql/pglite/vector' +import { makePGliteDependencyInjector } from '@electric-sql/pglite-vue' + +const { providePGlite, injectPGlite } = makePGliteDependencyInjector< + PGlite & + PGliteInterfaceExtensions<{ + live: typeof live + vector: typeof vector + }> +>() + +export { providePGlite, injectPGlite } +``` + +### useLiveQuery + +The `useLiveQuery` hook enables you to reactively receive updates to the results of a live query change. It wraps the [`.live.query()`](../live-queries.md#livequery) API. + +It has the interface: + +```ts +function useLiveQuery( + query: string | WatchSource, + params?: QueryParams | WatchSource, +): LiveQueryResults +``` + +And its arguments, which can also be [watch sources](https://vuejs.org/guide/essentials/watchers.html#watch-source-types) that will trigger a re-run, are: + +1. the SQL query +2. optional parameters for the query + +```vue + + + +``` + +### useLiveIncrementalQuery + +The `useLiveIncrementalQuery` hook enables you to reactively receive updates whenever the results of a live query change. It wraps the [`.live.incrementalQuery()`](../live-queries.md#liveincrementalquery) API, which provides a way to efficiently diff the query results in Postgres. + +It has the interface: + +```ts +export function useLiveIncrementalQuery( + query: string | WatchSource, + params: QueryParams | WatchSource, + key: string | WatchSource, +): LiveQueryResults +``` + +And its arguments, which can also be [watch sources](https://vuejs.org/guide/essentials/watchers.html#watch-source-types) that will trigger a re-run, are: + +1. the SQL query +2. optional parameters for the query +3. the name of the column to key the diff algorithm on + +```vue + + + +``` diff --git a/packages/pglite-react/test/provider.test-d.tsx b/packages/pglite-react/test/provider.test-d.tsx index 6cbe9f67..5f56cd87 100644 --- a/packages/pglite-react/test/provider.test-d.tsx +++ b/packages/pglite-react/test/provider.test-d.tsx @@ -1,5 +1,5 @@ import { describe, it, expectTypeOf } from 'vitest' -import { PGlite } from '@electric-sql/pglite' +import { PGlite, PGliteInterfaceExtensions } from '@electric-sql/pglite' import { live } from '@electric-sql/pglite/live' import { vector } from '@electric-sql/pglite/vector' import { makePGliteProvider } from '../src/provider.js' @@ -18,8 +18,13 @@ describe('provider', () => { }, }) - const { PGliteProvider, usePGlite } = - makePGliteProvider() + const { PGliteProvider, usePGlite } = makePGliteProvider< + PGlite & + PGliteInterfaceExtensions<{ + live: typeof live + vector: typeof vector + }> + >() // @ts-expect-error cannot pass db with just live extension ;() => diff --git a/packages/pglite-vue/README.md b/packages/pglite-vue/README.md index c206a86c..4d690312 100644 --- a/packages/pglite-vue/README.md +++ b/packages/pglite-vue/README.md @@ -1,6 +1,6 @@ -# PGlite Vue.js Bindings +# PGlite Vue Bindings -This package implements Vue.js hooks for [PGLite](https://pglite.dev/) on top of the [live query plugin](https://pglite.dev/docs/live-queries). Full documentation is available at [pglite.dev/docs/framework-hooks](https://pglite.dev/docs/framework-hooks#react). +This package implements Vue hooks for [PGLite](https://pglite.dev/) on top of the [live query plugin](https://pglite.dev/docs/live-queries). Full documentation is available at [pglite.dev/docs/framework-hooks](https://pglite.dev/docs/framework-hooks#react). To install: @@ -10,7 +10,8 @@ npm install @electric-sql/pglite-vue The hooks this package provides are: -- [proidePGlite](https://pglite.dev/docs/framework-hooks#providepglite): Provide a PGlite instance to all child components. -- [injectPGlite](https://pglite.dev/docs/framework-hooks#injectpglite): Retrieve the provided PGlite instance. +- [providePGlite](https://pglite.dev/docs/framework-hook/vuevye#providepglite): Provide a PGlite instance to all child components. +- [injectPGlite](https://pglite.dev/docs/framework-hooks/vue#injectpglite): Retrieve the provided PGlite instance. +- [makePGliteDependencyInjector](https://pglite.dev/docs/framework-hooks/vue#makepglitedependencyinjector): Utility to create a typed version of `providePGlite` and `injectPGlite`. - [useLiveQuery](https://pglite.dev/docs/framework-hooks#uselivequery): Reactively receive results of a live query change - [useLiveIncrementalQuery](https://pglite.dev/docs/framework-hooks#useliveincrementalquery): Reactively receive results of a live query change by offloading the diff to PGlite diff --git a/packages/pglite-vue/package.json b/packages/pglite-vue/package.json index 6e0fe0c5..6210e752 100644 --- a/packages/pglite-vue/package.json +++ b/packages/pglite-vue/package.json @@ -1,7 +1,7 @@ { "name": "@electric-sql/pglite-vue", "version": "0.2.0", - "description": "Vue.js hooks for using PGlite", + "description": "Vue hooks for using PGlite", "type": "module", "private": false, "publishConfig": { diff --git a/packages/pglite-vue/src/dependency-injection.ts b/packages/pglite-vue/src/dependency-injection.ts index 2a468b08..e4ea3c39 100644 --- a/packages/pglite-vue/src/dependency-injection.ts +++ b/packages/pglite-vue/src/dependency-injection.ts @@ -25,7 +25,7 @@ const PGliteKey = Symbol('PGliteProvider') * @returns An object with two functions: `providePGlite` and `injectPGlite`. * */ -export function makePGliteDependencyInjector< +function makePGliteDependencyInjector< T extends PGliteWithLive, >(): PGliteDependencyInjection { const providePGlite = (db: Ref | (T | undefined)): void => @@ -42,14 +42,7 @@ export function makePGliteDependencyInjector< } } -/** - * This "static" injector is used internally by our reactive methods - * to get access to the provided PGlite instance. - * It loses information about the extensions present on PGlite, - * but we only need the `live` extension information for our methods. - * However, users preferably don't lose extension type information, - * therefore, they can use {@link makePGliteDependencyInjector}. - */ -const { injectPGlite: injectPGliteUntyped } = makePGliteDependencyInjector() +const { injectPGlite, providePGlite } = + makePGliteDependencyInjector() -export { injectPGliteUntyped } +export { makePGliteDependencyInjector, injectPGlite, providePGlite } diff --git a/packages/pglite-vue/src/hooks.ts b/packages/pglite-vue/src/hooks.ts index e30c8b7a..6233adf7 100644 --- a/packages/pglite-vue/src/hooks.ts +++ b/packages/pglite-vue/src/hooks.ts @@ -12,7 +12,7 @@ import { isRef, } from 'vue-demi' import { Results } from '@electric-sql/pglite' -import { injectPGliteUntyped } from './dependency-injection' +import { injectPGlite } from './dependency-injection' type UnsubscribeFn = () => Promise type QueryParams = unknown[] | undefined | null @@ -25,8 +25,8 @@ function useLiveQueryImpl( query: string | WatchSource, params?: QueryParams | WatchSource, key?: string | WatchSource, -): LiveQueryResults | undefined { - const db = injectPGliteUntyped()! +): LiveQueryResults { + const db = injectPGlite()! const liveUpdate = shallowReactive< | Omit, 'affectedRows'> @@ -86,7 +86,7 @@ function useLiveQueryImpl( export function useLiveQuery( query: string | WatchSource, params?: QueryParams | WatchSource, -): LiveQueryResults | undefined { +): LiveQueryResults { return useLiveQueryImpl(query, params) } @@ -94,6 +94,6 @@ export function useLiveIncrementalQuery( query: string | WatchSource, params: QueryParams | WatchSource, key: string | WatchSource, -): LiveQueryResults | undefined { +): LiveQueryResults { return useLiveQueryImpl(query, params, key) } diff --git a/packages/pglite-vue/test/injection.test-d.ts b/packages/pglite-vue/test/injection.test-d.ts index 7e78a4f3..472908a2 100644 --- a/packages/pglite-vue/test/injection.test-d.ts +++ b/packages/pglite-vue/test/injection.test-d.ts @@ -2,7 +2,7 @@ * @vitest-environment node */ import { describe, it, expectTypeOf } from 'vitest' -import { PGlite } from '@electric-sql/pglite' +import { PGlite, PGliteInterfaceExtensions } from '@electric-sql/pglite' import { live } from '@electric-sql/pglite/live' import { makePGliteDependencyInjector } from '../src' import { vector } from '@electric-sql/pglite/vector' @@ -21,8 +21,13 @@ describe('dependency injection', () => { vector, }, }) - const { providePGlite, injectPGlite } = - makePGliteDependencyInjector() + const { providePGlite, injectPGlite } = makePGliteDependencyInjector< + PGlite & + PGliteInterfaceExtensions<{ + live: typeof live + vector: typeof vector + }> + >() // @ts-expect-error name is a string providePGlite(dbLive)