Convert to esm module syntax (#606)
* switch to esm module * Update package.json * change to maplibre package * fix tests * eslint * remove extra package updates * Delete package-lock.json * change 'fs' to 'node:fs' * put back node 10. without the package updates this still works * remove trailing commas * remove unassociated fix / formatting * remove unassociated fix * remove eslint from this PR * remove unassociated fix * lint * Merge remote-tracking branch 'upstream/master' into esm_update * fix mlgl * update maplibre-native to new version with arm64 * update minor version
This commit is contained in:
235
src/server.js
235
src/server.js
@@ -1,44 +1,45 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
import os from 'os';
|
||||
process.env.UV_THREADPOOL_SIZE =
|
||||
Math.ceil(Math.max(4, require('os').cpus().length * 1.5));
|
||||
Math.ceil(Math.max(4, os.cpus().length * 1.5));
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
import fs from 'node:fs';
|
||||
import path from 'path';
|
||||
|
||||
const chokidar = require('chokidar');
|
||||
const clone = require('clone');
|
||||
const cors = require('cors');
|
||||
const enableShutdown = require('http-shutdown');
|
||||
const express = require('express');
|
||||
const handlebars = require('handlebars');
|
||||
const mercator = new (require('@mapbox/sphericalmercator'))();
|
||||
const morgan = require('morgan');
|
||||
import chokidar from 'chokidar';
|
||||
import clone from 'clone';
|
||||
import cors from 'cors';
|
||||
import enableShutdown from 'http-shutdown';
|
||||
import express from 'express';
|
||||
import handlebars from 'handlebars';
|
||||
import SphericalMercator from '@mapbox/sphericalmercator';
|
||||
const mercator = new SphericalMercator();
|
||||
import morgan from 'morgan';
|
||||
import {serve_data} from './serve_data.js';
|
||||
import {serve_style} from './serve_style.js';
|
||||
import {serve_font} from './serve_font.js';
|
||||
import {getTileUrls, getPublicUrl} from './utils.js';
|
||||
|
||||
const packageJson = require('../package');
|
||||
const serve_font = require('./serve_font');
|
||||
const serve_style = require('./serve_style');
|
||||
const serve_data = require('./serve_data');
|
||||
const utils = require('./utils');
|
||||
import {fileURLToPath} from 'url';
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
const packageJson = JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8'));
|
||||
|
||||
let serve_rendered = null;
|
||||
const isLight = packageJson.name.slice(-6) === '-light';
|
||||
if (!isLight) {
|
||||
// do not require `serve_rendered` in the light package
|
||||
serve_rendered = require('./serve_rendered');
|
||||
}
|
||||
const serve_rendered = (await import(`${!isLight ? `./serve_rendered.js` : `./serve_light.js`}`)).serve_rendered;
|
||||
|
||||
function start(opts) {
|
||||
export function server(opts) {
|
||||
console.log('Starting server');
|
||||
|
||||
const app = express().disable('x-powered-by'),
|
||||
serving = {
|
||||
styles: {},
|
||||
rendered: {},
|
||||
data: {},
|
||||
fonts: {}
|
||||
};
|
||||
const app = express().disable('x-powered-by');
|
||||
const serving = {
|
||||
styles: {},
|
||||
rendered: {},
|
||||
data: {},
|
||||
fonts: {}
|
||||
};
|
||||
|
||||
app.enable('trust proxy');
|
||||
|
||||
@@ -46,7 +47,7 @@ function start(opts) {
|
||||
const defaultLogFormat = process.env.NODE_ENV === 'production' ? 'tiny' : 'dev';
|
||||
const logFormat = opts.logFormat || defaultLogFormat;
|
||||
app.use(morgan(logFormat, {
|
||||
stream: opts.logFile ? fs.createWriteStream(opts.logFile, { flags: 'a' }) : process.stdout,
|
||||
stream: opts.logFile ? fs.createWriteStream(opts.logFile, {flags: 'a'}) : process.stdout,
|
||||
skip: (req, res) => opts.silent && (res.statusCode === 200 || res.statusCode === 304)
|
||||
}));
|
||||
}
|
||||
@@ -56,7 +57,7 @@ function start(opts) {
|
||||
if (opts.configPath) {
|
||||
configPath = path.resolve(opts.configPath);
|
||||
try {
|
||||
config = clone(require(configPath));
|
||||
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||
} catch (e) {
|
||||
console.log('ERROR: Config file not found or invalid!');
|
||||
console.log(' See README.md for instructions and sample data.');
|
||||
@@ -81,7 +82,7 @@ function start(opts) {
|
||||
|
||||
const startupPromises = [];
|
||||
|
||||
const checkPath = type => {
|
||||
const checkPath = (type) => {
|
||||
if (!fs.existsSync(paths[type])) {
|
||||
console.error(`The specified path for "${type}" does not exist (${paths[type]}).`);
|
||||
process.exit(1);
|
||||
@@ -106,65 +107,65 @@ function start(opts) {
|
||||
|
||||
app.use('/data/', serve_data.init(options, serving.data));
|
||||
app.use('/styles/', serve_style.init(options, serving.styles));
|
||||
if (serve_rendered) {
|
||||
if (!isLight) {
|
||||
startupPromises.push(
|
||||
serve_rendered.init(options, serving.rendered)
|
||||
.then(sub => {
|
||||
app.use('/styles/', sub);
|
||||
})
|
||||
serve_rendered.init(options, serving.rendered)
|
||||
.then((sub) => {
|
||||
app.use('/styles/', sub);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
let addStyle = (id, item, allowMoreData, reportFonts) => {
|
||||
const addStyle = (id, item, allowMoreData, reportFonts) => {
|
||||
let success = true;
|
||||
if (item.serve_data !== false) {
|
||||
success = serve_style.add(options, serving.styles, item, id, opts.publicUrl,
|
||||
(mbtiles, fromData) => {
|
||||
let dataItemId;
|
||||
for (const id of Object.keys(data)) {
|
||||
if (fromData) {
|
||||
if (id === mbtiles) {
|
||||
dataItemId = id;
|
||||
}
|
||||
} else {
|
||||
if (data[id].mbtiles === mbtiles) {
|
||||
dataItemId = id;
|
||||
success = serve_style.add(options, serving.styles, item, id, opts.publicUrl,
|
||||
(mbtiles, fromData) => {
|
||||
let dataItemId;
|
||||
for (const id of Object.keys(data)) {
|
||||
if (fromData) {
|
||||
if (id === mbtiles) {
|
||||
dataItemId = id;
|
||||
}
|
||||
} else {
|
||||
if (data[id].mbtiles === mbtiles) {
|
||||
dataItemId = id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dataItemId) { // mbtiles exist in the data config
|
||||
return dataItemId;
|
||||
} else {
|
||||
if (fromData || !allowMoreData) {
|
||||
console.log(`ERROR: style "${item.style}" using unknown mbtiles "${mbtiles}"! Skipping...`);
|
||||
return undefined;
|
||||
if (dataItemId) { // mbtiles exist in the data config
|
||||
return dataItemId;
|
||||
} else {
|
||||
let id = mbtiles.substr(0, mbtiles.lastIndexOf('.')) || mbtiles;
|
||||
while (data[id]) id += '_';
|
||||
data[id] = {
|
||||
'mbtiles': mbtiles
|
||||
};
|
||||
return id;
|
||||
if (fromData || !allowMoreData) {
|
||||
console.log(`ERROR: style "${item.style}" using unknown mbtiles "${mbtiles}"! Skipping...`);
|
||||
return undefined;
|
||||
} else {
|
||||
let id = mbtiles.substr(0, mbtiles.lastIndexOf('.')) || mbtiles;
|
||||
while (data[id]) id += '_';
|
||||
data[id] = {
|
||||
'mbtiles': mbtiles
|
||||
};
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, font => {
|
||||
if (reportFonts) {
|
||||
serving.fonts[font] = true;
|
||||
}
|
||||
});
|
||||
}, (font) => {
|
||||
if (reportFonts) {
|
||||
serving.fonts[font] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (success && item.serve_rendered !== false) {
|
||||
if (serve_rendered) {
|
||||
if (!isLight) {
|
||||
startupPromises.push(serve_rendered.add(options, serving.rendered, item, id, opts.publicUrl,
|
||||
mbtiles => {
|
||||
let mbtilesFile;
|
||||
for (const id of Object.keys(data)) {
|
||||
if (id === mbtiles) {
|
||||
mbtilesFile = data[id].mbtiles;
|
||||
(mbtiles) => {
|
||||
let mbtilesFile;
|
||||
for (const id of Object.keys(data)) {
|
||||
if (id === mbtiles) {
|
||||
mbtilesFile = data[id].mbtiles;
|
||||
}
|
||||
}
|
||||
return mbtilesFile;
|
||||
}
|
||||
return mbtilesFile;
|
||||
}
|
||||
));
|
||||
} else {
|
||||
item.serve_rendered = false;
|
||||
@@ -183,9 +184,9 @@ function start(opts) {
|
||||
}
|
||||
|
||||
startupPromises.push(
|
||||
serve_font(options, serving.fonts).then(sub => {
|
||||
app.use('/', sub);
|
||||
})
|
||||
serve_font(options, serving.fonts).then((sub) => {
|
||||
app.use('/', sub);
|
||||
})
|
||||
);
|
||||
|
||||
for (const id of Object.keys(data)) {
|
||||
@@ -196,7 +197,7 @@ function start(opts) {
|
||||
}
|
||||
|
||||
startupPromises.push(
|
||||
serve_data.add(options, serving.data, item, id, opts.publicUrl)
|
||||
serve_data.add(options, serving.data, item, id, opts.publicUrl)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -208,8 +209,8 @@ function start(opts) {
|
||||
for (const file of files) {
|
||||
if (file.isFile() &&
|
||||
path.extname(file.name).toLowerCase() == '.json') {
|
||||
let id = path.basename(file.name, '.json');
|
||||
let item = {
|
||||
const id = path.basename(file.name, '.json');
|
||||
const item = {
|
||||
style: file.name
|
||||
};
|
||||
addStyle(id, item, false, false);
|
||||
@@ -218,27 +219,27 @@ function start(opts) {
|
||||
});
|
||||
|
||||
const watcher = chokidar.watch(path.join(options.paths.styles, '*.json'),
|
||||
{
|
||||
});
|
||||
{
|
||||
});
|
||||
watcher.on('all',
|
||||
(eventType, filename) => {
|
||||
if (filename) {
|
||||
let id = path.basename(filename, '.json');
|
||||
console.log(`Style "${id}" changed, updating...`);
|
||||
(eventType, filename) => {
|
||||
if (filename) {
|
||||
const id = path.basename(filename, '.json');
|
||||
console.log(`Style "${id}" changed, updating...`);
|
||||
|
||||
serve_style.remove(serving.styles, id);
|
||||
if (serve_rendered) {
|
||||
serve_rendered.remove(serving.rendered, id);
|
||||
}
|
||||
serve_style.remove(serving.styles, id);
|
||||
if (!isLight) {
|
||||
serve_rendered.remove(serving.rendered, id);
|
||||
}
|
||||
|
||||
if (eventType == "add" || eventType == "change") {
|
||||
let item = {
|
||||
style: filename
|
||||
};
|
||||
addStyle(id, item, false, false);
|
||||
if (eventType == 'add' || eventType == 'change') {
|
||||
const item = {
|
||||
style: filename
|
||||
};
|
||||
addStyle(id, item, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
app.get('/styles.json', (req, res, next) => {
|
||||
@@ -250,7 +251,7 @@ function start(opts) {
|
||||
version: styleJSON.version,
|
||||
name: styleJSON.name,
|
||||
id: id,
|
||||
url: `${utils.getPublicUrl(opts.publicUrl, req)}styles/${id}/style.json${query}`
|
||||
url: `${getPublicUrl(opts.publicUrl, req)}styles/${id}/style.json${query}`
|
||||
});
|
||||
}
|
||||
res.send(result);
|
||||
@@ -265,7 +266,7 @@ function start(opts) {
|
||||
} else {
|
||||
path = `${type}/${id}`;
|
||||
}
|
||||
info.tiles = utils.getTileUrls(req, info.tiles, path, info.format, opts.publicUrl, {
|
||||
info.tiles = getTileUrls(req, info.tiles, path, info.format, opts.publicUrl, {
|
||||
'pbf': options.pbfAlias
|
||||
});
|
||||
arr.push(info);
|
||||
@@ -283,7 +284,7 @@ function start(opts) {
|
||||
res.send(addTileJSONs(addTileJSONs([], req, 'rendered'), req, 'data'));
|
||||
});
|
||||
|
||||
//------------------------------------
|
||||
// ------------------------------------
|
||||
// serve web presentations
|
||||
app.use('/', express.static(path.join(__dirname, '../public/resources')));
|
||||
|
||||
@@ -329,7 +330,7 @@ function start(opts) {
|
||||
}));
|
||||
};
|
||||
|
||||
serveTemplate('/$', 'index', req => {
|
||||
serveTemplate('/$', 'index', (req) => {
|
||||
const styles = clone(serving.styles || {});
|
||||
for (const id of Object.keys(styles)) {
|
||||
const style = styles[id];
|
||||
@@ -345,9 +346,9 @@ function start(opts) {
|
||||
style.thumbnail = `${center[2]}/${Math.floor(centerPx[0] / 256)}/${Math.floor(centerPx[1] / 256)}.png`;
|
||||
}
|
||||
|
||||
style.xyz_link = utils.getTileUrls(
|
||||
req, style.serving_rendered.tileJSON.tiles,
|
||||
`styles/${id}`, style.serving_rendered.tileJSON.format, opts.publicUrl)[0];
|
||||
style.xyz_link = getTileUrls(
|
||||
req, style.serving_rendered.tileJSON.tiles,
|
||||
`styles/${id}`, style.serving_rendered.tileJSON.format, opts.publicUrl)[0];
|
||||
}
|
||||
}
|
||||
const data = clone(serving.data || {});
|
||||
@@ -365,10 +366,10 @@ function start(opts) {
|
||||
data_.thumbnail = `${center[2]}/${Math.floor(centerPx[0] / 256)}/${Math.floor(centerPx[1] / 256)}.${data_.tileJSON.format}`;
|
||||
}
|
||||
|
||||
data_.xyz_link = utils.getTileUrls(
|
||||
req, tilejson.tiles, `data/${id}`, tilejson.format, opts.publicUrl, {
|
||||
'pbf': options.pbfAlias
|
||||
})[0];
|
||||
data_.xyz_link = getTileUrls(
|
||||
req, tilejson.tiles, `data/${id}`, tilejson.format, opts.publicUrl, {
|
||||
'pbf': options.pbfAlias
|
||||
})[0];
|
||||
}
|
||||
if (data_.filesize) {
|
||||
let suffix = 'kB';
|
||||
@@ -390,7 +391,7 @@ function start(opts) {
|
||||
};
|
||||
});
|
||||
|
||||
serveTemplate('/styles/:id/$', 'viewer', req => {
|
||||
serveTemplate('/styles/:id/$', 'viewer', (req) => {
|
||||
const id = req.params.id;
|
||||
const style = clone(((serving.styles || {})[id] || {}).styleJSON);
|
||||
if (!style) {
|
||||
@@ -408,13 +409,13 @@ function start(opts) {
|
||||
return res.redirect(301, '/styles/' + req.params.id + '/');
|
||||
});
|
||||
*/
|
||||
serveTemplate('/styles/:id/wmts.xml', 'wmts', req => {
|
||||
serveTemplate('/styles/:id/wmts.xml', 'wmts', (req) => {
|
||||
const id = req.params.id;
|
||||
const wmts = clone((serving.styles || {})[id]);
|
||||
if (!wmts) {
|
||||
return null;
|
||||
}
|
||||
if (wmts.hasOwnProperty("serve_rendered") && !wmts.serve_rendered) {
|
||||
if (wmts.hasOwnProperty('serve_rendered') && !wmts.serve_rendered) {
|
||||
return null;
|
||||
}
|
||||
wmts.id = id;
|
||||
@@ -423,7 +424,7 @@ function start(opts) {
|
||||
return wmts;
|
||||
});
|
||||
|
||||
serveTemplate('/data/:id/$', 'data', req => {
|
||||
serveTemplate('/data/:id/$', 'data', (req) => {
|
||||
const id = req.params.id;
|
||||
const data = clone(serving.data[id]);
|
||||
if (!data) {
|
||||
@@ -447,7 +448,7 @@ function start(opts) {
|
||||
}
|
||||
});
|
||||
|
||||
const server = app.listen(process.env.PORT || opts.port, process.env.BIND || opts.bind, function () {
|
||||
const server = app.listen(process.env.PORT || opts.port, process.env.BIND || opts.bind, function() {
|
||||
let address = this.address().address;
|
||||
if (address.indexOf('::') === 0) {
|
||||
address = `[${address}]`; // literal IPv6 address
|
||||
@@ -465,10 +466,10 @@ function start(opts) {
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = opts => {
|
||||
export const exports = (opts) => {
|
||||
const running = start(opts);
|
||||
|
||||
running.startupPromise.catch(err => {
|
||||
running.startupPromise.catch((err) => {
|
||||
console.error(err.message);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user