Files: bec17d46ac063b6ba69d0a03459259f406307a93 / modules_basic / names.js
3891 bytesRaw
1 | var pull = require('pull-stream') |
2 | var many = require('pull-many') |
3 | var mfr = require('map-filter-reduce') |
4 | |
5 | function all(stream, cb) { |
6 | pull(stream, pull.collect(cb)) |
7 | } |
8 | |
9 | //var plugs = require('../plugs') |
10 | //var sbot_links2 = plugs.first(exports.sbot_links2 = []) |
11 | //var sbot_query = plugs.first(exports.sbot_query = []) |
12 | // |
13 | exports.needs = { |
14 | sbot_links2: 'first', |
15 | sbot_query: 'first' |
16 | } |
17 | |
18 | exports.gives = { |
19 | connection_status: true, |
20 | signifier: true, |
21 | signified: true, |
22 | } |
23 | |
24 | /* |
25 | filter(rel: ['mentions', prefix('@')]) | reduce(name: rel[1], value: count()) |
26 | */ |
27 | |
28 | var filter = { |
29 | $filter: { |
30 | rel: ["mentions", {$prefix: "@"}] |
31 | } |
32 | } |
33 | var map = { |
34 | $map: { |
35 | name: ['rel', 1], |
36 | id: 'dest', |
37 | ts: 'ts', |
38 | } |
39 | } |
40 | |
41 | var reduce = { |
42 | $reduce: { |
43 | name: 'name', |
44 | id: 'id', |
45 | rank: {$count: true}, |
46 | ts: {$max: 'ts'} |
47 | } |
48 | } |
49 | |
50 | var filter2 = { |
51 | $filter: { |
52 | value: { |
53 | content: { |
54 | type: "about", |
55 | name: {"$prefix": ""}, |
56 | about: {"$prefix": ""} |
57 | } |
58 | } |
59 | } |
60 | } |
61 | |
62 | var map2 = { |
63 | $map: { |
64 | name: ["value", "content", "name"], |
65 | id: ['value', 'content', 'about'], |
66 | ts: "timestamp" |
67 | } |
68 | } |
69 | |
70 | //union with this query... |
71 | |
72 | var names = NAMES = [] |
73 | function update(name) { |
74 | var n = names.find(function (e) { |
75 | return e.id == name.id && e.name == e.name |
76 | }) |
77 | if(!n) { |
78 | name.rank = 1 |
79 | //this should be inserted at the right place... |
80 | names.push(name) |
81 | } |
82 | else |
83 | n.rank = n.rank += (name.rank || 1) |
84 | } |
85 | |
86 | var ready = false, waiting = [] |
87 | |
88 | var merge = { |
89 | $reduce: { |
90 | name: 'name', |
91 | id: 'id', |
92 | rank: {$sum: 'rank'}, |
93 | ts: {$max: 'ts'} |
94 | } |
95 | } |
96 | |
97 | function add_sigil(stream) { |
98 | return pull(stream, pull.map(function (e) { |
99 | if (e && e.id && e.name && e.id[0] !== e.name[0]) |
100 | e.name = e.id[0] + e.name |
101 | return e |
102 | }) |
103 | ) |
104 | } |
105 | |
106 | var queryNamedGitRepos = [ |
107 | {$filter: { |
108 | value: { |
109 | content: { |
110 | type: "git-repo", |
111 | name: {"$prefix": ""} |
112 | } |
113 | } |
114 | }}, |
115 | {$map: { |
116 | name: ["value", "content", "name"], |
117 | id: ['key'], |
118 | ts: "timestamp" |
119 | }}, |
120 | reduce |
121 | ] |
122 | exports.create = function (api) { |
123 | |
124 | var exports = {} |
125 | exports.connection_status = function (err) { |
126 | if(!err) { |
127 | pull( |
128 | many([ |
129 | api.sbot_links2({query: [filter, map, reduce]}), |
130 | add_sigil(api.sbot_query({query: [filter2, map2, reduce]})), |
131 | add_sigil(api.sbot_query({query: queryNamedGitRepos})) |
132 | ]), |
133 | //reducing also ensures order by the lookup properties |
134 | //in this case: [name, id] |
135 | mfr.reduce(merge), |
136 | pull.collect(function (err, ary) { |
137 | if(!err) { |
138 | NAMES = names = ary |
139 | ready = true |
140 | while(waiting.length) waiting.shift()() |
141 | } |
142 | }) |
143 | ) |
144 | |
145 | pull(many([ |
146 | api.sbot_links2({query: [filter, map], old: false}), |
147 | add_sigil(api.sbot_query({query: [filter2, map2], old: false})), |
148 | add_sigil(api.sbot_query({query: queryNamedGitRepos, old: false})) |
149 | ]), |
150 | pull.drain(update)) |
151 | } |
152 | } |
153 | |
154 | function async(fn) { |
155 | return function (value, cb) { |
156 | function go () { cb(null, fn(value)) } |
157 | if(ready) go() |
158 | else waiting.push(go) |
159 | } |
160 | } |
161 | |
162 | function rank(ary) { |
163 | //sort by most used, or most recently used |
164 | return ary.sort(function (a, b) { return b.rank - a.rank || b.ts - a.ts }) |
165 | } |
166 | |
167 | //we are just iterating over the entire array. |
168 | //if this becomes a problem, maintain two arrays |
169 | //one of each sort order, but do not duplicate the objects. |
170 | //that should mean the space required is just 2x object references, |
171 | //not 2x objects, and we can use binary search to find matches. |
172 | |
173 | exports.signifier = async(function (id) { |
174 | return rank(names.filter(function (e) { return e.id == id})) |
175 | }) |
176 | |
177 | exports.signified = async(function (name) { |
178 | var rx = new RegExp('^'+name) |
179 | return rank(names.filter(function (e) { return rx.test(e.name) })) |
180 | }) |
181 | |
182 | return exports |
183 | } |
184 |
Built with git-ssb-web