Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 8 additions & 63 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 9 additions & 4 deletions src/create-zero-composables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ import type { MaybeRefOrGetter, ShallowRef } from 'vue'
import type { QueryResult, UseQueryOptions } from './query'
import { Zero } from '@rocicorp/zero'
import { shallowRef, toValue, watch } from 'vue'
import { useQueryWithZero } from './query'

export function createZeroComposables<S extends Schema = Schema, MD extends CustomMutatorDefs | undefined = undefined>(optsOrZero: MaybeRefOrGetter<ZeroOptions<S, MD> | { zero: Zero<S, MD> }>) {
import { useQuery as _useQuery } from './query'

export function createZeroComposables<
S extends Schema = Schema,
MD extends CustomMutatorDefs | undefined = undefined,
>(
optsOrZero: MaybeRefOrGetter<ZeroOptions<S, MD> | { zero: Zero<S, MD> }>,
) {
let z: ShallowRef<Zero<S, MD>>

function useZero(): ShallowRef<Zero<S, MD>> {
Expand Down Expand Up @@ -36,7 +41,7 @@ export function createZeroComposables<S extends Schema = Schema, MD extends Cust
options?: MaybeRefOrGetter<UseQueryOptions>,
): QueryResult<TReturn> {
const z = useZero()
return useQueryWithZero(z, query, options)
return _useQuery(z, query, options)
}

return {
Expand Down
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export { createZeroComposables } from './create-zero-composables'
export type { QueryResult, UseQueryOptions } from './query'
export { useQuery, useQueryWithZero } from './query'
export { useQuery } from './query'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine to remove useQueryWithZero, but do we still want to export useQuery? Wouldn't it be confusing that the signature of this useQuery is different than the signature of useQuery returned from createZeroComposables?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, could be. But if you don't want to use / need createZeroComposables then you want to use that import.

69 changes: 7 additions & 62 deletions src/query.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { TTL } from '@rocicorp/zero'
import type { MockInstance } from 'vitest'
import { createBuilder, createSchema, number, string, syncedQuery, table, Zero } from '@rocicorp/zero'
import { describe, expect, it, vi } from 'vitest'
import { nextTick, ref, watchEffect } from 'vue'
Expand Down Expand Up @@ -98,77 +97,23 @@ describe('useQuery', () => {
z.value.close()
})

it('useQuery with ttl (zero@0.18)', async () => {
it('useQuery with ttl', async () => {
const { z, tableQuery, useQuery } = await setupTestEnvironment()
if (!('updateTTL' in tableQuery)) {
// 0.19 removed updateTTL from the query
return
}

const ttl = ref<TTL>('1m')

const materializeSpy = vi.spyOn(tableQuery, 'materialize')
// @ts-expect-error missing from v0.19+
const updateTTLSpy = vi.spyOn(tableQuery, 'updateTTL')
const materializeSpy = vi.spyOn(z.value, 'materialize')
const queryGetter = vi.fn(() => tableQuery)

useQuery(queryGetter, () => ({ ttl: ttl.value }))

expect(queryGetter).toHaveBeenCalledTimes(1)
expect(updateTTLSpy).toHaveBeenCalledTimes(0)

expect(materializeSpy).toHaveLastReturnedWith(expect.any(VueView))
expect(materializeSpy).toHaveBeenCalledExactlyOnceWith(
tableQuery,
vueViewFactory,
'1m',
{ ttl: '1m' },
)
materializeSpy.mockClear()

ttl.value = '10m'
await nextTick()

expect(materializeSpy).toHaveBeenCalledTimes(0)
expect(updateTTLSpy).toHaveBeenCalledExactlyOnceWith('10m')

z.value.close()
})

it('useQuery with ttl (zero@0.19)', async () => {
const { z, tableQuery, useQuery } = await setupTestEnvironment()
if ('updateTTL' in tableQuery) {
// 0.19 removed updateTTL from the query
return
}

const ttl = ref<TTL>('1m')

let materializeSpy: MockInstance
// @ts-expect-error only present in v0.23+
if (z.value.materialize) {
materializeSpy = vi.spyOn(z.value, 'materialize')
}
else {
materializeSpy = vi.spyOn(tableQuery, 'materialize')
}

const queryGetter = vi.fn(() => tableQuery)

useQuery(queryGetter, () => ({ ttl: ttl.value }))
expect(queryGetter).toHaveBeenCalledTimes(1)

expect(materializeSpy).toHaveLastReturnedWith(expect.any(VueView))
// @ts-expect-error only present in v0.23+
if (z.value.materialize) {
expect(materializeSpy).toHaveBeenCalledExactlyOnceWith(
tableQuery,
vueViewFactory,
{ ttl: '1m' },
)
}
else {
expect(materializeSpy).toHaveBeenCalledExactlyOnceWith(
vueViewFactory,
'1m',
)
}

const view: VueView<unknown> = materializeSpy.mock.results[0]!.value
const updateTTLSpy = vi.spyOn(view, 'updateTTL')
Expand Down Expand Up @@ -329,7 +274,7 @@ describe('useQuery', () => {
await z.mutate.table.insert({ a: 1, b: 'a' })
await z.mutate.table.insert({ a: 2, b: 'b' })

const { data: rows, status } = useQuery(() => z.query.table)
const { data: rows, status } = useQuery(z, () => z.query.table)
expect(rows.value).toMatchInlineSnapshot(`[
{
"a": 1,
Expand Down
46 changes: 6 additions & 40 deletions src/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,40 +26,17 @@ export interface QueryResult<TReturn> {
error: ComputedRef<QueryError & { retry: () => void } | undefined>
}

/**
* @deprecated
*
* Use `useQuery` returned from `createZero` instead. This function doesn't
* support Synced Queries, and will be removed in a future version.
*
* @param query The query to execute.
* @param options Options for the query.
* @returns The result of the query.
*/
export function useQuery<
TSchema extends Schema,
TTable extends keyof TSchema['tables'] & string,
TReturn,
>(
query: MaybeRefOrGetter<Query<TSchema, TTable, TReturn>>,
options?: MaybeRefOrGetter<UseQueryOptions>,
): QueryResult<TReturn> {
return useQueryWithZero(undefined as unknown as Zero<TSchema>, query, options)
}

export function useQueryWithZero<
TSchema extends Schema,
TTable extends keyof TSchema['tables'] & string,
TReturn,
MD extends CustomMutatorDefs | undefined = undefined,
>(
z: MaybeRefOrGetter<Zero<TSchema, MD>>,
query: MaybeRefOrGetter<Query<TSchema, TTable, TReturn>>,
options?: MaybeRefOrGetter<UseQueryOptions>,
): QueryResult<TReturn> {
const ttl = computed(() => {
return toValue(options)?.ttl ?? DEFAULT_TTL_MS
})
const ttl = computed(() => toValue(options)?.ttl ?? DEFAULT_TTL_MS)
const view = shallowRef<VueView<HumanReadable<TReturn>> | null>(null)
const refetchKey = shallowRef(0)

Expand All @@ -71,18 +48,7 @@ export function useQueryWithZero<
],
([q, z]) => {
view.value?.destroy()

// Only present in v0.23+
if (z?.materialize) {
view.value = z.materialize(q, vueViewFactory, { ttl: ttl.value })
return
}

// For synced queries (customQueryID), we need the Zero instance (e.g. during SSR it will be undefined)
if (q.customQueryID)
return

view.value = q.materialize(vueViewFactory, ttl.value)
view.value = z.materialize(q, vueViewFactory, { ttl: toValue(ttl) })
},
{ immediate: true },
)
Expand All @@ -96,12 +62,12 @@ export function useQueryWithZero<
}

return {
data: computed(() => view.value!.data),
status: computed(() => view.value!.status),
error: computed(() => view.value!.error
data: computed(() => view.value?.data as HumanReadable<TReturn>),
status: computed(() => view.value?.status ?? 'unknown'),
error: computed(() => view.value?.error
? {
retry: () => { refetchKey.value++ },
...view.value!.error,
...view.value.error,
}
: undefined,
),
Expand Down
1 change: 1 addition & 0 deletions src/view.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,7 @@ describe('vueViewFactory', () => {
onDestroy,
onTransactionCommit,
true,
() => {},
)
})

Expand Down
11 changes: 2 additions & 9 deletions src/view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,22 +162,15 @@ export function vueViewFactory<
onDestroy: () => void,
onTransactionCommit: (cb: () => void) => void,
queryComplete: true | ErroredQuery | Promise<true>,
updateTTL?: (ttl: TTL) => void,
updateTTL: (ttl: TTL) => void,
) {
interface UpdateTTL {
updateTTL: (ttl: TTL) => void
}
return new VueView<HumanReadable<TReturn>>(
input,
onTransactionCommit,
format,
onDestroy,
queryComplete,
// In zero@0.19 updateTTL is passed in to the view factory.
// In zero@0.18 it was a property on the query.
updateTTL ?? (ttl =>
(query as unknown as UpdateTTL).updateTTL(ttl)
),
updateTTL,
)
}

Expand Down