Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit36f00cc

Browse files
authored
feat(client): add entity and query functions (#93)
1 parentff7a181 commit36f00cc

File tree

5 files changed

+93
-26
lines changed

5 files changed

+93
-26
lines changed

‎README.md‎

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -173,17 +173,21 @@ todos
173173

174174
This hook returns the current database client with some helpful functions for syncing data with a backend.
175175

176-
-`client.dbToString()` serializes the whole db including the lookupHelpers to a string
177-
-`client.dbFromString('a serialized db string')` replaces the current db
178-
-`client.dbToDatoms()` returns an array of all the facts aka datoms saved in the db
179-
- datoms are the smallest unit of data in the database, like a key value pair but better
180-
- they are arrays of`[entityId, attribute, value, transactionId, isAddedBoolean]`
181-
-`client.addTransactListener((changedDatoms) => ...)` adds a listener function to all transactions
182-
- use this to save data to your backend
183-
-`client.removeTransactListener()` removes the transaction listener
184-
- please note that only 1 listener can be added per useClient scope
185-
-`client.transactSilently([{item: {name: ...}}])` like`transact()` only it will not trigger any listeners
186-
- use this to sync data from your backend into the client
176+
-`client.dbToString()` serializes the whole db including the lookupHelpers to a string.
177+
-`client.dbFromString('a serialized db string')` replaces the current db.
178+
-`client.dbToDatoms()` returns an array of all the facts aka datoms saved in the db.
179+
- Datoms are the smallest unit of data in the database, like a key value pair but better.
180+
- Datoms are arrays of`[entityId, attribute, value, transactionId, isAddedBoolean]`.
181+
-`client.addTransactListener((changedDatoms) => ...)` adds a listener function to all transactions.
182+
- Use this to save data to your backend.
183+
-`client.removeTransactListener()` removes the transaction listener.
184+
- Please note that only 1 listener can be added per useClient scope.
185+
-`client.transactSilently([{item: {name: ...}}])` like`transact()` only it will not trigger any listeners.
186+
- Use this to sync data from your backend into the client.
187+
-`client.entity(id or { thing: { attr: 'unique value' } })` like`useEntity`, but**returns a promise**. Get an entity in a callback or other places where a React hook does not make sense.
188+
- The entity returned by this function**will NOT live update the parent React component** when its data changes. If you want reactive updates we recommend using`useEntity`.
189+
-`client.query({ $find: 'thing', $where: { thing: { name: '$any' } } })` like`useQuery`, but**returns a promise**. Perform a query in a callback or other places where a React hook does not make sense.
190+
- The entities returned by this function**will NOT live update the parent React component** when their data changes. If you want reactive updates we recommend using`useQuery`.
187191

188192
Check out the[Firebase example](https://homebaseio.github.io/homebase-react/#!/example.todo_firebase) for a demonstration of how you might integrate a backend.
189193

‎docs/0400|API.md‎

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,17 +129,21 @@ todos
129129

130130
This hook returns the current database client with some helpful functions for syncing data with a backend.
131131

132-
-`client.dbToString()` serializes the whole db including the lookupHelpers to a string
133-
-`client.dbFromString('a serialized db string')` replaces the current db
134-
-`client.dbToDatoms()` returns an array of all the facts aka datoms saved in the db
135-
- datoms are the smallest unit of data in the database, like a key value pair but better
136-
- they are arrays of`[entityId, attribute, value, transactionId, isAddedBoolean]`
137-
-`client.addTransactListener((changedDatoms) => ...)` adds a listener function to all transactions
138-
- use this to save data to your backend
139-
-`client.removeTransactListener()` removes the transaction listener
140-
- please note that only 1 listener can be added per useClient scope
141-
-`client.transactSilently([{item: {name: ...}}])` like`transact()` only it will not trigger any listeners
142-
- use this to sync data from your backend into the client
132+
-`client.dbToString()` serializes the whole db including the lookupHelpers to a string.
133+
-`client.dbFromString('a serialized db string')` replaces the current db.
134+
-`client.dbToDatoms()` returns an array of all the facts aka datoms saved in the db.
135+
- Datoms are the smallest unit of data in the database, like a key value pair but better.
136+
- Datoms are arrays of`[entityId, attribute, value, transactionId, isAddedBoolean]`.
137+
-`client.addTransactListener((changedDatoms) => ...)` adds a listener function to all transactions.
138+
- Use this to save data to your backend.
139+
-`client.removeTransactListener()` removes the transaction listener.
140+
- Please note that only 1 listener can be added per useClient scope.
141+
-`client.transactSilently([{item: {name: ...}}])` like`transact()` only it will not trigger any listeners.
142+
- Use this to sync data from your backend into the client.
143+
-`client.entity(id or { thing: { attr: 'unique value' } })` like`useEntity`, but**returns a promise**. Get an entity in a callback or other places where a React hook does not make sense.
144+
- The entity returned by this function**will NOT live update the parent React component** when its data changes. If you want reactive updates we recommend using`useEntity`.
145+
-`client.query({ $find: 'thing', $where: { thing: { name: '$any' } } })` like`useQuery`, but**returns a promise**. Perform a query in a callback or other places where a React hook does not make sense.
146+
- The entities returned by this function**will NOT live update the parent React component** when their data changes. If you want reactive updates we recommend using`useQuery`.
143147

144148
Check out the[Firebase example](https://homebaseio.github.io/homebase-react/#!/example.todo_firebase) for a demonstration of how you might integrate a backend.
145149

‎src/homebase/react.cljs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@
150150
(d/transact! conn []::silent))
151151
"dbToDatoms" #(datoms->js (d/datoms @conn:eavt))
152152
;; "dbToJSON" #(clj->js (datoms->json (d/datoms @conn :eavt)))
153+
"entity" (fn [lookup] (js/Promise.resolve (hbjs/entity conn lookup)))
154+
"query" (fn [query & args] (js/Promise.resolve (apply hbjs/q query conn args)))
153155
"transactSilently" (fn [tx] (try-hook"useClient" #(hbjs/transact! conn tx::silent)))
154156
"addTransactListener" (fn [listener-fn] (d/listen! conn key #(when (not=::silent (:tx-meta %))
155157
(listener-fn (datoms->js (:tx-data %))))))

‎src/homebase/react.test.js‎

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
/* eslint-disable react/button-has-type */
22
import'@testing-library/jest-dom/extend-expect'
3-
import{fireEvent,render,screen}from'@testing-library/react'
3+
import{fireEvent,render,screen,waitFor}from'@testing-library/react'
44
import'jest-performance-testing'
55
importReactfrom'react'
6+
import{act}from'react-dom/test-utils'
67
import{perf,wait}from'react-performance-testing'
78
import{
89
HomebaseProvider,
@@ -307,18 +308,44 @@ describe('client', () => {
307308
const[order]=useEntity(1)
308309
// TODO: test client.addTransactListener()
309310
// TODO: test client.removeTransactListener()
311+
312+
const[entityResultState,setEntityResultState]=React.useState()
313+
asyncfunctionrunEntity(){
314+
constentityResult=awaitclient.entity(7)
315+
act(()=>{
316+
setEntityResultState(entityResult.get('name'))
317+
})
318+
}
319+
const[queryResultState,setQueryResultState]=React.useState()
320+
asyncfunctionrunQuery(){
321+
constqueryResult=awaitclient.query({
322+
$find:'item',
323+
$where:{item:{name:'$any'}},
324+
})
325+
act(()=>{
326+
setQueryResultState(queryResult[0].get('name'))
327+
})
328+
}
329+
React.useEffect(()=>{
330+
runQuery()
331+
runEntity()
332+
},[client])
333+
310334
return(
311335
<>
312336
<divdata-testid="client.dbToString()">{client.dbToString()}</div>
313337
<divdata-testid="client.dbToDatoms()">{JSON.stringify(client.dbToDatoms())}</div>
314338
<button
315339
onClick={()=>
316-
client.transactSilently([{order:{id:order.get('id'),name:'order1'}}])}
340+
client.transactSilently([{order:{id:order.get('id'),name:'order1'}}])
341+
}
317342
>
318343
update|order.name
319344
</button>
320345
<divdata-testid="order.name">{order.get('name')}</div>
321346
<buttononClick={()=>client.dbFromString(initialDBString)}>client.dbFromString()</button>
347+
<divdata-testid="client.entity">{entityResultState}</div>
348+
<divdata-testid="client.query">{queryResultState}</div>
322349
</>
323350
)
324351
}
@@ -330,7 +357,7 @@ describe('client', () => {
330357
)
331358

332359
it('useClient',async()=>{
333-
expect.assertions(4)
360+
expect.assertions(7)
334361
render(<ClientApp/>)
335362
expect(screen.getByTestId('client.dbToString()')).toHaveTextContent(initialDBString)
336363
expect(screen.getByTestId('client.dbToDatoms()')).toHaveTextContent(
@@ -340,6 +367,10 @@ describe('client', () => {
340367
expect(screen.getByTestId('order.name')).toHaveTextContent('order1')
341368
fireEvent.click(screen.getByText('client.dbFromString()'))
342369
expect(screen.getByTestId('order.name')).toBeEmptyDOMElement()
370+
awaitwaitFor(()=>{
371+
expect(screen.getByTestId('client.entity')).toHaveTextContent('name lookup')
372+
expect(screen.getByTestId('client.query')).toHaveTextContent('id lookup')
373+
})
343374
})
344375
})
345376

‎types/index.d.ts‎

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,33 @@ export type homebaseClient = {
9595
* Transacts data without triggering any listeners. Typically used to sync data from your backend into the client.
9696
*@param transaction - A database transaction.
9797
*/
98-
transactSilently:(transaction:Transaction)=>any
98+
transactSilently:(transaction:Transaction)=>any,
99+
100+
/**
101+
* Returns a promise that contains a single entity by `lookup`.
102+
*@param lookup - an entity id or lookup object.
103+
*@returns Promise<Entity> - A promise wrapping an entity.
104+
*@example const entity = await client.entity(10)
105+
*@example const entity = await client.entity({ identity: "a unique lookup key" })
106+
*@example
107+
* const project = await client.entity({ project: { name: "a unique name" }})
108+
* project.get('name')
109+
*/
110+
entity:(lookup:object|number)=>Promise<Entity>,
111+
112+
/**
113+
* Returns a promise that contains a collection of entities by `query`.
114+
*@param query - a query object or datalog string.
115+
*@param args - optional query arguments.
116+
*@returns Promise<[Entity]> - A promise wrapping an array of entities.
117+
*@example
118+
* const todos = await client.query({
119+
* $find: 'todo',
120+
* $where: { todo: { name: '$any' }}
121+
* })
122+
* todos.map(todo => todo.get('name'))
123+
*/
124+
query:(query:object|string, ...args:any)=>Promise<[Entity]>
99125
}
100126

101127
/**

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp