Add "serveAllStyles" option + watch the directory

This commit is contained in:
Petr Sloup 2020-01-07 15:59:38 +01:00
parent cb700181d3
commit d7a34f3a74
5 changed files with 110 additions and 29 deletions

View file

@ -27,6 +27,7 @@ Example::
"maxSize": 2048,
"pbfAlias": "pbf",
"serveAllFonts": false,
"serveAllStyles": false,
"serveStaticMaps": true,
"tileMargin": 0
},
@ -124,6 +125,13 @@ If you have plenty of memory, try setting these equal to or slightly above your
If you need to conserve memory, try lower values for scale factors that are less common.
Default is ``[16, 8, 4]``.
``serveAllStyles``
------------------------
If this option is enabled, all the styles from the ``paths.styles`` will be served. (No recursion, only ``.json`` files are used.)
The process will also watch for changes in this directory and remove/add more styles dynamically.
It is recommended to also use the ``serveAllFonts`` option when using this option.
``watermark``
-----------

View file

@ -32,6 +32,7 @@
"handlebars": "4.5.3",
"http-shutdown": "1.2.1",
"morgan": "1.9.1",
"node-watch": "0.6.3",
"pbf": "3.2.1",
"proj4": "2.6.0",
"request": "2.88.0",

View file

@ -663,7 +663,12 @@ module.exports = {
const styleFile = params.style;
const styleJSONPath = path.resolve(options.paths.styles, styleFile);
styleJSON = clone(require(styleJSONPath));
try {
styleJSON = JSON.parse(fs.readFileSync(styleJSONPath));
} catch (e) {
console.log('Error parsing style file');
return false;
}
if (styleJSON.sprite && !httpTester.test(styleJSON.sprite)) {
styleJSON.sprite = 'sprites://' +
@ -798,5 +803,14 @@ module.exports = {
});
return Promise.all([renderersReadyPromise]);
},
remove: (repo, id) => {
let item = repo[id];
if (item) {
item.map.renderers.forEach(pool => {
pool.close();
});
}
delete repo[id];
},
};

View file

@ -72,10 +72,19 @@ module.exports = {
return app;
},
remove: (repo, id) => {
delete repo[id];
},
add: (options, repo, params, id, publicUrl, reportTiles, reportFont) => {
const styleFile = path.resolve(options.paths.styles, params.style);
let styleJSON;
try {
styleJSON = JSON.parse(fs.readFileSync(styleFile));
} catch (e) {
console.log('Error parsing style file');
return false;
}
const styleJSON = clone(require(styleFile));
for (const name of Object.keys(styleJSON.sources)) {
const source = styleJSON.sources[name];
const url = source.url;
@ -92,6 +101,9 @@ module.exports = {
}
}
const identifier = reportTiles(mbtilesFile, fromData);
if (!identifier) {
return false;
}
source.url = `local://data/${identifier}.json`;
}
}
@ -128,5 +140,7 @@ module.exports = {
publicUrl,
name: styleJSON.name
};
return true;
}
};

View file

@ -14,6 +14,7 @@ const express = require('express');
const handlebars = require('handlebars');
const mercator = new (require('@mapbox/sphericalmercator'))();
const morgan = require('morgan');
const watch = require('node-watch');
const packageJson = require('../package');
const serve_font = require('./serve_font');
@ -114,15 +115,10 @@ function start(opts) {
);
}
for (const id of Object.keys(config.styles || {})) {
const item = config.styles[id];
if (!item.style || item.style.length === 0) {
console.log(`Missing "style" property for ${id}`);
continue;
}
let addStyle = (id, item, allowMoreData, reportFonts) => {
let success = true;
if (item.serve_data !== false) {
serve_style.add(options, serving.styles, item, id, opts.publicUrl,
success = serve_style.add(options, serving.styles, item, id, opts.publicUrl,
(mbtiles, fromData) => {
let dataItemId;
for (const id of Object.keys(data)) {
@ -138,9 +134,10 @@ function start(opts) {
}
if (dataItemId) { // mbtiles exist in the data config
return dataItemId;
} else if (fromData) {
console.log(`ERROR: data "${mbtiles}" not found!`);
process.exit(1);
} else {
if (fromData || !allowMoreData) {
console.log(`ERROR: style "${file.name}" using unknown mbtiles "${mbtiles}"! Skipping...`);
return undefined;
} else {
let id = mbtiles.substr(0, mbtiles.lastIndexOf('.')) || mbtiles;
while (data[id]) id += '_';
@ -149,11 +146,14 @@ function start(opts) {
};
return id;
}
}
}, font => {
if (reportFonts) {
serving.fonts[font] = true;
}
});
}
if (item.serve_rendered !== false) {
if (success && item.serve_rendered !== false) {
if (serve_rendered) {
startupPromises.push(serve_rendered.add(options, serving.rendered, item, id, opts.publicUrl,
mbtiles => {
@ -170,6 +170,16 @@ function start(opts) {
item.serve_rendered = false;
}
}
};
for (const id of Object.keys(config.styles || {})) {
const item = config.styles[id];
if (!item.style || item.style.length === 0) {
console.log(`Missing "style" property for ${id}`);
continue;
}
addStyle(id, item, true, true);
}
startupPromises.push(
@ -190,6 +200,41 @@ function start(opts) {
);
}
if (options.serveAllStyles) {
fs.readdir(options.paths.styles, {withFileTypes: true}, (err, files) => {
if (err) {
return;
}
for (const file of files) {
if (file.isFile() &&
path.extname(file.name).toLowerCase() == '.json') {
let id = path.basename(file.name, '.json');
let item = {
style: file.name
};
addStyle(id, item, false, false);
}
}
});
watch(options.paths.styles,
{ persistent: false, filter: /\.json$/ },
(eventType, filename) => {
let id = path.basename(filename, '.json');
console.log(`Style "${id}" changed, updating...`);
serve_style.remove(serving.styles, id);
serve_rendered.remove(serving.rendered, id);
if (eventType == "update") {
let item = {
style: filename
};
addStyle(id, item, false, false);
}
});
}
app.get('/styles.json', (req, res, next) => {
const result = [];
const query = req.query.key ? (`?key=${req.query.key}`) : '';
@ -207,10 +252,9 @@ function start(opts) {
const addTileJSONs = (arr, req, type) => {
for (const id of Object.keys(serving[type])) {
let info = clone(serving[type][id]);
const info = clone(serving[type][id].tileJSON);
let path = '';
if (type === 'rendered') {
info = info.tileJSON;
path = `styles/${id}`;
} else {
path = `${type}/${id}`;
@ -280,7 +324,7 @@ function start(opts) {
};
serveTemplate('/$', 'index', req => {
const styles = clone(config.styles || {});
const styles = clone(serving.styles || {});
for (const id of Object.keys(styles)) {
const style = styles[id];
style.name = (serving.styles[id] || serving.rendered[id] || {}).name;
@ -341,7 +385,7 @@ function start(opts) {
serveTemplate('/styles/:id/$', 'viewer', req => {
const id = req.params.id;
const style = clone((config.styles || {})[id]);
const style = clone(((serving.styles || {})[id] || {}).styleJSON);
if (!style) {
return null;
}
@ -359,7 +403,7 @@ function start(opts) {
*/
serveTemplate('/styles/:id/wmts.xml', 'wmts', req => {
const id = req.params.id;
const wmts = clone((config.styles || {})[id]);
const wmts = clone((serving.styles || {})[id]);
if (!wmts) {
return null;
}