diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ca7034..47e4c91 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,7 +38,7 @@ importers: version: 9.3.0 knip: specifier: latest - version: 5.70.2(@types/node@24.10.1)(typescript@5.9.3) + version: 5.71.0(@types/node@24.10.1)(typescript@5.9.3) lint-staged: specifier: latest version: 16.2.7 @@ -3225,8 +3225,8 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - knip@5.70.2: - resolution: {integrity: sha512-LI7DbeVnk7h9+FAet5KzzHNdDwJyqDa2+cn4uQfZYTfpuVjEqtGmYD9r5b9JEuOs4eVkf/7sskNhWXxELm3C/Q==} + knip@5.71.0: + resolution: {integrity: sha512-hwgdqEJ+7DNJ5jE8BCPu7b57TY7vUwP6MzWYgCgPpg6iPCee/jKPShDNIlFER2koti4oz5xF88VJbKCb4Wl71g==} engines: {node: '>=18.18.0'} hasBin: true peerDependencies: @@ -4552,46 +4552,6 @@ packages: resolution: {integrity: sha512-JwPr6erhX53EWH/HCSzfy1tTFrtPXUe927wdM1jqBBeYp1OM+qPHjWbsvv6pIBduqdgxxS+ScfG7S28pzyr2DQ==} engines: {node: '>=0.10.48'} - vite@7.2.4: - resolution: {integrity: sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - jiti: '>=1.21.0' - less: ^4.0.0 - lightningcss: ^1.21.0 - sass: ^1.70.0 - sass-embedded: ^1.70.0 - stylus: '>=0.54.8' - sugarss: ^5.0.0 - terser: ^5.16.0 - tsx: ^4.8.1 - yaml: ^2.4.2 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - vite@7.2.6: resolution: {integrity: sha512-tI2l/nFHC5rLh7+5+o7QjKjSR04ivXDF4jcgV0f/bTQ+OJiITy5S6gaynVsEM+7RqzufMnVbIon6Sr5x1SDYaQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -6522,13 +6482,13 @@ snapshots: chai: 6.2.1 tinyrainbow: 3.0.3 - '@vitest/mocker@4.0.14(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))': + '@vitest/mocker@4.0.14(vite@7.2.6(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2))': dependencies: '@vitest/spy': 4.0.14 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.2.6(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) '@vitest/pretty-format@4.0.14': dependencies: @@ -8159,7 +8119,7 @@ snapshots: dependencies: json-buffer: 3.0.1 - knip@5.70.2(@types/node@24.10.1)(typescript@5.9.3): + knip@5.71.0(@types/node@24.10.1)(typescript@5.9.3): dependencies: '@nodelib/fs.walk': 1.2.8 '@types/node': 24.10.1 @@ -9696,21 +9656,6 @@ snapshots: version-guard@1.1.3: {} - vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2): - dependencies: - esbuild: 0.25.12 - fdir: 6.5.0(picomatch@4.0.3) - picomatch: 4.0.3 - postcss: 8.5.6 - rollup: 4.53.3 - tinyglobby: 0.2.15 - optionalDependencies: - '@types/node': 24.10.1 - fsevents: 2.3.3 - jiti: 2.6.1 - tsx: 4.21.0 - yaml: 2.8.2 - vite@7.2.6(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: esbuild: 0.25.12 @@ -9729,7 +9674,7 @@ snapshots: vitest@4.0.14(@opentelemetry/api@1.9.0)(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2): dependencies: '@vitest/expect': 4.0.14 - '@vitest/mocker': 4.0.14(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/mocker': 4.0.14(vite@7.2.6(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2)) '@vitest/pretty-format': 4.0.14 '@vitest/runner': 4.0.14 '@vitest/snapshot': 4.0.14 @@ -9746,7 +9691,7 @@ snapshots: tinyexec: 0.3.2 tinyglobby: 0.2.15 tinyrainbow: 3.0.3 - vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) + vite: 7.2.6(@types/node@24.10.1)(jiti@2.6.1)(tsx@4.21.0)(yaml@2.8.2) why-is-node-running: 2.3.0 optionalDependencies: '@opentelemetry/api': 1.9.0 diff --git a/src/create-zero-composables.ts b/src/create-zero-composables.ts index f60842d..283fa6f 100644 --- a/src/create-zero-composables.ts +++ b/src/create-zero-composables.ts @@ -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(optsOrZero: MaybeRefOrGetter | { zero: Zero }>) { +import { useQuery as _useQuery } from './query' + +export function createZeroComposables< + S extends Schema = Schema, + MD extends CustomMutatorDefs | undefined = undefined, +>( + optsOrZero: MaybeRefOrGetter | { zero: Zero }>, +) { let z: ShallowRef> function useZero(): ShallowRef> { @@ -36,7 +41,7 @@ export function createZeroComposables, ): QueryResult { const z = useZero() - return useQueryWithZero(z, query, options) + return _useQuery(z, query, options) } return { diff --git a/src/index.ts b/src/index.ts index 696b550..b8879bb 100644 --- a/src/index.ts +++ b/src/index.ts @@ -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' diff --git a/src/query.test.ts b/src/query.test.ts index cfaf7fb..8db464a 100644 --- a/src/query.test.ts +++ b/src/query.test.ts @@ -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' @@ -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('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('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 = materializeSpy.mock.results[0]!.value const updateTTLSpy = vi.spyOn(view, 'updateTTL') @@ -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, diff --git a/src/query.ts b/src/query.ts index 536ceab..20d086a 100644 --- a/src/query.ts +++ b/src/query.ts @@ -26,40 +26,17 @@ export interface QueryResult { error: ComputedRef 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>, - options?: MaybeRefOrGetter, -): QueryResult { - return useQueryWithZero(undefined as unknown as Zero, query, options) -} - -export function useQueryWithZero< - TSchema extends Schema, - TTable extends keyof TSchema['tables'] & string, - TReturn, MD extends CustomMutatorDefs | undefined = undefined, >( z: MaybeRefOrGetter>, query: MaybeRefOrGetter>, options?: MaybeRefOrGetter, ): QueryResult { - const ttl = computed(() => { - return toValue(options)?.ttl ?? DEFAULT_TTL_MS - }) + const ttl = computed(() => toValue(options)?.ttl ?? DEFAULT_TTL_MS) const view = shallowRef> | null>(null) const refetchKey = shallowRef(0) @@ -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 }, ) @@ -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), + status: computed(() => view.value?.status ?? 'unknown'), + error: computed(() => view.value?.error ? { retry: () => { refetchKey.value++ }, - ...view.value!.error, + ...view.value.error, } : undefined, ), diff --git a/src/view.test.ts b/src/view.test.ts index 68a293f..3616c3b 100644 --- a/src/view.test.ts +++ b/src/view.test.ts @@ -1306,6 +1306,7 @@ describe('vueViewFactory', () => { onDestroy, onTransactionCommit, true, + () => {}, ) }) diff --git a/src/view.ts b/src/view.ts index 64a908b..3bb6bcd 100644 --- a/src/view.ts +++ b/src/view.ts @@ -162,22 +162,15 @@ export function vueViewFactory< onDestroy: () => void, onTransactionCommit: (cb: () => void) => void, queryComplete: true | ErroredQuery | Promise, - updateTTL?: (ttl: TTL) => void, + updateTTL: (ttl: TTL) => void, ) { - interface UpdateTTL { - updateTTL: (ttl: TTL) => void - } return new VueView>( 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, ) }