Last active
September 23, 2024 15:03
-
-
Save samwightt/d66c8c6affee47115b6b458fe9cb36d1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { | |
| Owner, | |
| type Evolu, | |
| type EvoluSchema, | |
| type QueryResult, | |
| type SyncState, | |
| } from "@evolu/common"; | |
| export * from "@evolu/common"; | |
| export * from "@evolu/common-web"; | |
| import { type SelectQueryBuilder } from "kysely"; | |
| import { type Row } from "@evolu/common"; | |
| import { | |
| ref, | |
| type MaybeRef, | |
| toValue, | |
| watch, | |
| computed, | |
| onUnmounted, | |
| type DeepReadonly, | |
| type Ref, | |
| } from "vue"; | |
| // I add an explicit 'q` function for subqueries. This allows you to define query functions with correct type inference that you can pass to | |
| // `createQuery` later. | |
| type QueryCallback<T extends EvoluSchema> = Parameters< | |
| Evolu<T>["createQuery"] | |
| >[0]; | |
| export type EvoluQueryCreator<T extends EvoluSchema> = Parameters< | |
| QueryCallback<T> | |
| >[0]; | |
| export const createVueApi = <T extends EvoluSchema>(evolu: Evolu<T>) => { | |
| function makeQuery<A, I extends keyof A, R extends Row>( | |
| callback: (db: EvoluQueryCreator<T>) => SelectQueryBuilder<A, I, R> | |
| ): (db: EvoluQueryCreator<T>) => SelectQueryBuilder<A, I, R> { | |
| return callback; | |
| } | |
| function getEvolu(): Evolu<T> { | |
| return inject("evolu", evolu); | |
| } | |
| function provideEvolu(e: Evolu<T>) { | |
| provide("evolu", e); | |
| } | |
| function loadQuery<A, I extends keyof A, R extends Row>( | |
| callback: MaybeRef< | |
| (db: EvoluQueryCreator<T>) => SelectQueryBuilder<A, I, R> | |
| > | |
| ): Ref<DeepReadonly<QueryResult<R>>> { | |
| const evolu = getEvolu(); | |
| const data = ref<QueryResult<R>>({ | |
| row: null, | |
| rows: [], | |
| }); | |
| // Vue's built in get value function has a problem when passed functions for some reason. | |
| const getValue = computed(() => { | |
| if (typeof callback === "function") { | |
| return callback; | |
| } | |
| return callback.value; | |
| }); | |
| const compiledQuery = computed(() => evolu.createQuery(getValue.value)); | |
| watch( | |
| compiledQuery, | |
| async (query, _prev, onCleanup) => { | |
| const result = await evolu.loadQuery<R>(query); | |
| data.value = result; | |
| console.log("Set up watch!"); | |
| const unsubscribe = evolu.subscribeQuery(query)(() => { | |
| console.log("New query value!"); | |
| data.value = evolu.getQuery<R>(query); | |
| }); | |
| // Have to use the passed onCleanup function because we need this to work async. | |
| onCleanup(() => { | |
| unsubscribe(); | |
| }); | |
| }, | |
| { | |
| // Does not run initially unless we pass this (why??) lol | |
| immediate: true, | |
| } | |
| ); | |
| return data as Ref<DeepReadonly<QueryResult<R>>>; | |
| } | |
| function loadOwner(): Ref<DeepReadonly<Owner | null>> { | |
| const evolu = getEvolu(); | |
| const owner = evolu.getOwner(); | |
| const data = ref<Owner | null>(owner); | |
| // Probably would be safer to put this in an onMount function but seems to work fine. | |
| // Evolu doesn't work with SSR anyways. | |
| const unsubscribe = evolu.subscribeOwner(() => { | |
| data.value = evolu.getOwner(); | |
| }); | |
| onUnmounted(() => { | |
| unsubscribe(); | |
| }); | |
| return data; | |
| } | |
| function useSyncState(): Ref<DeepReadonly<SyncState>> { | |
| const evolu = getEvolu(); | |
| const state = evolu.getSyncState(); | |
| const data = ref<SyncState>(state); | |
| const unsubscribe = evolu.subscribeSyncState(() => { | |
| data.value = evolu.getSyncState(); | |
| }); | |
| onUnmounted(() => { | |
| unsubscribe(); | |
| }); | |
| return data; | |
| } | |
| return { | |
| q: makeQuery, | |
| getQuery: loadQuery, | |
| getEvolu, | |
| provideEvolu, | |
| getOwner: loadOwner, | |
| useSyncState, | |
| }; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment