diff --git a/.gitignore b/.gitignore index e65999f..11e5cb9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ test_data data light config.json +*.mbtiles diff --git a/package.json b/package.json index 7e71853..1b32a3c 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "nomnom": "1.8.1", "request": "2.74.0", "sharp": "0.15.1", - "sphericalmercator": "1.0.5" + "sphericalmercator": "1.0.5", + "tileserver-gl-styles": "0.1.0" }, "devDependencies": { "should": "^10.0.0", diff --git a/run.sh b/run.sh index fc5e2cc..5f34649 100755 --- a/run.sh +++ b/run.sh @@ -1,11 +1,3 @@ #!/bin/bash -if [ ! -f /data/config.json ]; then - echo "INFO: No config.json found! Downloading sample data..." - echo "--------------------------------------------------------------------------------" - curl -L -o sample_data.zip https://github.com/klokantech/tileserver-gl-data/archive/v0.8.0.zip - unzip -q sample_data.zip -d sample_data - mv sample_data/tileserver-gl-data-*/* -t /data - rm sample_data.zip - rm -r sample_data -fi -xvfb-run -a -e /dev/stdout --server-args="-screen 0 1024x768x24" node /usr/src/app/src/main.js -p 80 -c /data/config.json +cd /data +xvfb-run -a -e /dev/stdout --server-args="-screen 0 1024x768x24" node /usr/src/app/ -p 80 diff --git a/src/main.js b/src/main.js index 34df437..4e12742 100644 --- a/src/main.js +++ b/src/main.js @@ -2,7 +2,21 @@ 'use strict'; +var fs = require('fs'), + path = require('path'), + request = require('request'); + +var mbtiles = require('mbtiles'); + +var packageJson = require('../package'); + var opts = require('nomnom') + .option('mbtiles', { + default: undefined, + help: 'MBTiles file (uses demo configuration);\n' + + '\t ignored if the configuration file is also specified', + position: 0 + }) .option('config', { abbr: 'c', default: 'config.json', @@ -18,17 +32,129 @@ var opts = require('nomnom') default: 8080, help: 'Port' }) + .option('verbose', { + abbr: 'V', + flag: true, + help: 'More verbose output' + }) .option('version', { abbr: 'v', flag: true, help: 'Version info', callback: function() { - return 'version ' + require('../package.json').version; + return packageJson.name + ' v' + packageJson.version; } }).parse(); -return require('./server')({ - config: opts.config, - bind: opts.bind, - port: opts.port + +console.log('Starting ' + packageJson.name + ' v' + packageJson.version); + +var startServer = function(configPath, config) { + return require('./server')({ + configPath: configPath, + config: config, + bind: opts.bind, + port: opts.port + }); +}; + +var startWithMBTiles = function(mbtilesFile) { + console.log('Automatically creating config file for ' + mbtilesFile); + + mbtilesFile = path.resolve(process.cwd(), mbtilesFile); + + var mbtilesStats = fs.statSync(mbtilesFile); + if (!mbtilesStats.isFile() || mbtilesStats.size === 0) { + console.log('ERROR: Not valid MBTiles file: ' + mbtilesFile); + process.exit(1); + } + var instance = new mbtiles(mbtilesFile, function(err) { + instance.getInfo(function(err, info) { + if (info.format != 'pbf') { + console.log('ERROR: MBTiles format is not "pbf".'); + process.exit(1); + } + var bounds = info.bounds; + + var styleDir = path.resolve(__dirname, "../node_modules/tileserver-gl-styles/"); + + var config = { + "options": { + "paths": { + "root": styleDir, + "fonts": "glyphs", + "sprites": "sprites", + "styles": "styles", + "mbtiles": path.dirname(mbtilesFile) + } + }, + "styles": {}, + "data": { + "data": { + "mbtiles": path.basename(mbtilesFile) + } + } + }; + + var styles = fs.readdirSync(path.resolve(styleDir, 'styles')); + for (var i=0; i < styles.length; i++) { + var styleFilename = styles[i]; + if (styleFilename.endsWith('.json')) { + var styleObject = { + "style": path.basename(styleFilename), + "bounds": bounds + }; + config['styles'][path.basename(styleFilename, '.json')] = + styleObject; + } + } + + if (opts.verbose) { + console.log(JSON.stringify(config, undefined, 2)); + } else { + console.log('Run with --verbose to see the config file here.'); + } + + return startServer(null, config); + }); + }); +}; + +fs.stat(path.resolve(opts.config), function(err, stats) { + if (err || !stats.isFile() || stats.size === 0) { + var mbtiles = opts.mbtiles; + if (!mbtiles) { + // try to find in the cwd + var files = fs.readdirSync(process.cwd()); + for (var i=0; i < files.length; i++) { + var filename = files[i]; + if (filename.endsWith('.mbtiles')) { + var mbTilesStats = fs.statSync(filename); + if (mbTilesStats.isFile() && mbTilesStats.size > 0) { + mbtiles = filename; + break; + } + } + } + if (mbtiles) { + console.log('No MBTiles specified, using ' + mbtiles); + return startWithMBTiles(mbtiles); + } else { + var url = 'https://osm2vectortiles-downloads.os.zhdk.cloud.switch.ch/v2.0/extracts/zurich_switzerland.mbtiles'; + var filename = 'zurich_switzerland.mbtiles'; + var stream = fs.createWriteStream(filename); + console.log('Downloading sample data (' + filename + ') from ' + url); + stream.on('finish', function() { + return startWithMBTiles(mbtiles); + }); + return request.get(url).pipe(stream); + } + } + if (mbtiles) { + return startWithMBTiles(mbtiles); + } + } else { + console.log('Using specified config file from ' + opts.config); + return startServer(opts.config, null); + } }); diff --git a/src/serve_rendered.js b/src/serve_rendered.js index 410d324..1400dc2 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -178,7 +178,6 @@ module.exports = function(options, repo, params, id, dataResolver) { if (fromData) { mbtilesFile = dataResolver(mbtilesFile); } - console.log(mbtilesFile); queue.push(function(callback) { mbtilesFile = path.resolve(options.paths.mbtiles, mbtilesFile); diff --git a/src/server.js b/src/server.js index 8e90eb0..1047db7 100644 --- a/src/server.js +++ b/src/server.js @@ -28,7 +28,7 @@ if (packageJson.name.slice(-6) !== '-light') { } module.exports = function(opts, callback) { - console.log('Starting ' + packageJson.name + ' v' + packageJson.version); + console.log('Starting server'); var app = express().disable('x-powered-by'), serving = { @@ -50,21 +50,29 @@ module.exports = function(opts, callback) { app.use(morgan('dev')); } - var configPath = path.resolve(opts.config); - - var config; - try { - config = clone(require(configPath)); - } catch (e) { - console.log('ERROR: Config file not found or invalid!'); - console.log(' See README.md for instructions and sample data.'); + var config = opts.config || null; + var configPath = null; + if (opts.configPath) { + configPath = path.resolve(opts.configPath); + try { + config = clone(require(configPath)); + } catch (e) { + console.log('ERROR: Config file not found or invalid!'); + console.log(' See README.md for instructions and sample data.'); + process.exit(1); + } + } + if (!config) { + console.log('ERROR: No config file not specified!'); process.exit(1); } var options = config.options || {}; var paths = options.paths || {}; options.paths = paths; - paths.root = path.resolve(process.cwd(), paths.root || ''); + paths.root = path.resolve( + configPath ? path.dirname(configPath) : process.cwd(), + paths.root || ''); paths.styles = path.resolve(paths.root, paths.styles || ''); paths.fonts = path.resolve(paths.root, paths.fonts || ''); paths.sprites = path.resolve(paths.root, paths.sprites || ''); @@ -83,11 +91,17 @@ module.exports = function(opts, callback) { if (item.serve_data !== false) { app.use('/styles/', serve_style(options, serving.styles, item, id, - function(mbtiles) { + function(mbtiles, fromData) { var dataItemId; Object.keys(data).forEach(function(id) { - if (data[id].mbtiles == mbtiles) { - dataItemId = id; + if (fromData) { + if (id == mbtiles) { + dataItemId = id; + } + } else { + if (data[id].mbtiles == mbtiles) { + dataItemId = id; + } } }); if (dataItemId) { // mbtiles exist in the data config @@ -107,7 +121,16 @@ module.exports = function(opts, callback) { if (item.serve_rendered !== false) { if (serve_rendered) { app.use('/styles/' + id + '/', - serve_rendered(options, serving.rendered, item, id)); + serve_rendered(options, serving.rendered, item, id, + function(mbtiles) { + var mbtilesFile; + Object.keys(data).forEach(function(id) { + if (id == mbtiles) { + mbtilesFile = data[id].mbtiles; + } + }); + return mbtilesFile; + })); } else { item.serve_rendered = false; } diff --git a/test/setup.js b/test/setup.js index 69a78f9..b752949 100644 --- a/test/setup.js +++ b/test/setup.js @@ -7,7 +7,7 @@ before(function() { console.log('global setup'); process.chdir('test_data'); var running = require('../src/server')({ - config: 'config.json', + configPath: 'config.json', port: 8888 }); global.app = running.app;