git ssb

16+

Dominic / patchbay



Tree: 6dbc799416e7828344ed4ab645ebde51f3ddaea0

Files: 6dbc799416e7828344ed4ab645ebde51f3ddaea0 / app / page / query.js

3265 bytesRaw
1const nest = require('depnest')
2const { h, Value, computed, when } = require('mutant')
3const Scroller = require('mutant-scroll')
4const next = require('pull-next-query')
5const json5 = require('json5')
6
7exports.gives = nest({
8 'app.html.menuItem': true,
9 'app.page.query': true
10})
11
12exports.needs = nest({
13 'app.sync.goTo': 'first',
14 'message.html.render': 'first',
15 'sbot.pull.stream': 'first'
16})
17
18// TODO ?? extract a module patchbay-devtools ?
19exports.create = function (api) {
20 return nest({
21 'app.html.menuItem': menuItem,
22 'app.page.query': queryPage
23 })
24
25 function menuItem () {
26 return h('a', {
27 'ev-click': () => api.app.sync.goTo({ page: 'query' })
28 }, '/query')
29 }
30
31 function queryPage (location) {
32 const input = Value()
33 const error = computed(input, i => {
34 try {
35 var query = json5.parse(i)
36 } catch (err) {
37 // console.error(err)
38 return err
39 }
40 if (isValidQuery(query)) activateQuery()
41 })
42
43 const { initialQuery, initialValue } = getInitialState(location)
44 const query = Value(initialQuery)
45
46 const activateQuery = () => query.set(json5.parse(input()))
47
48 return h('Query', { title: '/query' }, [
49 h('section.query', [
50 h('textarea', { 'ev-input': ev => input.set(ev.target.value), value: initialValue }),
51 h('button', {
52 className: when(error, '', '-primary'),
53 disabled: when(error, 'disabled'),
54 'ev-click': activateQuery
55 }, 'Go!')
56 ]),
57 h('section.output', [
58 computed(query, query => {
59 return Scroller({
60 streamToBottom: source(query),
61 render: msg => h('pre', JSON.stringify(msg, null, 2)),
62 comparer: (a, b) => {
63 if (a && b && a.key && b.key) return a.key === b.key
64 return a === b
65 }
66 })
67 })
68 ])
69 ])
70 }
71
72 function source (query) {
73 const opts = {
74 query,
75 reverse: true,
76 limit: 50
77 }
78
79 return api.sbot.pull.stream(server => {
80 return next(server.query.read, opts, ['value', 'timestamp'])
81 })
82 }
83}
84
85function getInitialState (location) {
86 const { initialQuery, initialValue } = location
87 if (isValidQuery(initialQuery)) {
88 return {
89 initialQuery,
90 initialValue: initialValue || json5.stringify(initialQuery, null, 2)
91 }
92 }
93
94 const defaultValue = `[{
95 $filter: {
96 value: {
97 timestamp: {$gt: 0},
98 content: {
99 type: 'post'
100 }
101 }
102 }
103}, {
104 $map: {
105 author: ['value', 'author'],
106 text: ['value', 'content', 'text'],
107 ts: {
108 received: ['timestamp'],
109 asserted: ['value', 'timestamp']
110 }
111 }
112}]
113
114// $filter - used to prune down results. This must be the first entry, as ssb-query uses it to determine the most optimal index for fast lookup.
115
116// $map - optional, can be used to pluck data you want out. Doing this reduces the amount of data sent over muxrpc, which speeds up loading
117`
118 return {
119 initialQuery: json5.parse(defaultValue),
120 initialValue: defaultValue
121 }
122}
123
124function isValidQuery (query) {
125 if (!Array.isArray(query)) return false
126 if (!query.map(q => Object.keys(q)[0]).every(q => ['$filter', '$map', '$reduce'].includes(q))) return false
127
128 return true
129}
130

Built with git-ssb-web