UNPKG

2.87 kBJavaScriptView Raw
1var errors = require('../errors')
2var filterSafeDeletes = require('../lib/filter_deletes')
3var validateChangeset = require('../lib/validate_changeset')
4var replacePlaceholderIds = require('../lib/replace_ids')
5
6module.exports = function (osm) {
7 return function (changes, id, version, cb) {
8 if (typeof version === 'function') {
9 cb = version
10 version = null
11 }
12 // Check changeset with id, version exists + is valid
13 validateChangeset(osm, id, version, function (err) {
14 if (err) return cb(err)
15 // Check each change in changeset references the same changeset
16 validateChangesetIds(changes, id, function (err) {
17 if (err) return cb(err)
18 // Skip any deletes which would break things, or throw an error
19 // if `if-unused` is not set on input
20 filterSafeDeletes(osm, changes, function (err, filtered) {
21 if (err) return cb(err)
22 // Replace placeholderIds with UUIDs.
23 replacePlaceholderIds(filtered, onProcessed)
24 })
25 })
26 })
27
28 function onProcessed (err, results) {
29 if (err) return cb(err)
30 var byId = {}
31 results.forEach(function (change) {
32 byId[change.id] = change
33 })
34 var batch = results.map(batchMap)
35 osm.batch(batch, function (err, nodes) {
36 if (err) return cb(err)
37 var diffResult = nodes.map(function (node) {
38 var id = node.value.k || node.value.d
39 var change = byId[id]
40 var diff = {
41 type: change.type,
42 old_id: change.old_id || change.id
43 }
44 if (change.action !== 'delete') {
45 diff.new_id = id
46 diff.new_version = node.key
47 }
48 return diff
49 })
50 cb(null, diffResult)
51 })
52 }
53 }
54}
55
56/**
57 * Check that changeset ids in the changes all match the passed id argument
58 */
59function validateChangesetIds (changes, id, cb) {
60 var invalidIds = changes.filter(function (change) {
61 return change.changeset !== id
62 }).map(function (change) {
63 return change.changeset || 'missing'
64 })
65 if (invalidIds.length) {
66 return cb(new errors.ChangesetIdMismatch('#' + invalidIds.join(', #'), '#' + id))
67 }
68 cb()
69}
70
71var SKIP_PROPS = ['action', 'id', 'version', 'ifUnused', 'old_id']
72
73/**
74 * Turn a changeset operation into a osm-p2p-db batch operation
75 */
76function batchMap (change) {
77 var op = {
78 type: change.action === 'delete' ? 'del' : 'put',
79 key: change.id,
80 value: {}
81 }
82 if (change.action === 'create') op.links = []
83 if (change.action !== 'create' && change.version) {
84 op.links = change.version.split(/\s*,\s*/).filter(Boolean)
85 }
86 Object.keys(change).forEach(function (prop) {
87 if (SKIP_PROPS.indexOf(prop) > -1) return
88 op.value[prop === 'nodes' ? 'refs' : prop] = change[prop]
89 })
90 op.value.timestamp = new Date().toISOString()
91 return op
92}