UNPKG

@graffy/client

Version:

Graffy client library for the browser.

86 lines (80 loc) 2.41 kB
import { encodeUrl, serialize, deserialize, makePath } from '@graffy/common'; import { makeStream } from '@graffy/stream'; function getOptionsParam(options) { if (!options) return ''; return encodeURIComponent(serialize(options)); } export default ((baseUrl, { getOptions = () => {}, watch, connInfoPath = '/connection' } = {}) => store => { connInfoPath = makePath(connInfoPath); store.onWrite(connInfoPath, ({ url }) => { baseUrl = url; return { url }; }); store.onRead(connInfoPath, () => ({ url: baseUrl })); store.on('read', (query, options) => { if (!fetch) throw Error('client.fetch.unavailable'); const optionsParam = getOptionsParam(getOptions('read', options)); const url = baseUrl + "?q=" + encodeUrl(query) + "&opts=" + optionsParam; return fetch(url).then(res => { if (res.status === 200) return res.json(); return res.text().then(message => { throw Error('server.' + message); }); }); }); store.on('watch', (query, options) => { if (watch === 'none') throw Error('client.no_watch'); if (watch === 'hang') { return makeStream(push => { push(undefined); }); } if (!EventSource) throw Error('client.sse.unavailable'); const optionsParam = getOptionsParam(getOptions('watch', options)); const url = baseUrl + "?q=" + encodeUrl(query) + "&opts=" + optionsParam; const source = new EventSource(url); return makeStream((push, end) => { source.onmessage = ({ data }) => { push(deserialize(data)); }; source.onerror = e => { end(Error('client.sse.transport: ' + e.message)); }; source.addEventListener('graffyerror', e => { end(Error('server.' + e.data)); }); return () => { source.close(); }; }); }); store.on('write', (change, options) => { if (!fetch) throw Error('client.fetch.unavailable'); const optionsParam = getOptionsParam(getOptions('write', options)); const url = baseUrl + "?opts=" + optionsParam; return fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: serialize(change) }).then(res => { if (res.status === 200) return res.json(); return res.text().then(message => { throw Error('server.' + message); }); }); }); });