Skip to content

Commit dbf51fe

Browse files
committed
fix
1 parent 333964f commit dbf51fe

File tree

6 files changed

+359
-156
lines changed

6 files changed

+359
-156
lines changed

README.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,17 @@ npm install zero-vue
1919
pnpm install zero-vue
2020
```
2121

22+
Register plugin:
23+
24+
```js
25+
import { createApp } from 'vue'
26+
import { createZero } from 'zero-vue'
27+
28+
const app = createApp(App)
29+
app.use(createZero())
30+
```
31+
32+
Use `useQuery`:
2233
```js
2334
import { Zero } from '@rocicorp/zero'
2435
import { useQuery } from 'zero-vue'
@@ -34,6 +45,15 @@ const z = new Zero({
3445
const { data: users } = useQuery(z.query.user)
3546
```
3647

48+
Optional: typing `useZero`:
49+
```ts
50+
import { createUseZero } from 'zero-vue';
51+
import type { Schema } from './schema.ts';
52+
import type { Mutators } from './mutators.ts';
53+
export const useZero = createUseZero<Schema, Mutators>();
54+
const z = useZero(); // z is typed with your own schema and mutators
55+
```
56+
3757
> [!TIP]
3858
> See [the playground](./playground) for a full working example based on [rocicorp/hello-zero](https://github.com/rocicorp/hello-zero), or check out [danielroe/hello-zero-nuxt](https://github.com/danielroe/hello-zero-nuxt) to see how to set things up with [Nuxt](https://nuxt.com/).
3959

src/create-zero.test.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import { createSchema, number, string, table, Zero } from '@rocicorp/zero'
2+
import { assert, describe, expect, it } from 'vitest'
3+
import { computed, createApp, inject, ref } from 'vue'
4+
import { createZero, zeroSymbol } from './create-zero'
5+
6+
const testSchema = createSchema({
7+
tables: [
8+
table('test')
9+
.columns({
10+
id: number(),
11+
name: string(),
12+
})
13+
.primaryKey('id'),
14+
],
15+
})
16+
17+
describe('createZero', () => {
18+
it('installs and provides zero instance to Vue app', () => {
19+
const app = createApp({})
20+
app.use(createZero({
21+
userID: 'test-user',
22+
server: null,
23+
schema: testSchema,
24+
kvStore: 'mem' as const,
25+
}))
26+
27+
app.runWithContext(() => {
28+
const zero = inject(zeroSymbol)
29+
assert(zero?.value)
30+
expect(zero?.value.userID).toEqual('test-user')
31+
})
32+
})
33+
34+
it('accepts Zero instance instead of options', () => {
35+
const app = createApp({})
36+
const zero = new Zero({
37+
userID: 'test-user',
38+
server: null,
39+
schema: testSchema,
40+
kvStore: 'mem' as const,
41+
})
42+
app.use(createZero({ zero }))
43+
44+
app.runWithContext(() => {
45+
const injectedZero = inject(zeroSymbol)
46+
assert(injectedZero?.value)
47+
expect(injectedZero.value).toEqual(zero)
48+
})
49+
})
50+
51+
it('updates when options change', async () => {
52+
const app = createApp({})
53+
const userID = ref('test-user')
54+
const zeroOptions = computed(() => ({
55+
userID: userID.value,
56+
server: null,
57+
schema: testSchema,
58+
kvStore: 'mem' as const,
59+
}))
60+
61+
app.use(createZero(zeroOptions))
62+
63+
await app.runWithContext(async () => {
64+
const injectedZero = inject(zeroSymbol)
65+
assert(injectedZero?.value)
66+
67+
expect(injectedZero.value.userID).toEqual('test-user')
68+
69+
const oldZero = injectedZero.value
70+
71+
userID.value = 'test-user-2'
72+
await 1
73+
74+
expect(injectedZero.value.userID).toEqual('test-user-2')
75+
expect(injectedZero.value.closed).toBe(false)
76+
expect(oldZero.closed).toBe(true)
77+
})
78+
})
79+
80+
it('updates when Zero instance changes', async () => {
81+
const app = createApp({})
82+
const userID = ref('test-user')
83+
84+
const zero = computed(() => ({ zero: new Zero({
85+
userID: userID.value,
86+
server: null,
87+
schema: testSchema,
88+
kvStore: 'mem' as const,
89+
}) }))
90+
91+
app.use(createZero(zero))
92+
93+
await app.runWithContext(async () => {
94+
const injectedZero = inject(zeroSymbol)
95+
assert(injectedZero?.value)
96+
97+
expect(injectedZero.value.userID).toEqual('test-user')
98+
99+
const oldZero = injectedZero.value
100+
101+
userID.value = 'test-user-2'
102+
await 1
103+
104+
expect(injectedZero.value.userID).toEqual('test-user-2')
105+
expect(injectedZero.value.closed).toBe(false)
106+
expect(oldZero.closed).toBe(true)
107+
})
108+
})
109+
})

src/create-zero.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
1-
import type { Schema, ZeroOptions } from '@rocicorp/zero'
1+
import type { CustomMutatorDefs, Schema, ZeroOptions } from '@rocicorp/zero'
22
import type { App, InjectionKey, MaybeRefOrGetter, ShallowRef } from 'vue'
33
import { Zero } from '@rocicorp/zero'
44
import { shallowRef, toValue, watch } from 'vue'
55

66
export const zeroSymbol = Symbol('zero') as InjectionKey<ShallowRef<Zero<Schema, undefined>>>
77

8-
export function createZero<S extends Schema = Schema>(opts: MaybeRefOrGetter<ZeroOptions<S>>) {
9-
const z = shallowRef() as ShallowRef<Zero<S>>
8+
const oldZeroCleanups = new Set()
109

11-
watch(() => toValue(opts), async (opts) => {
12-
// await z.value?.close()
13-
z.value = new Zero(opts)
10+
export function createZero<S extends Schema = Schema, MD extends CustomMutatorDefs | undefined = undefined>(optsOrZero: MaybeRefOrGetter<ZeroOptions<S, MD> | { zero: Zero<S, MD> }>) {
11+
const z = shallowRef() as ShallowRef<Zero<S, MD>>
12+
13+
const opts = toValue(optsOrZero)
14+
z.value = 'zero' in opts ? opts.zero : new Zero(opts)
15+
16+
watch(() => toValue(optsOrZero), (opts) => {
17+
const cleanupZeroPromise = z.value.close()
18+
oldZeroCleanups.add(cleanupZeroPromise)
19+
cleanupZeroPromise.finally(() => {
20+
oldZeroCleanups.delete(cleanupZeroPromise)
21+
})
22+
23+
z.value = 'zero' in opts ? opts.zero : new Zero(opts)
1424
}, { deep: true })
1525

1626
return {
1727
install: (app: App) => {
18-
z.value = new Zero(toValue(opts))
19-
2028
// @ts-expect-error - TODO: type properly
2129
app.provide(zeroSymbol, z)
2230
},

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1+
export { createUseZero } from './create-use-zero'
2+
export { createZero } from './create-zero'
13
export { useQuery, type UseQueryOptions } from './query'

0 commit comments

Comments
 (0)