UNPKG

osm-p2p-server

Version:

Peer-to-peer OpenStreetMap API v0.6 Server

115 lines (103 loc) 2.92 kB
var collect = require('collect-stream') var pumpify = require('pumpify') var mapStream = require('through2-map') var collectTransform = require('collect-transform-stream') var defork = require('osm-p2p-defork') var through = require('through2') var checkRefExist = require('../lib/check_ref_ex.js') module.exports = function (osm) { return function getMap (bbox, opts, cb) { if (typeof opts === 'function') { cb = opts opts = {} } opts.observations = true opts.forks = opts.forks || false opts.order = 'type' // For now, filter deletions (until downstream can handle them). // // This also involves removing references to deleted nodes from ways (iD // handles this poorly). This relies on the reordering step. var nodesSeen = {} var deletionFilter = through.obj(function (chunk, enc, next) { if (!chunk.deleted) { if (chunk && chunk.type === 'node') { nodesSeen[chunk.id] = true } else if (chunk && chunk.type === 'way') { chunk.refs = (chunk.refs || []).filter(function (id) { return !!nodesSeen[id] }) } } if (!chunk.deleted) next(null, chunk) else next() }) var pipeline = [ osm.queryStream ? osm.queryStream(bbox, opts) : osm.query(bbox, opts), orderByType(), deletionFilter, checkRefExist(osm), mapStream.obj(refs2nodes) ] // If forks ought to be filtered out, add another step to the pipeline that // does so. if (!opts.forks) { pipeline.push(deforkStream()) } var queryStreamJson = pumpify.obj.apply(this, pipeline) if (cb) { collect(queryStreamJson, function (err, elements) { if (err) return cb(err) cb(null, elements) }) } else { return queryStreamJson } } } function deforkStream () { return collectTransform(function (res) { return defork(res).sort(cmpType) }) } var typeOrder = { node: 0, way: 1, relation: 2 } function cmpType (a, b) { return typeOrder[a.type] - typeOrder[b.type] } function orderByType () { var queue = { ways: [], relations: [] } return through.obj(write, end) function write (chunk, enc, next) { if (chunk && chunk && chunk.type === 'way') { queue.ways.push(chunk) next() } else if (chunk && chunk.type === 'relation') { queue.relations.push(chunk) next() } else { next(null, chunk) } } function end (next) { var self = this queue.ways.forEach(function (way) { self.push(way) }) queue.relations.forEach(function (rel) { self.push(rel) }) next() } } function refs2nodes (doc) { var element = { id: doc.id } for (var prop in doc) { if (!doc.hasOwnProperty(prop)) continue if (prop === 'refs') { element.nodes = doc.refs } else { element[prop] = doc[prop] } } return element }