1 | var errors = require('../errors')
|
2 | var filterSafeDeletes = require('../lib/filter_deletes')
|
3 | var validateChangeset = require('../lib/validate_changeset')
|
4 | var replacePlaceholderIds = require('../lib/replace_ids')
|
5 |
|
6 | module.exports = function (osm) {
|
7 | return function (changes, id, version, cb) {
|
8 | if (typeof version === 'function') {
|
9 | cb = version
|
10 | version = null
|
11 | }
|
12 |
|
13 | validateChangeset(osm, id, version, function (err) {
|
14 | if (err) return cb(err)
|
15 |
|
16 | validateChangesetIds(changes, id, function (err) {
|
17 | if (err) return cb(err)
|
18 |
|
19 |
|
20 | filterSafeDeletes(osm, changes, function (err, filtered) {
|
21 | if (err) return cb(err)
|
22 |
|
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 |
|
58 |
|
59 | function 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 |
|
71 | var SKIP_PROPS = ['action', 'id', 'version', 'ifUnused', 'old_id']
|
72 |
|
73 |
|
74 |
|
75 |
|
76 | function batchMap (change) {
|
77 | var op = {
|
78 | type: change.action === 'delete' ? 'del' : 'put',
|
79 | key: change.id,
|
80 | value: {}
|
81 | }
|
82 | if (change.action !== 'create' && change.version) {
|
83 | op.links = change.version.split(/\s*,\s*/).filter(Boolean)
|
84 | }
|
85 | Object.keys(change).forEach(function (prop) {
|
86 | if (SKIP_PROPS.indexOf(prop) > -1) return
|
87 | op.value[prop === 'nodes' ? 'refs' : prop] = change[prop]
|
88 | })
|
89 | op.value.timestamp = new Date().toISOString()
|
90 | return op
|
91 | }
|