Link Search Menu Expand Document


To add some sort of backend to your Stores you can make use of fritz2’s repositories. fritz2 offers implementations of the repository-interfaces for several types of backends:

  • LocalStorage
  • REST
  • more like WebSockets, GraphQL etc. soon to be added


Working with repositories requires the definition of a Resource first:

val personResource = Resource(
    Person::_id, // function to extract the unique id from a given instance
    KotlinXJsonSerializer(Person.serializer()), // implementation of Serializer interface to write and read the entity
    Person() // definition of an empty entity (to reset an edit form, e.g.)


We differentiate two kinds of repositories:

  • an EntityRepository deals with one single entity of a given type. It offers the usual CRUD-methods:
    • load(entity, id)
    • saveOrUpdate(entity)
    • delete(entity)
  • a QueryRepository deals with a List of instances of a given type. It offers the following methods to query or manipulate the content of the repository:
    • query(entities, query)
    • addOrUpdate(entities, entity)
    • updateMany(entities, entitiesToUpdate)
    • delete(entities, id(s))


To connect a Store with a REST-backend for example, just add the repository-service and use its methods in your handler:

// use the defined resource from above
val entityStore = object : RootStore<Person>(personResource.emptyEntity) {

    private val rest = restEntity(personResource, "https://your_url")

    val load = handle<String> { person, id ->
        rest.load(person, id)

    val saveOrUpdate = handle { rest.saveOrUpdate(it) }

    val delete = handle { rest.delete(it) }
    init {

syncBy automatically calls the given Handler on each update of your Store.


When creating a QueryRepository you can define a type describing the queries done by this repository and a function how to execute the query defined by a given instance of this query-type.

data class PersonQuery(val namePrefix: String? = null)

val queryStore = object : RootStore<List<Person>>(emptyList()) {
    val rest = localStorageQuery<Person, String, PersonQuery>(personResource, "your prefix") { entities, query ->
        if (query.namePrefix != null) entities.filter { }   
        else entities

    val query = handle(execute = rest::query)
    val delete = handle<String>(execute = rest::delete)

    init {
        action(PersonQuery()) handledBy query

Of course the receiver and result of this function depend on the concrete implementation you use. For a RestQuery you have to build and fire the request according to your query-object:

val queryStore = restQuery<Person, String, PersonQuery>(personResource, "your url") { query ->
    get(query.namePrefix?.let {"?name=$it"}.orEmpty())

If you do not specify a function all entities of the defined Resource will be returned.


You can see repositories of all types in action at

Distributed by an MIT license.