@cero-base/react 0.0.1 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -10
- package/package.json +3 -3
- package/src/hooks/use-client.jsx +11 -29
- package/src/hooks/use-query.js +10 -19
- package/src/ui/cero.jsx +6 -7
package/README.md
CHANGED
|
@@ -11,11 +11,14 @@ npm install @cero-base/react
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
|
13
13
|
```jsx
|
|
14
|
-
import { Cero, Room } from '@cero-base/react'
|
|
14
|
+
import { Cero, Room, useClient } from '@cero-base/react'
|
|
15
15
|
|
|
16
16
|
function App() {
|
|
17
|
+
const { db, ready, error } = useClient(client)
|
|
18
|
+
|
|
19
|
+
if (!ready) return null
|
|
17
20
|
return (
|
|
18
|
-
<Cero
|
|
21
|
+
<Cero db={db}>
|
|
19
22
|
<Room id={roomId}>
|
|
20
23
|
<Chat />
|
|
21
24
|
</Room>
|
|
@@ -26,9 +29,17 @@ function App() {
|
|
|
26
29
|
|
|
27
30
|
## Hooks
|
|
28
31
|
|
|
32
|
+
### useClient(client)
|
|
33
|
+
|
|
34
|
+
Manages client lifecycle (ready/error). Pass a `Client` instance.
|
|
35
|
+
|
|
36
|
+
```jsx
|
|
37
|
+
const { db, ready, error } = useClient(client)
|
|
38
|
+
```
|
|
39
|
+
|
|
29
40
|
### useCero()
|
|
30
41
|
|
|
31
|
-
Access the db instance from context.
|
|
42
|
+
Access the db/client instance from context.
|
|
32
43
|
|
|
33
44
|
```jsx
|
|
34
45
|
const db = useCero()
|
|
@@ -42,12 +53,9 @@ Access the current Room from context.
|
|
|
42
53
|
const room = useRoom()
|
|
43
54
|
```
|
|
44
55
|
|
|
45
|
-
### useCollection(name, query?)
|
|
46
|
-
|
|
47
|
-
Subscribe to a collection. Returns live data + CRUD methods.
|
|
56
|
+
### useCollection(name, query?, opts?)
|
|
48
57
|
|
|
49
|
-
|
|
50
|
-
- Shared collections: requires `<Room>` provider
|
|
58
|
+
Subscribe to a collection with CRUD methods.
|
|
51
59
|
|
|
52
60
|
```jsx
|
|
53
61
|
const { data, put, del, get, sub } = useCollection('messages')
|
|
@@ -55,7 +63,7 @@ const { data, put, del, get, sub } = useCollection('messages')
|
|
|
55
63
|
|
|
56
64
|
### useRooms()
|
|
57
65
|
|
|
58
|
-
|
|
66
|
+
Subscribe to room list.
|
|
59
67
|
|
|
60
68
|
```jsx
|
|
61
69
|
const { data: rooms } = useRooms()
|
|
@@ -71,7 +79,7 @@ const { data: members } = useMembers()
|
|
|
71
79
|
|
|
72
80
|
### useProfile()
|
|
73
81
|
|
|
74
|
-
Subscribe to identity profile
|
|
82
|
+
Subscribe to identity profile with setter.
|
|
75
83
|
|
|
76
84
|
```jsx
|
|
77
85
|
const { data: profile, set } = useProfile()
|
|
@@ -84,6 +92,7 @@ await set({ name: 'Alice' })
|
|
|
84
92
|
| --------------------- | ------------------------------------ |
|
|
85
93
|
| `Cero` | Context provider — wraps db instance |
|
|
86
94
|
| `Room` | Context provider — wraps room by id |
|
|
95
|
+
| `useClient(client)` | Manage client lifecycle |
|
|
87
96
|
| `useCero()` | Access db from context |
|
|
88
97
|
| `useRoom()` | Access room from context |
|
|
89
98
|
| `useProfile()` | Subscribe to profile |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cero-base/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "React hooks and providers for cero-base",
|
|
5
5
|
"files": [
|
|
6
6
|
"src",
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
".": "./src/index.js"
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@cero-base/core": "^0.0.
|
|
22
|
-
"@cero-base/rpc": "^0.0.
|
|
21
|
+
"@cero-base/core": "^0.0.5",
|
|
22
|
+
"@cero-base/rpc": "^0.0.5"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@testing-library/react": "^16.0.0",
|
package/src/hooks/use-client.jsx
CHANGED
|
@@ -1,39 +1,21 @@
|
|
|
1
|
-
import { useState, useEffect
|
|
2
|
-
import { Client, getRpc } from '@cero-base/rpc'
|
|
1
|
+
import { useState, useEffect } from 'react'
|
|
3
2
|
|
|
4
|
-
export function useClient(
|
|
3
|
+
export function useClient(client) {
|
|
5
4
|
const [db, setDb] = useState(null)
|
|
6
5
|
const [ready, setReady] = useState(false)
|
|
7
6
|
const [error, setError] = useState(null)
|
|
8
|
-
const ref = useRef(null)
|
|
9
7
|
|
|
10
8
|
useEffect(() => {
|
|
11
|
-
|
|
9
|
+
client
|
|
10
|
+
.ready()
|
|
11
|
+
.then(() => {
|
|
12
|
+
setDb(client)
|
|
13
|
+
setReady(true)
|
|
14
|
+
})
|
|
15
|
+
.catch((err) => setError(err.message || String(err)))
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
ref.current = ctx
|
|
16
|
-
const rpc = getRpc(ctx.pipe, spec)
|
|
17
|
-
client = new Client(rpc, schema, spec)
|
|
18
|
-
|
|
19
|
-
client
|
|
20
|
-
.ready()
|
|
21
|
-
.then(() => {
|
|
22
|
-
setDb(client)
|
|
23
|
-
setReady(true)
|
|
24
|
-
})
|
|
25
|
-
.catch((err) => setError('RPC ready failed: ' + (err.message || String(err))))
|
|
26
|
-
} catch (err) {
|
|
27
|
-
setError('Client setup failed: ' + (err.message || String(err)))
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return () => {
|
|
31
|
-
try {
|
|
32
|
-
if (client) client.close()
|
|
33
|
-
if (ref.current?.destroy) ref.current.destroy()
|
|
34
|
-
} catch {}
|
|
35
|
-
}
|
|
36
|
-
}, [])
|
|
17
|
+
return () => client.close()
|
|
18
|
+
}, [client])
|
|
37
19
|
|
|
38
20
|
return { db, ready, error }
|
|
39
21
|
}
|
package/src/hooks/use-query.js
CHANGED
|
@@ -3,46 +3,37 @@ import { store } from '@simplestack/store'
|
|
|
3
3
|
import { useStoreValue } from '@simplestack/store/react'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* useQuery —
|
|
7
|
-
*
|
|
8
|
-
* All named hooks compose from this. Exported as escape hatch for custom subscriptions.
|
|
9
|
-
*
|
|
10
|
-
* Uses @simplestack/store as the reactive layer — signal-based, fine-grained updates.
|
|
11
|
-
* The store persists between mounts (stale-while-revalidate for free).
|
|
12
|
-
* Redundant updates are skipped via Object.is inside store.select().set().
|
|
6
|
+
* useQuery — subscribes to a Readable stream, returns reactive data.
|
|
13
7
|
*
|
|
14
8
|
* @param {Function} streamFn - Returns a Readable stream (from .sub())
|
|
15
9
|
* @param {Array} deps - Dependency array (re-subscribes when changed)
|
|
16
10
|
* @returns {{ data: any, busy: boolean, error: Error|null }}
|
|
17
11
|
*/
|
|
18
12
|
export function useQuery(streamFn, deps) {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
s.current = store({ data: null, busy: true, error: null })
|
|
13
|
+
const state = useRef(null)
|
|
14
|
+
if (state.current === null) {
|
|
15
|
+
state.current = store({ data: null, busy: true, error: null })
|
|
23
16
|
}
|
|
24
17
|
|
|
25
18
|
useEffect(() => {
|
|
26
|
-
const st =
|
|
19
|
+
const st = state.current
|
|
27
20
|
st.select('busy').set(true)
|
|
28
21
|
|
|
29
22
|
const stream = streamFn()
|
|
30
23
|
|
|
31
|
-
stream.on('data', (
|
|
32
|
-
|
|
33
|
-
ref.current = d
|
|
34
|
-
st.select('data').set(d)
|
|
24
|
+
stream.on('data', (data) => {
|
|
25
|
+
st.select('data').set(data)
|
|
35
26
|
st.select('busy').set(false)
|
|
36
27
|
st.select('error').set(null)
|
|
37
28
|
})
|
|
38
29
|
|
|
39
|
-
stream.on('error', (
|
|
40
|
-
st.select('error').set(
|
|
30
|
+
stream.on('error', (error) => {
|
|
31
|
+
st.select('error').set(error)
|
|
41
32
|
st.select('busy').set(false)
|
|
42
33
|
})
|
|
43
34
|
|
|
44
35
|
return () => stream.destroy()
|
|
45
36
|
}, deps) // eslint-disable-line react-hooks/exhaustive-deps
|
|
46
37
|
|
|
47
|
-
return useStoreValue(
|
|
38
|
+
return useStoreValue(state.current)
|
|
48
39
|
}
|
package/src/ui/cero.jsx
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react'
|
|
2
2
|
import { CeroContext } from './context.js'
|
|
3
3
|
|
|
4
|
-
export function Cero({
|
|
5
|
-
const [ready, setReady] = useState(
|
|
4
|
+
export function Cero({ db, children }) {
|
|
5
|
+
const [ready, setReady] = useState(db.opened)
|
|
6
6
|
|
|
7
7
|
useEffect(() => {
|
|
8
|
-
if (!
|
|
9
|
-
|
|
10
|
-
.ready()
|
|
8
|
+
if (!db.opened)
|
|
9
|
+
db.ready()
|
|
11
10
|
.then(() => setReady(true))
|
|
12
11
|
.catch(console.error)
|
|
13
12
|
else setReady(true)
|
|
14
|
-
}, [
|
|
13
|
+
}, [db])
|
|
15
14
|
|
|
16
15
|
if (!ready) return null
|
|
17
16
|
|
|
18
|
-
return <CeroContext.Provider value={
|
|
17
|
+
return <CeroContext.Provider value={db}>{children}</CeroContext.Provider>
|
|
19
18
|
}
|