Add "serveAllStyles" option + watch the directory
This commit is contained in:
parent
cb700181d3
commit
d7a34f3a74
5 changed files with 110 additions and 29 deletions
|
@ -27,6 +27,7 @@ Example::
|
||||||
"maxSize": 2048,
|
"maxSize": 2048,
|
||||||
"pbfAlias": "pbf",
|
"pbfAlias": "pbf",
|
||||||
"serveAllFonts": false,
|
"serveAllFonts": false,
|
||||||
|
"serveAllStyles": false,
|
||||||
"serveStaticMaps": true,
|
"serveStaticMaps": true,
|
||||||
"tileMargin": 0
|
"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.
|
If you need to conserve memory, try lower values for scale factors that are less common.
|
||||||
Default is ``[16, 8, 4]``.
|
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``
|
``watermark``
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
"handlebars": "4.5.3",
|
"handlebars": "4.5.3",
|
||||||
"http-shutdown": "1.2.1",
|
"http-shutdown": "1.2.1",
|
||||||
"morgan": "1.9.1",
|
"morgan": "1.9.1",
|
||||||
|
"node-watch": "0.6.3",
|
||||||
"pbf": "3.2.1",
|
"pbf": "3.2.1",
|
||||||
"proj4": "2.6.0",
|
"proj4": "2.6.0",
|
||||||
"request": "2.88.0",
|
"request": "2.88.0",
|
||||||
|
|
|
@ -663,7 +663,12 @@ module.exports = {
|
||||||
|
|
||||||
const styleFile = params.style;
|
const styleFile = params.style;
|
||||||
const styleJSONPath = path.resolve(options.paths.styles, styleFile);
|
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)) {
|
if (styleJSON.sprite && !httpTester.test(styleJSON.sprite)) {
|
||||||
styleJSON.sprite = 'sprites://' +
|
styleJSON.sprite = 'sprites://' +
|
||||||
|
@ -798,5 +803,14 @@ module.exports = {
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all([renderersReadyPromise]);
|
return Promise.all([renderersReadyPromise]);
|
||||||
|
},
|
||||||
|
remove: (repo, id) => {
|
||||||
|
let item = repo[id];
|
||||||
|
if (item) {
|
||||||
|
item.map.renderers.forEach(pool => {
|
||||||
|
pool.close();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
delete repo[id];
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,10 +72,19 @@ module.exports = {
|
||||||
|
|
||||||
return app;
|
return app;
|
||||||
},
|
},
|
||||||
|
remove: (repo, id) => {
|
||||||
|
delete repo[id];
|
||||||
|
},
|
||||||
add: (options, repo, params, id, publicUrl, reportTiles, reportFont) => {
|
add: (options, repo, params, id, publicUrl, reportTiles, reportFont) => {
|
||||||
const styleFile = path.resolve(options.paths.styles, params.style);
|
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)) {
|
for (const name of Object.keys(styleJSON.sources)) {
|
||||||
const source = styleJSON.sources[name];
|
const source = styleJSON.sources[name];
|
||||||
const url = source.url;
|
const url = source.url;
|
||||||
|
@ -92,6 +101,9 @@ module.exports = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const identifier = reportTiles(mbtilesFile, fromData);
|
const identifier = reportTiles(mbtilesFile, fromData);
|
||||||
|
if (!identifier) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
source.url = `local://data/${identifier}.json`;
|
source.url = `local://data/${identifier}.json`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,5 +140,7 @@ module.exports = {
|
||||||
publicUrl,
|
publicUrl,
|
||||||
name: styleJSON.name
|
name: styleJSON.name
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@ const express = require('express');
|
||||||
const handlebars = require('handlebars');
|
const handlebars = require('handlebars');
|
||||||
const mercator = new (require('@mapbox/sphericalmercator'))();
|
const mercator = new (require('@mapbox/sphericalmercator'))();
|
||||||
const morgan = require('morgan');
|
const morgan = require('morgan');
|
||||||
|
const watch = require('node-watch');
|
||||||
|
|
||||||
const packageJson = require('../package');
|
const packageJson = require('../package');
|
||||||
const serve_font = require('./serve_font');
|
const serve_font = require('./serve_font');
|
||||||
|
@ -114,15 +115,10 @@ function start(opts) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const id of Object.keys(config.styles || {})) {
|
let addStyle = (id, item, allowMoreData, reportFonts) => {
|
||||||
const item = config.styles[id];
|
let success = true;
|
||||||
if (!item.style || item.style.length === 0) {
|
|
||||||
console.log(`Missing "style" property for ${id}`);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.serve_data !== false) {
|
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) => {
|
(mbtiles, fromData) => {
|
||||||
let dataItemId;
|
let dataItemId;
|
||||||
for (const id of Object.keys(data)) {
|
for (const id of Object.keys(data)) {
|
||||||
|
@ -138,9 +134,10 @@ function start(opts) {
|
||||||
}
|
}
|
||||||
if (dataItemId) { // mbtiles exist in the data config
|
if (dataItemId) { // mbtiles exist in the data config
|
||||||
return dataItemId;
|
return dataItemId;
|
||||||
} else if (fromData) {
|
} else {
|
||||||
console.log(`ERROR: data "${mbtiles}" not found!`);
|
if (fromData || !allowMoreData) {
|
||||||
process.exit(1);
|
console.log(`ERROR: style "${file.name}" using unknown mbtiles "${mbtiles}"! Skipping...`);
|
||||||
|
return undefined;
|
||||||
} else {
|
} else {
|
||||||
let id = mbtiles.substr(0, mbtiles.lastIndexOf('.')) || mbtiles;
|
let id = mbtiles.substr(0, mbtiles.lastIndexOf('.')) || mbtiles;
|
||||||
while (data[id]) id += '_';
|
while (data[id]) id += '_';
|
||||||
|
@ -149,11 +146,14 @@ function start(opts) {
|
||||||
};
|
};
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}, font => {
|
}, font => {
|
||||||
|
if (reportFonts) {
|
||||||
serving.fonts[font] = true;
|
serving.fonts[font] = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (item.serve_rendered !== false) {
|
if (success && item.serve_rendered !== false) {
|
||||||
if (serve_rendered) {
|
if (serve_rendered) {
|
||||||
startupPromises.push(serve_rendered.add(options, serving.rendered, item, id, opts.publicUrl,
|
startupPromises.push(serve_rendered.add(options, serving.rendered, item, id, opts.publicUrl,
|
||||||
mbtiles => {
|
mbtiles => {
|
||||||
|
@ -170,6 +170,16 @@ function start(opts) {
|
||||||
item.serve_rendered = false;
|
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(
|
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) => {
|
app.get('/styles.json', (req, res, next) => {
|
||||||
const result = [];
|
const result = [];
|
||||||
const query = req.query.key ? (`?key=${req.query.key}`) : '';
|
const query = req.query.key ? (`?key=${req.query.key}`) : '';
|
||||||
|
@ -207,10 +252,9 @@ function start(opts) {
|
||||||
|
|
||||||
const addTileJSONs = (arr, req, type) => {
|
const addTileJSONs = (arr, req, type) => {
|
||||||
for (const id of Object.keys(serving[type])) {
|
for (const id of Object.keys(serving[type])) {
|
||||||
let info = clone(serving[type][id]);
|
const info = clone(serving[type][id].tileJSON);
|
||||||
let path = '';
|
let path = '';
|
||||||
if (type === 'rendered') {
|
if (type === 'rendered') {
|
||||||
info = info.tileJSON;
|
|
||||||
path = `styles/${id}`;
|
path = `styles/${id}`;
|
||||||
} else {
|
} else {
|
||||||
path = `${type}/${id}`;
|
path = `${type}/${id}`;
|
||||||
|
@ -280,7 +324,7 @@ function start(opts) {
|
||||||
};
|
};
|
||||||
|
|
||||||
serveTemplate('/$', 'index', req => {
|
serveTemplate('/$', 'index', req => {
|
||||||
const styles = clone(config.styles || {});
|
const styles = clone(serving.styles || {});
|
||||||
for (const id of Object.keys(styles)) {
|
for (const id of Object.keys(styles)) {
|
||||||
const style = styles[id];
|
const style = styles[id];
|
||||||
style.name = (serving.styles[id] || serving.rendered[id] || {}).name;
|
style.name = (serving.styles[id] || serving.rendered[id] || {}).name;
|
||||||
|
@ -341,7 +385,7 @@ function start(opts) {
|
||||||
|
|
||||||
serveTemplate('/styles/:id/$', 'viewer', req => {
|
serveTemplate('/styles/:id/$', 'viewer', req => {
|
||||||
const id = req.params.id;
|
const id = req.params.id;
|
||||||
const style = clone((config.styles || {})[id]);
|
const style = clone(((serving.styles || {})[id] || {}).styleJSON);
|
||||||
if (!style) {
|
if (!style) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -359,7 +403,7 @@ function start(opts) {
|
||||||
*/
|
*/
|
||||||
serveTemplate('/styles/:id/wmts.xml', 'wmts', req => {
|
serveTemplate('/styles/:id/wmts.xml', 'wmts', req => {
|
||||||
const id = req.params.id;
|
const id = req.params.id;
|
||||||
const wmts = clone((config.styles || {})[id]);
|
const wmts = clone((serving.styles || {})[id]);
|
||||||
if (!wmts) {
|
if (!wmts) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue