Skip to content

Commit 333964f

Browse files
committed
draft: zero 0.23
1 parent 6c28133 commit 333964f

File tree

9 files changed

+939
-35
lines changed

9 files changed

+939
-35
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,17 @@
3535
"vue": "^3.5.13"
3636
},
3737
"dependencies": {
38-
"@rocicorp/zero": "^0.22.0"
38+
"@rocicorp/zero": "^0.23.0"
3939
},
4040
"devDependencies": {
4141
"@antfu/eslint-config": "latest",
4242
"@rocicorp/resolver": "1.0.2",
43+
"@testing-library/vue": "^8.1.0",
4344
"@vitest/coverage-v8": "latest",
4445
"bumpp": "latest",
4546
"changelogithub": "13.16.0",
4647
"eslint": "latest",
48+
"happy-dom": "^18.0.1",
4749
"installed-check": "latest",
4850
"knip": "latest",
4951
"lint-staged": "latest",

pnpm-lock.yaml

Lines changed: 827 additions & 26 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
packages:
22
- playground
3+
34
ignoredBuiltDependencies:
45
- esbuild
56
- protobufjs
67
- unrs-resolver
8+
79
onlyBuiltDependencies:
810
- '@rocicorp/zero-sqlite3'
11+
- oxc-resolver
912
- simple-git-hooks

src/create-use-zero.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { CustomMutatorDefs, Schema, Zero } from '@rocicorp/zero'
2+
import type { ShallowRef } from 'vue'
3+
import { inject } from 'vue'
4+
import { zeroSymbol } from './create-zero'
5+
6+
export function createUseZero<
7+
S extends Schema,
8+
MD extends CustomMutatorDefs | undefined = undefined,
9+
>() {
10+
return () => inject(zeroSymbol) as ShallowRef<Zero<S, MD>>
11+
}

src/create-zero.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import type { Schema, ZeroOptions } from '@rocicorp/zero'
2+
import type { App, InjectionKey, MaybeRefOrGetter, ShallowRef } from 'vue'
3+
import { Zero } from '@rocicorp/zero'
4+
import { shallowRef, toValue, watch } from 'vue'
5+
6+
export const zeroSymbol = Symbol('zero') as InjectionKey<ShallowRef<Zero<Schema, undefined>>>
7+
8+
export function createZero<S extends Schema = Schema>(opts: MaybeRefOrGetter<ZeroOptions<S>>) {
9+
const z = shallowRef() as ShallowRef<Zero<S>>
10+
11+
watch(() => toValue(opts), async (opts) => {
12+
// await z.value?.close()
13+
z.value = new Zero(opts)
14+
}, { deep: true })
15+
16+
return {
17+
install: (app: App) => {
18+
z.value = new Zero(toValue(opts))
19+
20+
// @ts-expect-error - TODO: type properly
21+
app.provide(zeroSymbol, z)
22+
},
23+
}
24+
}

src/query.test.ts

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,26 @@
11
import type { TTL } from '@rocicorp/zero'
2-
import { createSchema, number, string, table, Zero } from '@rocicorp/zero'
2+
import { createBuilder, createSchema, number, string, syncedQuery, table, Zero } from '@rocicorp/zero'
33
import { describe, expect, it, vi } from 'vitest'
4-
import { ref, watchEffect } from 'vue'
4+
import { createApp, nextTick, onMounted, ref, shallowRef, watchEffect } from 'vue'
5+
import { createUseZero } from './create-use-zero'
6+
import { createZero } from './create-zero'
57
import { useQuery } from './query'
68
import { VueView, vueViewFactory } from './view'
79

10+
export function withSetup<T>(composable: () => T) {
11+
const result = shallowRef<T>()
12+
const app = createApp({
13+
setup() {
14+
onMounted(() => {
15+
result.value = composable()
16+
})
17+
18+
return () => {}
19+
},
20+
})
21+
return [result, app] as const
22+
}
23+
824
async function setupTestEnvironment() {
925
const schema = createSchema({
1026
tables: [
@@ -16,22 +32,41 @@ async function setupTestEnvironment() {
1632
.primaryKey('a'),
1733
],
1834
})
35+
const builder = createBuilder(schema)
1936

20-
const z = new Zero({
37+
const useZero = createUseZero<typeof schema>()
38+
const [zero, app] = withSetup(useZero)
39+
app.use(createZero({
2140
userID: 'asdf',
2241
server: null,
2342
schema,
2443
// This is often easier to develop with if you're frequently changing
2544
// the schema. Switch to 'idb' for local-persistence.
2645
kvStore: 'mem',
27-
})
46+
}))
47+
app.mount(document.createElement('div'))
48+
49+
const z = zero.value!.value
2850

2951
await z.mutate.table.insert({ a: 1, b: 'a' })
3052
await z.mutate.table.insert({ a: 2, b: 'b' })
3153

54+
const byIdQuery = syncedQuery(
55+
'byId',
56+
([id]) => {
57+
if (typeof id !== 'number') {
58+
throw new TypeError('id must be a number')
59+
}
60+
return [id] as const
61+
},
62+
(id: number) => {
63+
return builder.table.where('a', id)
64+
},
65+
)
66+
3267
const tableQuery = z.query.table
3368

34-
return { z, tableQuery }
69+
return { z, tableQuery, byIdQuery }
3570
}
3671

3772
describe('useQuery', () => {
@@ -112,7 +147,7 @@ describe('useQuery', () => {
112147
z.close()
113148
})
114149

115-
it('useQuery with ttl (zero@0.19)', async () => {
150+
it.only('useQuery with ttl (zero@0.19)', async () => {
116151
const { z, tableQuery } = await setupTestEnvironment()
117152
if ('updateTTL' in tableQuery) {
118153
// 0.19 removed updateTTL from the query
@@ -258,4 +293,23 @@ describe('useQuery', () => {
258293

259294
z.close()
260295
})
296+
297+
it.skip('useQuery with syncedQuery', async () => {
298+
const { z, byIdQuery } = await setupTestEnvironment()
299+
300+
const a = ref(1)
301+
const { data: rows, status } = useQuery(() => byIdQuery(a.value))
302+
303+
expect(rows.value).toMatchInlineSnapshot(`
304+
[
305+
{
306+
"a": 1,
307+
"b": "a",
308+
Symbol(rc): 1,
309+
},
310+
]`)
311+
expect(status.value).toEqual('unknown')
312+
313+
z.close()
314+
})
261315
})

src/query.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ import type { VueView } from './view'
77
import {
88
computed,
99
getCurrentInstance,
10+
inject,
1011
onUnmounted,
1112
shallowRef,
1213
toValue,
1314
watch,
1415
} from 'vue'
16+
import { zeroSymbol } from './create-zero'
1517
import { vueViewFactory } from './view'
1618

1719
const DEFAULT_TTL_MS = 1_000 * 60 * 5
@@ -38,11 +40,16 @@ export function useQuery<
3840
})
3941
const view = shallowRef<VueView<HumanReadable<TReturn>> | null>(null)
4042

43+
const z = inject(zeroSymbol)
44+
if (!z) {
45+
throw new Error('Zero not found. Did you forget to call app.use(createZero())?')
46+
}
47+
4148
watch(
4249
() => toValue(query),
4350
(q) => {
4451
view.value?.destroy()
45-
view.value = q.materialize(vueViewFactory, ttl.value)
52+
view.value = z.value.materialize(q, vueViewFactory, { ttl: ttl.value })
4653
},
4754
{ immediate: true },
4855
)

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
"compilerOptions": {
33
"target": "es2022",
44
"lib": [
5-
"es2022"
5+
"es2022",
6+
"dom"
67
],
78
"moduleDetection": "force",
89
"module": "preserve",

vitest.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export default defineConfig({
1010
},
1111
},
1212
test: {
13+
environment: 'happy-dom',
1314
coverage: {
1415
include: ['src'],
1516
reporter: ['text', 'json', 'html'],

0 commit comments

Comments
 (0)