npm package: @jsonql/client
Description: jsonql js http and socket client for browser with multiple API for different framework
Author: Joel Chu
Latest version: 0.4.0

# @jsonql/client

> This is jsonql browser client comes with jsonql-client (http) and optional socket clients, plus various modules for ui frameworks

## Basic Example

Stock http client

```js
import jsonqlClient from '@jsonql/client'
import Fly from 'flyio'
const config = {} // your configuration options

jsonqlClient(config)
  .then(client => {
    // start to do your thing
  })
```


Using the static client with pre-generated contract (works better with Third party JS frameworks)

```js
import { jsonqlStaticClient } from '@jsonql/client/static'
import contract from 'path/to/your/public-contract.json'
import Fly from 'flyio' // or specific client to your need

const client = jsonqlStaticClient(Fly, { contract })

client.query.helloWorld()
  .then(msg => {
    // you get Hello world!
  })
```

## Third party JS Framework modules

We have developed several modules to integrate with some of the third party JS frameworks.

### Vuex module

[Vuex](https://vuex.vuejs.org) store support was add in version 1.5.19

First create a new Vuex store file (let say call it `jsonql.js`)

```js
import contract from 'path/to/your/public-contract.json'
import { jsonqlVuex } from '@jsonql/client/vue'
import Fly from 'flyio'

const jsonqlVuexModule = jsonqlVuex(Fly, { contract })

export { jsonqlVuexModule }
```

Now in your `store.js` where you define your Vuex store

```js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

import { jsonqlVuexModule } from './jsonql'

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {
    jsonqlVuexModule
  }
})
```

This Vuex module is namespaced. In your component

```html
<template>
  <div>
    {{hello}}
  </div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
  name: 'test',
  computed: {
    hello() {
      return this.getJsonqlResult('helloWorld')
    }
  }
  actions: {
    ...mapActions('jsonqlVuexModule', ['helloWorld'])
  },
  getters: {
    ...mapGetters('jsonqlVuexModule', ['getJsonqlResult'])
  }
}
</script>
```


### Prefix your resolver with their type

There is a little different between our core jsonql client and in the above module. Normally, the client will namespaced each
methods under their type:

```js
jsonql()
  .then(client => {
    // query
    client.query.helloWorld()
    // mutation
    client.mutation.updateSomething()
    // auth
    client.auth.login()
    // etc
  })

```

We try to be compatible with the Vuex (or most of the js state machine) style, we remove the namespace, and just construct
the resolver under the client, there is one little potential danger, when you don't name each of your resolver with a unique name.
But again this is an edge case, I don't think anyone in their right mind will have a `query.login`, `auth.login` at the same time?

But when you find yourself in this situation. You can use the `prefix` option.

```js
import contract from 'path/to/your/public-contract.json'
import { jsonqlVuex } from '@jsonql/client/vue'
import Fly from 'flyio'
// here we pass the prefix: true option
const jsonqlVuexModule = jsonqlVuex(Fly, { contract, prefix: true })

export { jsonqlVuexModule }

```

Then it will turn `query.helloWorld` into `queryHelloWorld`.

```html
<template>
  <div>
    {{hello}}
  </div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
export default {
  name: 'test',
  computed: {
    ...mapGetters('jsonqlVuexModule', ['getJsonqlResult']),
    hello() {
      return this.getJsonqlResult('queryHelloWorld')
    }
  },
  actions: {
    ...mapActions('jsonqlVuexModule', ['queryHelloWorld'])
  }
}
</script>
```

If you need this option, then remember, everything will prefix with their `resolver type` name, in camel case.

### Vuex getter: getJsonqlResult

You should notice there is a *Vuex getter* method call `getJsonqlResult`, and you pass the resolver name (with prefix if you use `prefix:true` option). Then you will get back the last resolver call result via this *getter*.

The reason is in the Vuex model, after the call to resolver, we store (*commit*) the result in our internal `result` state, and key with the resolver name. And whenever a new result return, it will get overwritten, because it's a flat object.

Of course, you can simply call the actions, and wait for the promise to resolve. You will get the same effect. For example:

```js
<template>
  <div>
    {{hello}}
  </div>
</template>
<script>
// do your import vuex etc
export default {
  data() {
    hello: 'waiting ...'
  }
  created() {
    this.helloWorld()
      .then(result => {
        this.hello = result
      })
  },
  methods() {
    ...mapActions('jsonqlVuexModule', ['helloWorld'])
  }
}

</script>

```

### Vuex getter: getJsonqlError

Whenever an error happens, we do the same like success result, we commit to our internal `error` state, and you can use this *getter* to get it.
And after we commit, we will throw it again which wrap in a generic `Error`. So you can also catch it again. For example:

```js
<template>
  <div>
    <p>{{hello}}</p>
    <span class="error">{{error}}</span>
  </div>
</template>
<script>
// do your import vuex etc
export default {
  data() {
    hello: 'waiting ...'
  }
  created() {
    this.helloWorld()
      .then(result => {
        this.hello = result
      })
  },
  computed: {
    ...mapGetters('jsonqlVuexModule', ['getJsonqlError']),
    error() {
      return this.getJsonqlError('helloWorld')
    }
  }
  methods() {
    ...mapActions('jsonqlVuexModule', ['helloWorld'])
  }
}
</script>

```

This *getter* is literally identical to `getJsonqlResult`.

---

https://jsonql.org

NEWBRAN LTD UK &amp; T01SOURCE CN