Files: c01134463891ae1d25f93fc89424b752ead934e2 / util.js
4898 bytesRaw
1 | var Map = require('pull-stream/throughs/map') |
2 | |
3 | // opts standardized to work like levelup api |
4 | function stdopts (opts) { |
5 | opts = opts || {} |
6 | opts.keys = opts.keys !== false // default keys to true |
7 | opts.values = opts.values !== false // default values to true |
8 | return opts |
9 | } |
10 | |
11 | function msgFmt (keys, values, obj) { |
12 | if (keys && values) { return obj } |
13 | if (keys) { return obj.key } |
14 | if (values) { return obj.value } |
15 | return null // i guess? |
16 | } |
17 | |
18 | exports.options = stdopts |
19 | exports.format = msgFmt |
20 | |
21 | exports.lo = null |
22 | exports.hi = undefined |
23 | |
24 | exports.wait = function () { |
25 | var waiting = [] |
26 | var value |
27 | return { |
28 | get: function () { return value }, |
29 | set: function (_value) { |
30 | value = _value |
31 | |
32 | var l = waiting.length |
33 | for (var i = 0; i < l; ++i) { waiting[i](null, value) } |
34 | waiting = waiting.slice(l) |
35 | }, |
36 | wait: function (cb) { |
37 | if (value !== undefined) cb(null, value) |
38 | else waiting.push(cb) |
39 | } |
40 | } |
41 | } |
42 | |
43 | /** |
44 | * Remove metadata from a message value and replace it with the original |
45 | * content (if any) found in `value.meta.original`. This also deletes the |
46 | * deprecated `value.private` and such, which still exists for backward-compat. |
47 | * |
48 | * @param {object} data - `value` property from message object |
49 | * |
50 | * @todo Delete unboxer metadata, which exists for backward-compatibility. |
51 | * |
52 | * @returns {object} the original message value, extracted from `value.meta.original` |
53 | */ |
54 | const originalValue = exports.originalValue = function (value) { |
55 | var copy = {} |
56 | |
57 | for (let key in value) { |
58 | if (key !== 'meta' && key !== 'cyphertext' && key !== 'private' && key !== 'unbox') { |
59 | copy[key] = value[key] |
60 | } |
61 | } |
62 | |
63 | if (value.meta && value.meta.original) { |
64 | for (let key in value.meta.original) { |
65 | copy[key] = value.meta.original[key] |
66 | } |
67 | } |
68 | |
69 | return copy |
70 | } |
71 | |
72 | /** |
73 | * Remove metadata from messages and return *only* the original message, ready |
74 | * for replication or cryptographic verification. |
75 | * |
76 | * @param {object} data - message object with `key` and `value` properties |
77 | * |
78 | * @returns {object} the original data, extracted from `data.value.meta.original` |
79 | */ |
80 | var originalData = exports.originalData = function (data) { |
81 | data.value = originalValue(data.value) |
82 | return data |
83 | } |
84 | |
85 | /** |
86 | * Used to make modifications to values during streams, which is dependent on |
87 | * the `isOriginal` param. If `isOriginal` is truthy, then it passes each `msg` |
88 | * to `originalData()` and each `msg.value` to `originalValue()`. |
89 | * |
90 | * Usually `isOriginal` will be falsy, but if you need to hash or replicate the |
91 | * value from the stream then you should make sure that `isOriginal` is set to |
92 | * true. For example, most of the time you want private messages to be unboxed |
93 | * (decrypted), but if you're replicating those values to another peer then |
94 | * it's important to make sure that `isOriginal` is truthy. |
95 | * |
96 | * @param {boolean} keys - whether keys will be passed through the stream |
97 | * @param {boolean} values - whether values will be passed through the stream |
98 | * @param {boolean} isOriginal - whether you want *only* the original data |
99 | * |
100 | * @returns {function} a function that can be used to map over a stream |
101 | */ |
102 | exports.Format = exports.formatStream = function (keys, values, isPrivate) { |
103 | let extract |
104 | |
105 | if (isPrivate === true) { |
106 | extract = data => { |
107 | return keys && values |
108 | ? data.value |
109 | : keys |
110 | ? data.value.key |
111 | : data.value.value |
112 | } |
113 | } else { |
114 | extract = data => { |
115 | return keys && values |
116 | ? originalData(data.value) |
117 | : keys |
118 | ? data.value.key |
119 | : originalValue(data.value.value) |
120 | } |
121 | } |
122 | |
123 | return Map(function (data) { |
124 | if (data.sync) return data |
125 | return extract(data) |
126 | }) |
127 | } |
128 | |
129 | /** |
130 | * Backs up a value from `msg.value` to `msg.value.meta.original` in a simple |
131 | * and idiomatic way. This works regardless of whether `msg.value.meta` exists |
132 | * and should be used any time values are modified with `addMap()`. |
133 | * |
134 | * @param {object} msgValue - the `value` property of a message (usually `msg.value`) |
135 | * @param {string} property - name property that should be backed up |
136 | * |
137 | * @example |
138 | * metaBackup({ type: 'post', content: 'hello world', 'content') |
139 | * // => { meta: { original: { content: 'hello world' } } } |
140 | * |
141 | * @example |
142 | * var msg = { value: { type: 'post', content: 'bar' } } |
143 | * msg.value.meta = metaBackup(msg.value, 'content') |
144 | * msg.value.content = 'foo was here' |
145 | * msg.value.meta.original.content // => 'bar' |
146 | * |
147 | * @return {object} a `meta` object with the property backed up. |
148 | */ |
149 | exports.metaBackup = (msgValue, property) => { |
150 | const original = { [property]: msgValue[property] } |
151 | |
152 | if (!msgValue.meta) { |
153 | msgValue.meta = { original } |
154 | } else if (!msgValue.meta.original) { |
155 | msgValue.meta.original = original |
156 | } else if (!msgValue.meta.original[property]) { |
157 | msgValue.meta.original[property] = original[property] |
158 | } |
159 | |
160 | return msgValue.meta |
161 | } |
162 |
Built with git-ssb-web