From a22d60a16e0271e03d6d07b8c17a9fd9fce382f6 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 2 Apr 2017 21:31:46 -0400 Subject: [PATCH 1/3] Add support for getAsync(opts) Allows arbitrary parameters for the tilelive's getTile/Grid/Info interface As discussed in https://github.com/mapbox/tilelive/issues/189 --- backend.js | 127 ++++++++++++++++++++++++++++++++++++--------------- package.json | 6 ++- 2 files changed, 94 insertions(+), 39 deletions(-) diff --git a/backend.js b/backend.js index f7e42da..bb2d7fb 100644 --- a/backend.js +++ b/backend.js @@ -3,6 +3,7 @@ var crypto = require('crypto'); var mapnik = require('mapnik'); var util = require('util'); var sm = new (require('sphericalmercator'))(); +var uptile = require('tilelive-promise'); module.exports = Backend; @@ -35,64 +36,114 @@ function Backend(opts, callback) { backend._fillzoom = 'fillzoom' in info && !isNaN(parseInt(info.fillzoom, 10)) ? parseInt(info.fillzoom, 10) : undefined; - backend._source = source; + backend._source = uptile(source); if (callback) callback(null, backend); } }; +Backend.prototype.getAsync = function(opts) { + let self = this; + return new Promise((accept, reject) => { + try { + if (!self._source) { + throw new Error('Tilesource not loaded'); + } + let result; + switch (opts.type) { + case undefined: + case 'tile': + result = _getTile.call(self, opts); + break; + default: + result = self._source.getAsync(opts); + break; + } + accept(result); + } catch (err) { + reject(err); + } + }); +}; + Backend.prototype.getInfo = function(callback) { - if (!this._source) return callback(new Error('Tilesource not loaded')); - this._source.getInfo(callback); + this.getAsync({type: 'info'}).then(res => { + callback(undefined, res.info); + }, err => { + callback(err); + }); }; -// Wrapper around backend.getTile that implements a "locking" cache. +// handle additional parameters attached to callback Backend.prototype.getTile = function(z, x, y, callback) { - if (!this._source) return callback(new Error('Tilesource not loaded')); + this.getAsync({ + z: z, + x: x, + y: y, + legacy: callback.legacy, + scale: callback.scale, + upgrade: callback.upgrade, + setSrcData: callback.setSrcData + }).then(res => { + callback(undefined, res.tile, res.headers); + }, err => { + callback(err); + }); +}; + +// Wrapper around backend.getTile that implements a "locking" cache. +function _getTile(opts) { + var backend = this; + + return new Promise((accept, reject) => { + var z = opts.z, x = opts.x, y = opts.y; if (z < 0 || x < 0 || y < 0 || x >= Math.pow(2,z) || y >= Math.pow(2,z)) { - return callback(new Error('Tile does not exist')); + return reject(new Error('Tile does not exist')); } - var backend = this; var source = backend._source; var now = +new Date; - var legacy = callback.legacy || false; - var scale = callback.scale || backend._scale; - var upgrade = callback.upgrade || false; + var legacy = opts.legacy || false; + var scale = opts.scale || backend._scale; + var upgrade = opts.upgrade || false; // If scale > 1 adjusts source data zoom level inversely. // scale 2x => z-1, scale 4x => z-2, scale 8x => z-3, etc. if (legacy && z >= backend._minzoom) { var d = Math.round(Math.log(scale)/Math.log(2)); - var bz = (z - d) > backend._minzoom ? z - d : backend._minzoom; - var bx = Math.floor(x / Math.pow(2, z - bz)); - var by = Math.floor(y / Math.pow(2, z - bz)); + opts.z = (z - d) > backend._minzoom ? z - d : backend._minzoom; + opts.x = Math.floor(x / Math.pow(2, z - opts.z)); + opts.y = Math.floor(y / Math.pow(2, z - opts.z)); } else { - var bz = z | 0; - var bx = x | 0; - var by = y | 0; + opts.z = z | 0; + opts.x = x | 0; + opts.y = y | 0; } var size = 0; var headers = {}; // Overzooming support. - if (bz > backend._maxzoom) { - bz = backend._maxzoom; - bx = Math.floor(x / Math.pow(2, z - bz)); - by = Math.floor(y / Math.pow(2, z - bz)); + if (opts.z > backend._maxzoom) { + opts.z = backend._maxzoom; + opts.x = Math.floor(x / Math.pow(2, z - opts.z)); + opts.y = Math.floor(y / Math.pow(2, z - opts.z)); headers['x-vector-backend-object'] = 'overzoom'; } - source.getTile(bz, bx, by, function sourceGet(err, body, head) { + source.getAsync(opts).catch(function onGetTileError(err) { if (typeof backend._fillzoom === 'number' && err && err.message === 'Tile does not exist' && - bz > backend._fillzoom) { - bz = backend._fillzoom; - bx = Math.floor(x / Math.pow(2, z - bz)); - by = Math.floor(y / Math.pow(2, z - bz)); + opts.z > backend._fillzoom) { + opts.z = backend._fillzoom; + opts.x = Math.floor(x / Math.pow(2, z - opts.z)); + opts.y = Math.floor(y / Math.pow(2, z - opts.z)); headers['x-vector-backend-object'] = 'fillzoom'; - return source.getTile(bz, bx, by, sourceGet); + return source.getAsync(opts).catch(onGetTileError); } - if (err && err.message !== 'Tile does not exist') return callback(err); + if (err.message !== 'Tile does not exist') throw err; + return {}; + }).then(result => { + var body = result.tile; + var head = result.headers; if (body instanceof mapnik.VectorTile) { size = body._srcbytes; @@ -115,7 +166,7 @@ Backend.prototype.getTile = function(z, x, y, callback) { headers = head || {}; return makevtile(body, 'pbf'); // Image sources do not allow overzooming (yet). - } else if (bz < z && headers['x-vector-backend-object'] !== 'fillzoom') { + } else if (opts.z < z && headers['x-vector-backend-object'] !== 'fillzoom') { headers['x-vector-backend-object'] = 'empty'; return makevtile(); } else { @@ -141,34 +192,34 @@ Backend.prototype.getTile = function(z, x, y, callback) { headers['x-vector-backend-object'] = headers['x-vector-backend-object'] || 'default'; // Pass-thru of an upstream mapnik vector tile (not pbf) source. - if (data instanceof mapnik.VectorTile) return callback(null, data, headers); + if (data instanceof mapnik.VectorTile) return accept({tile: data, headers: headers}); - var vtile = new mapnik.VectorTile(bz, bx, by); + var vtile = new mapnik.VectorTile(opts.z, opts.x, opts.y); vtile._srcbytes = size; - if (callback.setSrcData) vtile._srcdata = data; + if (opts.setSrcData) vtile._srcdata = data; // null/zero length data is a solid tile be painted. - if (!data || !data.length) return callback(null, vtile, headers); + if (!data || !data.length) return accept({tile: vtile, headers: headers}); try { if (type === 'pbf') { // We use addData here over setData because we know it was just created // and is empty so skips a clear call internally in mapnik. vtile.addData(data,{upgrade:upgrade},function(err) { - if (err) return callback(err); - return callback(null, vtile, headers); + if (err) return reject(err); + return accept({tile: vtile, headers: headers}); }); } else { vtile.addImageBuffer(data, backend._layer, function(err) { - if (err) return callback(err); - return callback(null, vtile, headers); + if (err) return reject(err); + return accept({tile: vtile, headers: headers}); }); } } catch (err) { - return callback(err); + return reject(err); } }; -}; +})}; // Proxies mapnik vtile.query method with the added convienice of // letting the tilelive-vector backend do the hard work of finding diff --git a/package.json b/package.json index 69426ad..eb7069d 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,9 @@ "type": "BSD" } ], + "contributors": [ + "Yuri Astrakhan " + ], "dependencies": { "aws-sdk": "^2.2.30", "s3urls": "^1.3.0", @@ -23,6 +26,7 @@ "numeral": "~1.5.3", "sphericalmercator": "~1.0.5", "spherical": "~0.1.0", + "tilelive-promise": "^1.0.5", "underscore": "~1.8.0" }, "devDependencies": { @@ -37,4 +41,4 @@ "test": "tape test/*.js", "coverage": "istanbul cover tape test/*.js && coveralls < ./coverage/lcov.info" } -} \ No newline at end of file +} From 678235ae6373522f06536c0ed5179f3724f93aac Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 5 Apr 2017 21:09:09 -0400 Subject: [PATCH 2/3] Added getSync to vector itself --- backend.js | 4 +- index.js | 150 ++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 116 insertions(+), 38 deletions(-) diff --git a/backend.js b/backend.js index bb2d7fb..7196d8a 100644 --- a/backend.js +++ b/backend.js @@ -52,7 +52,7 @@ Backend.prototype.getAsync = function(opts) { switch (opts.type) { case undefined: case 'tile': - result = _getTile.call(self, opts); + result = _getTileAsync.call(self, opts); break; default: result = self._source.getAsync(opts); @@ -91,7 +91,7 @@ Backend.prototype.getTile = function(z, x, y, callback) { }; // Wrapper around backend.getTile that implements a "locking" cache. -function _getTile(opts) { +function _getTileAsync(opts) { var backend = this; return new Promise((accept, reject) => { diff --git a/index.js b/index.js index a827fe3..9d5355d 100644 --- a/index.js +++ b/index.js @@ -122,30 +122,94 @@ Vector.prototype.update = function(opts, callback) { return; }; +Vector.prototype.getAsync = function(opts) { + let self = this; + return new Promise((accept, reject) => { + try { + if (!self._map) { + throw new Error('Tilesource not loaded'); + } + let result; + switch (opts.type) { + case undefined: + case 'tile': + result = _getTileAsync.call(self, opts); + break; + case 'grid': + if (!self._map.parameters.interactivity_layer) { + throw new Error('Tilesource has no interactivity_layer'); + } + if (!self._map.parameters.interactivity_fields) { + throw new Error('Tilesource has no interactivity_fields'); + } + result = _getTileAsync.call(self, opts).then(v => { + // _getTile returns all responses in the "tile" property, rename it to grid + v.grid = v.tile; + delete v.tile; + return v; + }); + break; + case 'info': + result = _getInfoAsync.call(self); + break; + default: + throw new Error(`Unknown type ${opts.type}`); + } + accept(result); + } catch (err) { + reject(err); + } + }); +}; + +function getAsyncParameters(z, x, y, callback) { + return { + z: z, + x: x, + y: y, + format: callback.format, + scale: callback.scale, + profile: callback.profile, + legacy: callback.legacy, + upgrade: callback.upgrade, + renderer: callback.renderer + }; +}; + Vector.prototype.getTile = function(z, x, y, callback) { - if (!this._map) return callback(new Error('Tilesource not loaded')); - if (z < 0 || x < 0 || y < 0 || x >= Math.pow(2,z) || y >= Math.pow(2,z)) { - return callback(new Error('Tile does not exist')); - } // Hack around tilelive API - allow params to be passed per request // as attributes of the callback function. - var format = callback.format || this._format; - var scale = callback.scale || this._scale; - var profile = callback.profile || false; - var legacy = callback.legacy || false; - var upgrade = callback.upgrade || false; + this.getAsync(getAsyncParameters(z, x, y, callback)).then(res => { + callback(undefined, res.tile, res.headers); + }, err => { + callback(err); + }); +}; + +function _getTileAsync(options) { + var source = this; + return new Promise((accept, reject) => { + + var z = options.z, x = options.x, y = options.y; + if (z < 0 || x < 0 || y < 0 || x >= Math.pow(2,z) || y >= Math.pow(2,z)) { + return reject(new Error('Tile does not exist')); + } + var format = options.format || source._format; + var scale = options.scale || source._scale; + var profile = options.profile || false; + var legacy = options.legacy || false; + var upgrade = options.upgrade || false; var width = !legacy ? scale * 256 | 0 || 256 : 256; var height = !legacy ? scale * 256 | 0 || 256 : 256; - var source = this; var drawtime; var loadtime = +new Date; var cb = function(err, vtile, head) { if (err && err.message !== 'Tile does not exist') - return callback(err); + return reject(err); // For xray styles use srcdata tile format. - if (!callback.format && source._xray && vtile._srcdata) { + if (!options.format && source._xray && vtile._srcdata) { var type = tiletype.type(vtile._srcdata); format = type === 'jpg' ? 'jpeg' : type === 'webp' ? 'webp' : @@ -184,22 +248,22 @@ Vector.prototype.getTile = function(z, x, y, callback) { headers['x-vector-backend-object'] = head['x-vector-backend-object']; // Return headers for 'headers' format. - if (format === 'headers') return callback(null, headers, headers); + if (format === 'headers') return accept({tile:headers, headers:headers}); loadtime = (+new Date) - loadtime; drawtime = +new Date; var opts = {z:z, x:x, y:y, scale:scale, buffer_size:256 * scale}; if (format === 'json') { - try { return callback(null, vtile.toJSON(), headers); } - catch(err) { return callback(err); } + try { return accept({tile: vtile.toJSON(), headers:headers}); } + catch(err) { return reject(err); } } else if (format === 'utf') { var surface = new mapnik.Grid(width,height); opts.layer = source._map.parameters.interactivity_layer; opts.fields = source._map.parameters.interactivity_fields.split(','); } else if (format === 'svg') { var surface = new mapnik.CairoSurface('svg',width,height); - if (callback.renderer || this._renderer) { - opts.renderer = callback.renderer || this._renderer; + if (options.renderer || source._renderer) { + opts.renderer = options.renderer || source._renderer; } } else { var surface = new mapnik.Image(width,height); @@ -207,19 +271,19 @@ Vector.prototype.getTile = function(z, x, y, callback) { vtile.render(source._map, surface, opts, function(err, image) { if (err) { err.code = 'EMAPNIK'; - return callback(err); + return reject(err); } if (format == 'svg') { headers['Content-Type'] = 'image/svg+xml'; - return callback(null, image.getData(), headers); + return accept({tile: image.getData(), headers: headers}); } else if (format === 'utf') { image.encode({}, function(err, buffer) { - if (err) return callback(err); - return callback(null, buffer, headers); + if (err) return reject(err); + return accept({tile: buffer, headers: headers}); }); } else { image.encode(format, {}, function(err, buffer) { - if (err) return callback(err); + if (err) return reject(err); buffer._loadtime = loadtime; buffer._drawtime = (+new Date) - drawtime; @@ -227,12 +291,12 @@ Vector.prototype.getTile = function(z, x, y, callback) { if (profile) buffer._layerInfo = profiler.layerInfo(vtile); - return callback(null, buffer, headers); + return accept({tile: buffer, headers: headers}); }); } }); }; - if (!callback.format && source._xray) { + if (!options.format && source._xray) { cb.setSrcData = true; } cb.format = format; @@ -240,14 +304,18 @@ Vector.prototype.getTile = function(z, x, y, callback) { cb.legacy = legacy; cb.upgrade = upgrade; source._backend.getTile(z, x, y, cb); +}); }; Vector.prototype.getGrid = function(z, x, y, callback) { - if (!this._map) return callback(new Error('Tilesource not loaded')); - if (!this._map.parameters.interactivity_layer) return callback(new Error('Tilesource has no interactivity_layer')); - if (!this._map.parameters.interactivity_fields) return callback(new Error('Tilesource has no interactivity_fields')); callback.format = 'utf'; - return this.getTile(z, x, y, callback); + var params = getAsyncParameters(z, x, y, callback); + params.type = 'grid'; + this.getAsync(params).then(res => { + callback(undefined, res.grid, res.headers); + }, err => { + callback(err); + }); }; Vector.prototype.getHeaders = function(z, x, y, callback) { @@ -256,11 +324,21 @@ Vector.prototype.getHeaders = function(z, x, y, callback) { }; Vector.prototype.getInfo = function(callback) { - if (!this._map) return callback(new Error('Tilesource not loaded')); - if (this._info) return callback(null, this._info); + this.getAsync({type: 'info'}).then(res => { + callback(undefined, res.info); + }, err => { + callback(err); + }); +}; + +function _getInfoAsync() { + var source = this; + return new Promise((accept, reject) => { - var params = this._map.parameters; - this._info = Object.keys(params).reduce(function(memo, key) { + if (source._info) return accept({info: source._info}); + + var params = source._map.parameters; + source._info = Object.keys(params).reduce(function(memo, key) { switch (key) { // The special "json" key/value pair allows JSON to be serialized // and merged into the metadata of a mapnik XML based source. This @@ -268,7 +346,7 @@ Vector.prototype.getInfo = function(callback) { // captured by mapnik XML. case 'json': try { var jsondata = JSON.parse(params[key]); } - catch (err) { return callback(err); } + catch (err) { return reject(err); } Object.keys(jsondata).reduce(function(memo, key) { memo[key] = memo[key] || jsondata[key]; return memo; @@ -287,8 +365,8 @@ Vector.prototype.getInfo = function(callback) { } return memo; }, {}); - return callback(null, this._info); -}; + return accept({info: source._info}); +})}; // Proxies mapnik vtile.query method with the added convienice of // letting the tilelive-vector backend do the hard work of finding @@ -405,7 +483,7 @@ function tm2z(uri, callback) { if (typeof uri === 'string') { uri = url.parse(uri, true); uri.pathname = qs.unescape(uri.pathname); - } + } var maxsize = { file: uri.filesize || 750 * 1024, From 3b4ca9f4b8aa9e6c42a152529e31cfe4dd2901f6 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 11 Apr 2017 14:06:22 -0400 Subject: [PATCH 3/3] Pass params to backend, tile|grid|info=>data --- backend.js | 29 +++++++++++++--------- index.js | 70 +++++++++++++++++++++++++++------------------------- package.json | 2 +- 3 files changed, 54 insertions(+), 47 deletions(-) diff --git a/backend.js b/backend.js index 7196d8a..ae451f5 100644 --- a/backend.js +++ b/backend.js @@ -67,7 +67,7 @@ Backend.prototype.getAsync = function(opts) { Backend.prototype.getInfo = function(callback) { this.getAsync({type: 'info'}).then(res => { - callback(undefined, res.info); + callback(undefined, res.data); }, err => { callback(err); }); @@ -82,9 +82,10 @@ Backend.prototype.getTile = function(z, x, y, callback) { legacy: callback.legacy, scale: callback.scale, upgrade: callback.upgrade, - setSrcData: callback.setSrcData + setSrcData: callback.setSrcData, + treatAsVector: callback.treatAsVector }).then(res => { - callback(undefined, res.tile, res.headers); + callback(undefined, res.data, res.headers); }, err => { callback(err); }); @@ -142,7 +143,7 @@ function _getTileAsync(opts) { if (err.message !== 'Tile does not exist') throw err; return {}; }).then(result => { - var body = result.tile; + var body = result.data; var head = result.headers; if (body instanceof mapnik.VectorTile) { @@ -152,10 +153,14 @@ function _getTileAsync(opts) { } var compression = false; - if (body && body[0] == 0x78 && body[1] == 0x9C) { - compression = 'inflate'; - } else if (body && body[0] == 0x1F && body[1] == 0x8B) { - compression = 'gunzip'; + if (body) { + if (body[0] == 0x78 && body[1] == 0x9C) { + compression = 'inflate'; + } else if (body[0] == 0x1F && body[1] == 0x8B) { + compression = 'gunzip'; + } else if (opts.treatAsVector) { + compression = true; + } } if (!body || !body.length) { @@ -192,14 +197,14 @@ function _getTileAsync(opts) { headers['x-vector-backend-object'] = headers['x-vector-backend-object'] || 'default'; // Pass-thru of an upstream mapnik vector tile (not pbf) source. - if (data instanceof mapnik.VectorTile) return accept({tile: data, headers: headers}); + if (data instanceof mapnik.VectorTile) return accept({data: data, headers: headers}); var vtile = new mapnik.VectorTile(opts.z, opts.x, opts.y); vtile._srcbytes = size; if (opts.setSrcData) vtile._srcdata = data; // null/zero length data is a solid tile be painted. - if (!data || !data.length) return accept({tile: vtile, headers: headers}); + if (!data || !data.length) return accept({data: vtile, headers: headers}); try { if (type === 'pbf') { @@ -207,12 +212,12 @@ function _getTileAsync(opts) { // and is empty so skips a clear call internally in mapnik. vtile.addData(data,{upgrade:upgrade},function(err) { if (err) return reject(err); - return accept({tile: vtile, headers: headers}); + return accept({data: vtile, headers: headers}); }); } else { vtile.addImageBuffer(data, backend._layer, function(err) { if (err) return reject(err); - return accept({tile: vtile, headers: headers}); + return accept({data: vtile, headers: headers}); }); } } catch (err) { diff --git a/index.js b/index.js index 9d5355d..a715eff 100644 --- a/index.js +++ b/index.js @@ -18,6 +18,7 @@ var profiler = require('./tile-profiler'); var Backend = require('./backend'); var AWS = require('aws-sdk'); var s3urls = require('s3urls'); +var uptile = require('tilelive-promise'); // Register fonts for xray styles. mapnik.register_fonts(path.resolve(__dirname, 'fonts')); @@ -54,7 +55,7 @@ function Vector(uri, callback) { this._format = uri.format || undefined; this._renderer = uri.renderer || undefined; this._source = uri.source || undefined; - this._backend = uri.backend || undefined; + this._backend = uri.backend ? uptile(uri.backend) : undefined; this._base = path.resolve(uri.base || __dirname); if (callback) this.once('open', callback); @@ -142,12 +143,7 @@ Vector.prototype.getAsync = function(opts) { if (!self._map.parameters.interactivity_fields) { throw new Error('Tilesource has no interactivity_fields'); } - result = _getTileAsync.call(self, opts).then(v => { - // _getTile returns all responses in the "tile" property, rename it to grid - v.grid = v.tile; - delete v.tile; - return v; - }); + result = _getTileAsync.call(self, opts); break; case 'info': result = _getInfoAsync.call(self); @@ -172,7 +168,8 @@ function getAsyncParameters(z, x, y, callback) { profile: callback.profile, legacy: callback.legacy, upgrade: callback.upgrade, - renderer: callback.renderer + renderer: callback.renderer, + treatAsVector: callback.treatAsVector }; }; @@ -180,7 +177,7 @@ Vector.prototype.getTile = function(z, x, y, callback) { // Hack around tilelive API - allow params to be passed per request // as attributes of the callback function. this.getAsync(getAsyncParameters(z, x, y, callback)).then(res => { - callback(undefined, res.tile, res.headers); + callback(undefined, res.data, res.headers); }, err => { callback(err); }); @@ -190,9 +187,10 @@ function _getTileAsync(options) { var source = this; return new Promise((accept, reject) => { + var options2 = Object.assign({}, options); var z = options.z, x = options.x, y = options.y; if (z < 0 || x < 0 || y < 0 || x >= Math.pow(2,z) || y >= Math.pow(2,z)) { - return reject(new Error('Tile does not exist')); + throw new Error('Tile does not exist'); } var format = options.format || source._format; var scale = options.scale || source._scale; @@ -204,9 +202,22 @@ function _getTileAsync(options) { var drawtime; var loadtime = +new Date; - var cb = function(err, vtile, head) { - if (err && err.message !== 'Tile does not exist') - return reject(err); + + if (!options.format && source._xray) { + options2.setSrcData = true; + } + options2.format = format; + options2.scale = scale; + options2.legacy = legacy; + options2.upgrade = upgrade; + + source._backend.getAsync(options2).catch(err => { + if (err.message !== 'Tile does not exist') + throw err; + }).then(result => { + + var vtile = result.data; + var head = result.headers; // For xray styles use srcdata tile format. if (!options.format && source._xray && vtile._srcdata) { @@ -248,14 +259,13 @@ function _getTileAsync(options) { headers['x-vector-backend-object'] = head['x-vector-backend-object']; // Return headers for 'headers' format. - if (format === 'headers') return accept({tile:headers, headers:headers}); + if (format === 'headers') return accept({data:headers, headers:headers}); loadtime = (+new Date) - loadtime; drawtime = +new Date; var opts = {z:z, x:x, y:y, scale:scale, buffer_size:256 * scale}; if (format === 'json') { - try { return accept({tile: vtile.toJSON(), headers:headers}); } - catch(err) { return reject(err); } + return accept({data: vtile.toJSON(), headers:headers}); } else if (format === 'utf') { var surface = new mapnik.Grid(width,height); opts.layer = source._map.parameters.interactivity_layer; @@ -273,13 +283,13 @@ function _getTileAsync(options) { err.code = 'EMAPNIK'; return reject(err); } - if (format == 'svg') { + if (format === 'svg') { headers['Content-Type'] = 'image/svg+xml'; - return accept({tile: image.getData(), headers: headers}); + return accept({data: image.getData(), headers: headers}); } else if (format === 'utf') { image.encode({}, function(err, buffer) { if (err) return reject(err); - return accept({tile: buffer, headers: headers}); + return accept({data: buffer, headers: headers}); }); } else { image.encode(format, {}, function(err, buffer) { @@ -291,20 +301,12 @@ function _getTileAsync(options) { if (profile) buffer._layerInfo = profiler.layerInfo(vtile); - return accept({tile: buffer, headers: headers}); + return accept({data: buffer, headers: headers}); }); } }); - }; - if (!options.format && source._xray) { - cb.setSrcData = true; - } - cb.format = format; - cb.scale = scale; - cb.legacy = legacy; - cb.upgrade = upgrade; - source._backend.getTile(z, x, y, cb); -}); + }).catch(reject); + }); }; Vector.prototype.getGrid = function(z, x, y, callback) { @@ -312,7 +314,7 @@ Vector.prototype.getGrid = function(z, x, y, callback) { var params = getAsyncParameters(z, x, y, callback); params.type = 'grid'; this.getAsync(params).then(res => { - callback(undefined, res.grid, res.headers); + callback(undefined, res.data, res.headers); }, err => { callback(err); }); @@ -325,7 +327,7 @@ Vector.prototype.getHeaders = function(z, x, y, callback) { Vector.prototype.getInfo = function(callback) { this.getAsync({type: 'info'}).then(res => { - callback(undefined, res.info); + callback(undefined, res.data); }, err => { callback(err); }); @@ -335,7 +337,7 @@ function _getInfoAsync() { var source = this; return new Promise((accept, reject) => { - if (source._info) return accept({info: source._info}); + if (source._info) return accept({data: source._info}); var params = source._map.parameters; source._info = Object.keys(params).reduce(function(memo, key) { @@ -365,7 +367,7 @@ function _getInfoAsync() { } return memo; }, {}); - return accept({info: source._info}); + return accept({data: source._info}); })}; // Proxies mapnik vtile.query method with the added convienice of diff --git a/package.json b/package.json index eb7069d..a43b95b 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "numeral": "~1.5.3", "sphericalmercator": "~1.0.5", "spherical": "~0.1.0", - "tilelive-promise": "^1.0.5", + "tilelive-promise": "^2.0.0", "underscore": "~1.8.0" }, "devDependencies": {