cozy-client
is the sdk to interact with the cozy stack from a Javascript application. It aims at hiding all low level details and providing a simple high level API to fetch and cache documents.
Main features:
- Authentication with a Cozy
- Querying and caching documents
- Transparent relations between couchdb documents
- Updates metadata in couch documents
- Offline: any data can be stored in a local PouchDB that is persisted across page loads
- React integration to connect your components to remote data
Additional features with plugins:
- Realtime: Be notified when changes occur on the server side
- InterApp: Interact with other apps (example : file picking within your app)
- Flag: Use feature flags
The following guide is an overview of a cozy-client integration to help you to get started.
npm install --save cozy-client
# or yarn add cozy-client
import CozyClient from 'cozy-client'
const schema = {
todos: {
doctype: 'io.cozy.todos',
attributes: {...},
relationships: {...}
}
}
const client = new CozyClient({
uri: 'http://cozy.tools:8080',
schema,
token: '...'
})
Usually, the token and URI are provided by the stack on the DOM node <div role="application">
.
When using this, you can instantiate a client with:
const client = CozyClient.fromDOM({
schema
}) // Note how token and uri are not passed, instead they are taken from the DOM
If you need guidance to get the URI of your instance and/or the token, see the app tutorial.
Every doctype accessed in cozy-client
needs to be declared in the schema section of the options.
See how to use the schema features
To fetch data, we first build a QueryDefinition
with the Q
helper:
import { Q } from 'cozy-client'
const allTodosQuery = Q('io.cozy.todos')
const singleTodoQuery = Q('io.cozy.todos').getById('5fcbbf2cb171b1d5c3bc6df3d4affb32')
QueryDefinition
s describe which documents to be fetched from CouchDB. It uses a fluent interface:
Q('io.cozy.todos')
.select(['title', 'checked'])
.where({checked: false})
.include(['dependencies'])
.sortBy([{'cozyMetadata.updatedAt': 'desc'}])
.limitBy(20)
select()
lists the fields you want in the response (all by default)where()
allows a mango selectorinclude()
will cause the query to fetch the related documents (see relationships)sortBy
sorts the documents by theirupdatedAt
metadata in descending orderlimitBy
limits the number of results to 20
By default, all fields in the where()
are automatically indexed. You can turn off this behavior by specifying
explicitly the list of fields to be indexed in indexFields()
.
Finally, client.query()
will execute your query and return a promise with a data
attribute containing the requested documents.
import CozyClient from 'cozy-client'
const client = new CozyClient({
/*...*/
})
const { data } = await client.query(Q('io.cozy.todos').where({ checked: false }))
console.log(data)
✅ Inside a React application, instead of using directly client.query
, please use useQuery
, <Query />
or queryConnect
to connect your components to cozy-client queries.
ℹ️ Check out our dedicated query documentation to know more about querying with cozy-client and avoid common traps that can dramatically impact your app performances.
🚀 Cozy-client's devtools allows to monitor your queries data and performance.
An instance of CozyClient
allows you to query and mutate (update) data, here's how it looks:
import CozyClient from 'cozy-client'
const client = new CozyClient({
/*...*/
})
// create a new io.cozy.todo
await client.save({_type: 'io.cozy.todos', label: 'Buy bread', checked: false })
const qdef = Q('io.cozy.todos').where({ checked: false })
const { data: todos } = await client.query(qdef)
const doc = todos[0]
// modify existing io.cozy.todo (will make an update if _rev is present inside the doc)
await client.save({...doc, checked: true})
save()
will return a Promise with a data
attribute containing the saved document.
ℹ️ When mutating data, queries that depend on the mutated document(s) will automatically be refreshed: components that depend on these queries will be re-rendered.
The saveAll()
method can be used to save multiple documents in one request.
const { data: updatedDocs } = await client.saveAll([
{ _type: 'io.cozy.todos', checked: true, label: 'Buy milk' },
{ _type: 'io.cozy.todos', checked: false, label: 'Make dinner' }
])