Files: 19874c0c0d66afbcbbf49555bb33b9b4de8909e4 / poll / async / get.js
2699 bytesRaw
1 | const pull = require('pull-stream') |
2 | const sort = require('ssb-sort') |
3 | const { isPoll, isPosition, isChooseOnePoll, isChooseOnePosition } = require('ssb-poll-schema') |
4 | isPoll.chooseOne = isChooseOnePoll |
5 | isPosition.chooseOne = isChooseOnePosition |
6 | const { ERROR_POSITION_TYPE } = require('../../types') |
7 | const getResults = require('../../position/sync/chooseOneResults') |
8 | const getMsgContent = require('../../lib/getMsgContent') |
9 | |
10 | module.exports = function (server) { |
11 | return function get (key, cb) { |
12 | server.get(key, (err, value) => { |
13 | if (err) return cb(err) |
14 | |
15 | var poll = { key, value } |
16 | if (!isPoll(poll)) return cb(new Error('scuttle-poll could not fetch, key provided was not a valid poll key')) |
17 | |
18 | pull( |
19 | createBacklinkStream(key), |
20 | pull.collect((err, msgs) => { |
21 | if (err) return cb(err) |
22 | |
23 | cb(null, decoratedPoll(poll, msgs)) |
24 | }) |
25 | ) |
26 | }) |
27 | } |
28 | |
29 | function createBacklinkStream (key) { |
30 | var filterQuery = { |
31 | $filter: { |
32 | dest: key |
33 | } |
34 | } |
35 | |
36 | return server.backlinks.read({ |
37 | query: [filterQuery], |
38 | index: 'DTA' // use asserted timestamps |
39 | }) |
40 | } |
41 | } |
42 | |
43 | function decoratedPoll (rawPoll, msgs = []) { |
44 | const { |
45 | author, |
46 | content: { |
47 | title, |
48 | body, |
49 | details: { type } |
50 | } |
51 | } = rawPoll.value |
52 | |
53 | const poll = Object.assign({}, rawPoll, { |
54 | type, |
55 | author, |
56 | title, |
57 | body, |
58 | |
59 | positions: [], |
60 | results: {}, |
61 | errors: [] |
62 | |
63 | // publishPosition: TODO ? add pre-filled helper functions to the poll? |
64 | }) |
65 | |
66 | // TODO add missingContext warnings to each msg |
67 | msgs = sort(msgs) |
68 | |
69 | poll.positions = msgs |
70 | .filter(msg => msg.value.content.root === poll.key) |
71 | .filter(isPosition[type]) |
72 | .map(position => { |
73 | return decoratePosition({position, poll}) |
74 | }) |
75 | |
76 | poll.errors = msgs |
77 | .filter(msg => msg.value.content.root === poll.key) |
78 | .filter(msg => isPosition(msg) && !isPosition[type](msg)) |
79 | .map(position => { |
80 | return { |
81 | type: ERROR_POSITION_TYPE, |
82 | message: `Position responses need to be off the ${type} type for this poll`, |
83 | position |
84 | } |
85 | }) |
86 | |
87 | const {results, errors} = getResults({ poll, positions: poll.positions }) |
88 | poll.results = results |
89 | poll.errors = poll.errors.concat(errors) |
90 | |
91 | return poll |
92 | } |
93 | |
94 | function decoratePosition ({position: rawPosition, poll: rawPoll}) { |
95 | var position = getMsgContent(rawPosition) |
96 | var poll = getMsgContent(rawPoll) |
97 | |
98 | // NOTE this isn't deep enough to be a safe clone |
99 | var newPosition = Object.assign({}, rawPosition) |
100 | |
101 | if (isPoll.chooseOne(poll)) { |
102 | var choiceIndex = position.details.choice |
103 | newPosition.choice = poll.details.choices[choiceIndex] |
104 | } |
105 | return newPosition |
106 | } |
107 |
Built with git-ssb-web