diff --git a/package.json b/package.json index 7dab91c..5012e84 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@mapbox/mapbox-gl-native": "5.0.2", "@mapbox/mapbox-gl-style-spec": "13.12.0", "@mapbox/mbtiles": "0.11.0", + "@mapbox/tilejson": "1.1.0", "@mapbox/sphericalmercator": "1.1.0", "@mapbox/vector-tile": "1.3.1", "advanced-pool": "0.3.3", diff --git a/src/serve_data.js b/src/serve_data.js index 37649bf..3c1067b 100644 --- a/src/serve_data.js +++ b/src/serve_data.js @@ -7,6 +7,7 @@ const zlib = require('zlib'); const clone = require('clone'); const express = require('express'); const MBTiles = require('@mapbox/mbtiles'); +const TileJSON = require('@mapbox/tilejson'); const Pbf = require('pbf'); const VectorTile = require('@mapbox/vector-tile').VectorTile; @@ -108,57 +109,95 @@ module.exports = { return res.sendStatus(404); } const info = clone(item.tileJSON); - info.tiles = utils.getTileUrls(req, info.tiles, - `data/${req.params.id}`, info.format, item.publicUrl, { - 'pbf': options.pbfAlias - }); + if (!info.tiles || !info.tiles[0].startsWith('http')) { + info.tiles = utils.getTileUrls(req, info.tiles, + `data/${req.params.id}`, info.format, item.publicUrl, { + 'pbf': options.pbfAlias + }); + } return res.send(info); }); return app; }, add: (options, repo, params, id, publicUrl) => { - const mbtilesFile = path.resolve(options.paths.mbtiles, params.mbtiles); - let tileJSON = { - 'tiles': params.domains || options.domains - }; - - const mbtilesFileStats = fs.statSync(mbtilesFile); - if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) { - throw Error(`Not valid MBTiles file: ${mbtilesFile}`); - } + let sourceInfoPromise; + let tileJSON = {}; let source; - const sourceInfoPromise = new Promise((resolve, reject) => { - source = new MBTiles(mbtilesFile, err => { - if (err) { - reject(err); - return; - } - source.getInfo((err, info) => { + + if (params.remote_tilejson) { + sourceInfoPromise = new Promise((resolve, reject) => { + source = new TileJSON(params.remote_tilejson, (err, _) => { if (err) { reject(err); return; } - tileJSON['name'] = id; - tileJSON['format'] = 'pbf'; + source.getInfo((err, info) => { + if (err) { + reject(err); + return; + } + tileJSON['name'] = id; - Object.assign(tileJSON, info); + Object.assign(tileJSON, info); - tileJSON['tilejson'] = '2.0.0'; - delete tileJSON['filesize']; - delete tileJSON['mtime']; - delete tileJSON['scheme']; + delete tileJSON['mtime']; + delete tileJSON['scheme']; - Object.assign(tileJSON, params.tilejson || {}); - utils.fixTileJSONCenter(tileJSON); + Object.assign(tileJSON, params.tilejson || {}); + utils.fixTileJSONCenter(tileJSON); - if (options.dataDecoratorFunc) { - tileJSON = options.dataDecoratorFunc(id, 'tilejson', tileJSON); - } - resolve(); + if (options.dataDecoratorFunc) { + tileJSON = options.dataDecoratorFunc(id, 'tilejson', tileJSON); + } + resolve(); + }); }); }); - }); + + } else { + + const mbtilesFile = path.resolve(options.paths.mbtiles, params.mbtiles); + tileJSON = { + 'tiles': params.domains || options.domains + }; + const mbtilesFileStats = fs.statSync(mbtilesFile); + if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) { + throw Error(`Not valid MBTiles file: ${mbtilesFile}`); + } + sourceInfoPromise = new Promise((resolve, reject) => { + source = new MBTiles(mbtilesFile, err => { + if (err) { + reject(err); + return; + } + source.getInfo((err, info) => { + if (err) { + reject(err); + return; + } + tileJSON['name'] = id; + tileJSON['format'] = 'pbf'; + + Object.assign(tileJSON, info); + + tileJSON['tilejson'] = '2.0.0'; + delete tileJSON['filesize']; + delete tileJSON['mtime']; + delete tileJSON['scheme']; + + Object.assign(tileJSON, params.tilejson || {}); + utils.fixTileJSONCenter(tileJSON); + + if (options.dataDecoratorFunc) { + tileJSON = options.dataDecoratorFunc(id, 'tilejson', tileJSON); + } + resolve(); + }); + }); + }); + + } return sourceInfoPromise.then(() => { repo[id] = { diff --git a/src/serve_rendered.js b/src/serve_rendered.js index e94b827..77fa926 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -19,6 +19,7 @@ const express = require('express'); const mercator = new (require('@mapbox/sphericalmercator'))(); const mbgl = require('@mapbox/mapbox-gl-native'); const MBTiles = require('@mapbox/mbtiles'); +const TileJSON = require('@mapbox/tilejson'); const proj4 = require('proj4'); const request = require('request'); @@ -758,6 +759,38 @@ module.exports = { } } + if (mbtilesFile.startsWith('http')) { + queue.push(new Promise((resolve, reject) => { + map.sources[name] = new TileJSON(mbtilesFile, (err, _) => { + map.sources[name].getInfo((err, info) => { + if (err) { + console.error(err); + return; + } + + const type = source.type; + Object.assign(source, info); + source.type = type; + source.url = mbtilesFile; + + if (options.dataDecoratorFunc) { + source = options.dataDecoratorFunc(name, 'tilejson', source); + } + + if (!attributionOverride && + source.attribution && source.attribution.length > 0) { + if (tileJSON.attribution.length > 0) { + tileJSON.attribution += '; '; + } + tileJSON.attribution += source.attribution; + } + resolve(); + }); + }); + })); + continue; + } + queue.push(new Promise((resolve, reject) => { mbtilesFile = path.resolve(options.paths.mbtiles, mbtilesFile); const mbtilesFileStats = fs.statSync(mbtilesFile); diff --git a/src/server.js b/src/server.js index cf15fed..972a94d 100644 --- a/src/server.js +++ b/src/server.js @@ -160,7 +160,7 @@ function start(opts) { let mbtilesFile; for (const id of Object.keys(data)) { if (id === mbtiles) { - mbtilesFile = data[id].mbtiles; + mbtilesFile = data[id].mbtiles || data[id].remote_tilejson; } } return mbtilesFile; @@ -190,8 +190,8 @@ function start(opts) { for (const id of Object.keys(data)) { const item = data[id]; - if (!item.mbtiles || item.mbtiles.length === 0) { - console.log(`Missing "mbtiles" property for ${id}`); + if ((!item.mbtiles || item.mbtiles.length === 0) && (!item.remote_tilejson || item.remote_tilejson.length === 0)) { + console.log(`Missing "mbtiles" or "remote_tilejson" property for ${id}`); continue; }