git ssb

16+

Dominic / patchbay



Tree: 885b7de1caf8644fe426d6f49b82f1f738f9b3bf

Files: 885b7de1caf8644fe426d6f49b82f1f738f9b3bf / app / page / query.js

3292 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 style: { order: 1 },
28 'ev-click': () => api.app.sync.goTo({ page: 'query' })
29 }, '/query')
30 }
31
32 function queryPage (location) {
33 const input = Value()
34 const error = computed(input, i => {
35 try {
36 var query = json5.parse(i)
37 } catch (err) {
38 // console.error(err)
39 return err
40 }
41 if (isValidQuery(query)) activateQuery()
42 })
43
44 const { initialQuery, initialValue } = getInitialState(location)
45 const query = Value(initialQuery)
46
47 const activateQuery = () => query.set(json5.parse(input()))
48
49 return h('Query', { title: '/query' }, [
50 h('section.query', [
51 h('textarea', { 'ev-input': ev => input.set(ev.target.value), value: initialValue }),
52 h('button', {
53 className: when(error, '', '-primary'),
54 disabled: when(error, 'disabled'),
55 'ev-click': activateQuery
56 }, 'Go!')
57 ]),
58 h('section.output', [
59 computed(query, query => {
60 return Scroller({
61 streamToBottom: source(query),
62 render: msg => h('pre', JSON.stringify(msg, null, 2)),
63 comparer: (a, b) => {
64 if (a && b && a.key && b.key) return a.key === b.key
65 return a === b
66 }
67 })
68 })
69 ])
70 ])
71 }
72
73 function source (query) {
74 const opts = {
75 query,
76 reverse: true,
77 limit: 50
78 }
79
80 return api.sbot.pull.stream(server => {
81 return next(server.query.read, opts, ['value', 'timestamp'])
82 })
83 }
84}
85
86function getInitialState (location) {
87 const { initialQuery, initialValue } = location
88 if (isValidQuery(initialQuery)) {
89 return {
90 initialQuery,
91 initialValue: initialValue || json5.stringify(initialQuery, null, 2)
92 }
93 }
94
95 const defaultValue = `[{
96 $filter: {
97 value: {
98 timestamp: {$gt: 0},
99 content: {
100 type: 'post'
101 }
102 }
103 }
104}, {
105 $map: {
106 author: ['value', 'author'],
107 text: ['value', 'content', 'text'],
108 ts: {
109 received: ['timestamp'],
110 asserted: ['value', 'timestamp']
111 }
112 }
113}]
114
115// $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.
116
117// $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
118`
119 return {
120 initialQuery: json5.parse(defaultValue),
121 initialValue: defaultValue
122 }
123}
124
125function isValidQuery (query) {
126 if (!Array.isArray(query)) return false
127 if (!query.map(q => Object.keys(q)[0]).every(q => ['$filter', '$map', '$reduce'].includes(q))) return false
128
129 return true
130}
131

Built with git-ssb-web