feat: allow 'pmtiles:' in configs. open file less

Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
This commit is contained in:
Andrew Calcutt 2023-10-10 12:30:46 -04:00
parent 98995ab1be
commit 0b99d8ddd1
6 changed files with 223 additions and 154 deletions

View file

@ -8,7 +8,11 @@ import { fileURLToPath } from 'url';
import request from 'request'; import request from 'request';
import { server } from './server.js'; import { server } from './server.js';
import MBTiles from '@mapbox/mbtiles'; import MBTiles from '@mapbox/mbtiles';
import { GetPMtilesInfo } from './pmtiles_adapter.js'; import {
PMtilesOpen,
PMtilesClose,
GetPMtilesInfo,
} from './pmtiles_adapter.js';
const __filename = fileURLToPath(import.meta.url); const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename); const __dirname = path.dirname(__filename);
@ -80,18 +84,18 @@ const startServer = (configPath, config) => {
}); });
}; };
const startWithInputFile = async (inputfile) => { const startWithinputFile = async (inputFile) => {
console.log(`[INFO] Automatically creating config file for ${inputfile}`); console.log(`[INFO] Automatically creating config file for ${inputFile}`);
console.log(`[INFO] Only a basic preview style will be used.`); console.log(`[INFO] Only a basic preview style will be used.`);
console.log( console.log(
`[INFO] See documentation to learn how to create config.json file.`, `[INFO] See documentation to learn how to create config.json file.`,
); );
inputfile = path.resolve(process.cwd(), inputfile); inputFile = path.resolve(process.cwd(), inputFile);
const inputfileStats = fs.statSync(inputfile); const inputFileStats = fs.statSync(inputFile);
if (!inputfileStats.isFile() || inputfileStats.size === 0) { if (!inputFileStats.isFile() || inputFileStats.size === 0) {
console.log(`ERROR: Not a valid input file: ${inputfile}`); console.log(`ERROR: Not a valid input file: ${inputFile}`);
process.exit(1); process.exit(1);
} }
@ -106,24 +110,27 @@ const startWithInputFile = async (inputfile) => {
root: styleDir, root: styleDir,
fonts: 'fonts', fonts: 'fonts',
styles: 'styles', styles: 'styles',
mbtiles: path.dirname(inputfile), mbtiles: path.dirname(inputFile),
pmtiles: path.dirname(inputFile),
}, },
}, },
styles: {}, styles: {},
data: {}, data: {},
}; };
const extension = inputfile.split('.').pop().toLowerCase(); const extension = inputFile.split('.').pop().toLowerCase();
if (extension === 'pmtiles') { if (extension === 'pmtiles') {
const info = await GetPMtilesInfo(inputfile); const FileDescriptor = PMtilesOpen(inputFile);
const info = await GetPMtilesInfo(FileDescriptor);
const metadata = info.metadata; const metadata = info.metadata;
PMtilesClose(FileDescriptor);
if ( if (
metadata.format === 'pbf' && metadata.format === 'pbf' &&
metadata.name.toLowerCase().indexOf('openmaptiles') > -1 metadata.name.toLowerCase().indexOf('openmaptiles') > -1
) { ) {
config['data'][`v3`] = { config['data'][`v3`] = {
mbtiles: path.basename(inputfile), pmtiles: path.basename(inputFile),
}; };
const styles = fs.readdirSync(path.resolve(styleDir, 'styles')); const styles = fs.readdirSync(path.resolve(styleDir, 'styles'));
@ -143,8 +150,8 @@ const startWithInputFile = async (inputfile) => {
console.log( console.log(
`WARN: PMTiles not in "openmaptiles" format. Serving raw data only...`, `WARN: PMTiles not in "openmaptiles" format. Serving raw data only...`,
); );
config['data'][(metadata.id || 'mbtiles').replace(/[?/:]/g, '_')] = { config['data'][(metadata.id || 'pmtiles').replace(/[?/:]/g, '_')] = {
mbtiles: path.basename(inputfile), pmtiles: path.basename(inputFile),
}; };
} }
@ -156,10 +163,10 @@ const startWithInputFile = async (inputfile) => {
return startServer(null, config); return startServer(null, config);
} else { } else {
const instance = new MBTiles(inputfile + '?mode=ro', (err) => { const instance = new MBTiles(inputFile + '?mode=ro', (err) => {
if (err) { if (err) {
console.log('ERROR: Unable to open MBTiles.'); console.log('ERROR: Unable to open MBTiles.');
console.log(`Make sure ${path.basename(inputfile)} is valid MBTiles.`); console.log(`Make sure ${path.basename(inputFile)} is valid MBTiles.`);
process.exit(1); process.exit(1);
} }
@ -167,7 +174,7 @@ const startWithInputFile = async (inputfile) => {
if (err || !info) { if (err || !info) {
console.log('ERROR: Metadata missing in the MBTiles.'); console.log('ERROR: Metadata missing in the MBTiles.');
console.log( console.log(
`Make sure ${path.basename(inputfile)} is valid MBTiles.`, `Make sure ${path.basename(inputFile)} is valid MBTiles.`,
); );
process.exit(1); process.exit(1);
} }
@ -178,7 +185,7 @@ const startWithInputFile = async (inputfile) => {
info.name.toLowerCase().indexOf('openmaptiles') > -1 info.name.toLowerCase().indexOf('openmaptiles') > -1
) { ) {
config['data'][`v3`] = { config['data'][`v3`] = {
mbtiles: path.basename(inputfile), mbtiles: path.basename(inputFile),
}; };
const styles = fs.readdirSync(path.resolve(styleDir, 'styles')); const styles = fs.readdirSync(path.resolve(styleDir, 'styles'));
@ -199,7 +206,7 @@ const startWithInputFile = async (inputfile) => {
`WARN: MBTiles not in "openmaptiles" format. Serving raw data only...`, `WARN: MBTiles not in "openmaptiles" format. Serving raw data only...`,
); );
config['data'][(info.id || 'mbtiles').replace(/[?/:]/g, '_')] = { config['data'][(info.id || 'mbtiles').replace(/[?/:]/g, '_')] = {
mbtiles: path.basename(inputfile), mbtiles: path.basename(inputFile),
}; };
} }
@ -217,30 +224,30 @@ const startWithInputFile = async (inputfile) => {
fs.stat(path.resolve(opts.config), (err, stats) => { fs.stat(path.resolve(opts.config), (err, stats) => {
if (err || !stats.isFile() || stats.size === 0) { if (err || !stats.isFile() || stats.size === 0) {
let inputfile; let inputFile;
if (opts.file) { if (opts.file) {
inputfile = opts.file; inputFile = opts.file;
} else if (opts.mbtiles) { } else if (opts.mbtiles) {
inputfile = opts.mbtiles; inputFile = opts.mbtiles;
} }
if (inputfile) { if (inputFile) {
return startWithInputFile(inputfile); return startWithinputFile(inputFile);
} else { } else {
// try to find in the cwd // try to find in the cwd
const files = fs.readdirSync(process.cwd()); const files = fs.readdirSync(process.cwd());
for (const filename of files) { for (const filename of files) {
if (filename.endsWith('.mbtiles') || filename.endsWith('.pmtiles')) { if (filename.endsWith('.mbtiles') || filename.endsWith('.pmtiles')) {
const InputFilesStats = fs.statSync(filename); const inputFilesStats = fs.statSync(filename);
if (InputFilesStats.isFile() && InputFilesStats.size > 0) { if (inputFilesStats.isFile() && inputFilesStats.size > 0) {
inputfile = filename; inputFile = filename;
break; break;
} }
} }
} }
if (inputfile) { if (inputFile) {
console.log(`No input file specified, using ${inputfile}`); console.log(`No input file specified, using ${inputFile}`);
return startWithInputFile(inputfile); return startWithinputFile(inputFile);
} else { } else {
const url = const url =
'https://github.com/maptiler/tileserver-gl/releases/download/v1.3.0/zurich_switzerland.mbtiles'; 'https://github.com/maptiler/tileserver-gl/releases/download/v1.3.0/zurich_switzerland.mbtiles';
@ -248,7 +255,7 @@ fs.stat(path.resolve(opts.config), (err, stats) => {
const stream = fs.createWriteStream(filename); const stream = fs.createWriteStream(filename);
console.log(`No input file found`); console.log(`No input file found`);
console.log(`[DEMO] Downloading sample data (${filename}) from ${url}`); console.log(`[DEMO] Downloading sample data (${filename}) from ${url}`);
stream.on('finish', () => startWithInputFile(filename)); stream.on('finish', () => startWithinputFile(filename));
return request.get(url).pipe(stream); return request.get(url).pipe(stream);
} }
} }

View file

@ -1,18 +1,25 @@
import fs from 'node:fs'; import fs from 'node:fs';
import PMTiles from 'pmtiles'; import PMTiles from 'pmtiles';
const PMTilesLocalSource = class { export const PMtilesOpen = (FilePath) => {
constructor(file) { const fd = fs.openSync(FilePath, 'r');
this.file = file; return fd;
};
export const PMtilesClose = (fd) => {
fs.closeSync(fd);
};
const PMTilesFileDescriptorSource = class {
constructor(fd) {
this.fd = fd;
} }
getKey() { getKey() {
return this.file.name; return this.fd;
} }
async getBytes(offset, length) { async getBytes(offset, length) {
const buffer = Buffer.alloc(length); const buffer = Buffer.alloc(length);
const fd = fs.openSync(this.file, 'r'); //Open the file in read mode await ReadBytes(this.fd, buffer, offset);
await ReadBytes(fd, buffer, offset); //Read the specifed bytes from the file
fs.closeSync(fd); //close the file
return { data: BufferToArrayBuffer(buffer) }; return { data: BufferToArrayBuffer(buffer) };
} }
}; };
@ -28,8 +35,8 @@ const ReadBytes = async (fd, buffer, offset) => {
}); });
}; };
export const GetPMtilesInfo = async (pmtilesFile) => { export const GetPMtilesInfo = async (fd) => {
const source = new PMTilesLocalSource(pmtilesFile); const source = new PMTilesFileDescriptorSource(fd);
const pmtiles = new PMTiles.PMTiles(source); const pmtiles = new PMTiles.PMTiles(source);
const header = await pmtiles.getHeader(); const header = await pmtiles.getHeader();
const metadata = await pmtiles.getMetadata(); const metadata = await pmtiles.getMetadata();
@ -47,8 +54,8 @@ export const GetPMtilesInfo = async (pmtilesFile) => {
return { header: header, metadata: metadata }; return { header: header, metadata: metadata };
}; };
export const GetPMtilesTile = async (pmtilesFile, z, x, y) => { export const GetPMtilesTile = async (fd, z, x, y) => {
const source = new PMTilesLocalSource(pmtilesFile); const source = new PMTilesFileDescriptorSource(fd);
const pmtiles = new PMTiles.PMTiles(source); const pmtiles = new PMTiles.PMTiles(source);
const header = await pmtiles.getHeader(); const header = await pmtiles.getHeader();
const TileType = GetPmtilesTileType(header.tileType); const TileType = GetPmtilesTileType(header.tileType);

View file

@ -11,7 +11,12 @@ import Pbf from 'pbf';
import { VectorTile } from '@mapbox/vector-tile'; import { VectorTile } from '@mapbox/vector-tile';
import { getTileUrls, fixTileJSONCenter } from './utils.js'; import { getTileUrls, fixTileJSONCenter } from './utils.js';
import { GetPMtilesInfo, GetPMtilesTile } from './pmtiles_adapter.js'; import {
PMtilesOpen,
PMtilesClose,
GetPMtilesInfo,
GetPMtilesTile,
} from './pmtiles_adapter.js';
export const serve_data = { export const serve_data = {
init: (options, repo) => { init: (options, repo) => {
@ -187,22 +192,33 @@ export const serve_data = {
return app; return app;
}, },
add: async (options, repo, params, id, publicUrl) => { add: async (options, repo, params, id, publicUrl) => {
const mbtilesFile = path.resolve(options.paths.mbtiles, params.mbtiles); let inputFile;
let inputType;
if (params.pmtiles) {
inputFile = path.resolve(options.paths.pmtiles, params.pmtiles);
inputType = 'pmtiles';
} else if (params.mbtiles) {
inputFile = path.resolve(options.paths.mbtiles, params.mbtiles);
inputType = 'mbtiles';
}
let tileJSON = { let tileJSON = {
tiles: params.domains || options.domains, tiles: params.domains || options.domains,
}; };
const mbtilesFileStats = fs.statSync(mbtilesFile); const inputFileStats = fs.statSync(inputFile);
if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) { if (!inputFileStats.isFile() || inputFileStats.size === 0) {
throw Error(`Not valid MBTiles file: ${mbtilesFile}`); throw Error(`Not valid input file: ${inputFile}`);
} }
const extension = mbtilesFile.split('.').pop().toLowerCase();
let source; let source;
if (extension === 'pmtiles') { let source_type;
const info = await GetPMtilesInfo(mbtilesFile); if (inputType === 'pmtiles') {
const FileDescriptor = PMtilesOpen(inputFile);
const info = await GetPMtilesInfo(FileDescriptor);
const metadata = info.metadata; const metadata = info.metadata;
source = mbtilesFile; source = FileDescriptor;
source_type = 'pmtiles';
tileJSON['name'] = id; tileJSON['name'] = id;
tileJSON['format'] = 'pbf'; tileJSON['format'] = 'pbf';
@ -220,9 +236,10 @@ export const serve_data = {
if (options.dataDecoratorFunc) { if (options.dataDecoratorFunc) {
tileJSON = options.dataDecoratorFunc(id, 'tilejson', tileJSON); tileJSON = options.dataDecoratorFunc(id, 'tilejson', tileJSON);
} }
} else { } else if (inputType === 'mbtiles') {
source_type = 'mbtiles';
const sourceInfoPromise = new Promise((resolve, reject) => { const sourceInfoPromise = new Promise((resolve, reject) => {
source = new MBTiles(mbtilesFile + '?mode=ro', (err) => { source = new MBTiles(inputFile + '?mode=ro', (err) => {
if (err) { if (err) {
reject(err); reject(err);
return; return;
@ -261,6 +278,7 @@ export const serve_data = {
tileJSON, tileJSON,
publicUrl, publicUrl,
source, source,
source_type,
}; };
}, },
}; };

View file

@ -6,8 +6,9 @@ import path from 'path';
import url from 'url'; import url from 'url';
import util from 'util'; import util from 'util';
import zlib from 'zlib'; import zlib from 'zlib';
import sharp from 'sharp'; // sharp has to be required before node-canvas. see https://github.com/lovell/sharp/issues/371
import { createCanvas, Image } from 'canvas'; import { createCanvas, Image } from 'canvas';
import sharp from 'sharp'; // sharp has to be required before node-canvas on linux but after it on windows. see https://github.com/lovell/sharp/issues/371
//import { createCanvas, Image } from 'canvas';
import clone from 'clone'; import clone from 'clone';
import Color from 'color'; import Color from 'color';
import express from 'express'; import express from 'express';
@ -19,7 +20,12 @@ import polyline from '@mapbox/polyline';
import proj4 from 'proj4'; import proj4 from 'proj4';
import request from 'request'; import request from 'request';
import { getFontsPbf, getTileUrls, fixTileJSONCenter } from './utils.js'; import { getFontsPbf, getTileUrls, fixTileJSONCenter } from './utils.js';
import { GetPMtilesInfo, GetPMtilesTile } from './pmtiles_adapter.js'; import {
PMtilesOpen,
PMtilesClose,
GetPMtilesInfo,
GetPMtilesTile,
} from './pmtiles_adapter.js';
const FLOAT_PATTERN = '[+-]?(?:\\d+|\\d+.?\\d+)'; const FLOAT_PATTERN = '[+-]?(?:\\d+|\\d+.?\\d+)';
const PATH_PATTERN = const PATH_PATTERN =
@ -1211,6 +1217,7 @@ export const serve_rendered = {
renderers: [], renderers: [],
renderers_static: [], renderers_static: [],
sources: {}, sources: {},
source_types: {},
}; };
let styleJSON; let styleJSON;
@ -1221,7 +1228,7 @@ export const serve_rendered = {
ratio: ratio, ratio: ratio,
request: async (req, callback) => { request: async (req, callback) => {
const protocol = req.url.split(':')[0]; const protocol = req.url.split(':')[0];
console.log('Handling request:', req); // console.log('Handling request:', req);
if (protocol === 'sprites') { if (protocol === 'sprites') {
const dir = options.paths[protocol]; const dir = options.paths[protocol];
const file = unescape(req.url).substring(protocol.length + 3); const file = unescape(req.url).substring(protocol.length + 3);
@ -1246,10 +1253,11 @@ export const serve_rendered = {
callback(err, { data: null }); callback(err, { data: null });
}, },
); );
} else if (protocol === 'mbtiles') { } else if (protocol === 'mbtiles' || protocol === 'pmtiles') {
const parts = req.url.split('/'); const parts = req.url.split('/');
const sourceId = parts[2]; const sourceId = parts[2];
const source = map.sources[sourceId]; const source = map.sources[sourceId];
const source_type = map.source_types[sourceId];
const sourceInfo = styleJSON.sources[sourceId]; const sourceInfo = styleJSON.sources[sourceId];
const z = parts[3] | 0; const z = parts[3] | 0;
@ -1257,17 +1265,8 @@ export const serve_rendered = {
const y = parts[5].split('.')[0] | 0; const y = parts[5].split('.')[0] | 0;
const format = parts[5].split('.')[1]; const format = parts[5].split('.')[1];
if ( if (source_type === 'pmtiles') {
typeof map.sources[sourceId] === 'string' && let tileinfo = await GetPMtilesTile(source, z, x, y);
map.sources[sourceId].split('.').pop().toLowerCase() ===
'pmtiles'
) {
let tileinfo = await GetPMtilesTile(
map.sources[sourceId],
z,
x,
y,
);
let data = tileinfo.data; let data = tileinfo.data;
let headers = tileinfo.header; let headers = tileinfo.header;
if (data == undefined) { if (data == undefined) {
@ -1301,7 +1300,7 @@ export const serve_rendered = {
callback(null, response); callback(null, response);
} }
} else { } else if (source_type === 'mbtiles') {
source.getTile(z, x, y, (err, data, headers) => { source.getTile(z, x, y, (err, data, headers) => {
if (err) { if (err) {
if (options.verbose) if (options.verbose)
@ -1463,39 +1462,46 @@ export const serve_rendered = {
const queue = []; const queue = [];
for (const name of Object.keys(styleJSON.sources)) { for (const name of Object.keys(styleJSON.sources)) {
let source = styleJSON.sources[name]; const source = styleJSON.sources[name];
const url = source.url; const url = source.url;
let source_type;
if (url && url.lastIndexOf('mbtiles:', 0) === 0) { if (url && url.lastIndexOf('mbtiles:', 0) === 0) {
// found mbtiles source, replace with info from local file // found mbtiles source, replace with info from local file
delete source.url; delete source.url;
let mbtilesFile = url.substring('mbtiles://'.length); let inputFile = url.replace('pmtiles://', '').replace('mbtiles://', '');
const fromData = const fromData =
mbtilesFile[0] === '{' && mbtilesFile[mbtilesFile.length - 1] === '}'; inputFile[0] === '{' && inputFile[inputFile.length - 1] === '}';
if (fromData) { if (fromData) {
mbtilesFile = mbtilesFile.substr(1, mbtilesFile.length - 2); inputFile = inputFile.substr(1, inputFile.length - 2);
const mapsTo = (params.mapping || {})[mbtilesFile]; const mapsTo = (params.mapping || {})[inputFile];
if (mapsTo) { if (mapsTo) {
mbtilesFile = mapsTo; inputFile = mapsTo;
} }
mbtilesFile = dataResolver(mbtilesFile);
if (!mbtilesFile) { const DataInfo = dataResolver(inputFile);
console.error(`ERROR: data "${mbtilesFile}" not found!`); if (DataInfo.inputfile) {
inputFile = DataInfo.inputfile;
source_type = DataInfo.filetype;
} else {
console.error(`ERROR: data "${inputFile}" not found!`);
process.exit(1); process.exit(1);
} }
} }
const mbtilesFileStats = fs.statSync(mbtilesFile); const inputFileStats = fs.statSync(inputFile);
if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) { if (!inputFileStats.isFile() || inputFileStats.size === 0) {
throw Error(`Not valid MBTiles file: ${mbtilesFile}`); throw Error(`Not valid MBTiles file: ${inputFile}`);
} }
const extension = mbtilesFile.split('.').pop().toLowerCase();
if (extension === 'pmtiles') { if (source_type === 'pmtiles') {
const info = await GetPMtilesInfo(mbtilesFile); let FileDescriptor = PMtilesOpen(inputFile);
const info = await GetPMtilesInfo(FileDescriptor);
const metadata = info.metadata; const metadata = info.metadata;
map.sources[metadata.name.toLowerCase()] = mbtilesFile; map.sources[metadata.name.toLowerCase()] = FileDescriptor;
map.source_types[metadata.name.toLowerCase()] = 'pmtiles';
if (!repoobj.dataProjWGStoInternalWGS && metadata.proj4) { if (!repoobj.dataProjWGStoInternalWGS && metadata.proj4) {
// how to do this for multiple sources with different proj4 defs? // how to do this for multiple sources with different proj4 defs?
@ -1514,7 +1520,6 @@ export const serve_rendered = {
`mbtiles://${name}/{z}/{x}/{y}.${metadata.format || 'pbf'}`, `mbtiles://${name}/{z}/{x}/{y}.${metadata.format || 'pbf'}`,
]; ];
delete source.scheme; delete source.scheme;
//console.log(source);
if ( if (
!attributionOverride && !attributionOverride &&
@ -1531,19 +1536,18 @@ export const serve_rendered = {
} else { } else {
queue.push( queue.push(
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
mbtilesFile = path.resolve(options.paths.mbtiles, mbtilesFile); inputFile = path.resolve(options.paths.mbtiles, inputFile);
const mbtilesFileStats = fs.statSync(mbtilesFile); const inputFileStats = fs.statSync(inputFile);
if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) { if (!inputFileStats.isFile() || inputFileStats.size === 0) {
throw Error(`Not valid MBTiles file: ${mbtilesFile}`); throw Error(`Not valid MBTiles file: ${inputFile}`);
} }
map.sources[name] = new MBTiles( map.sources[name] = new MBTiles(inputFile + '?mode=ro', (err) => {
mbtilesFile + '?mode=ro',
(err) => {
map.sources[name].getInfo((err, info) => { map.sources[name].getInfo((err, info) => {
if (err) { if (err) {
console.error(err); console.error(err);
return; return;
} }
map.source_types[name] = 'mbtiles';
if (!repoobj.dataProjWGStoInternalWGS && info.proj4) { if (!repoobj.dataProjWGStoInternalWGS && info.proj4) {
// how to do this for multiple sources with different proj4 defs? // how to do this for multiple sources with different proj4 defs?
@ -1585,8 +1589,7 @@ export const serve_rendered = {
} }
resolve(); resolve();
}); });
}, });
);
}), }),
); );
} }

View file

@ -111,19 +111,26 @@ export const serve_style = {
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;
if (url && url.lastIndexOf('mbtiles:', 0) === 0) { if (
let mbtilesFile = url.substring('mbtiles://'.length); url &&
(url.lastIndexOf('pmtiles:', 0) === 0 ||
url.lastIndexOf('mbtiles:', 0) === 0)
) {
let inputSource = url
.replace('pmtiles://', '')
.replace('mbtiles://', '');
const fromData = const fromData =
mbtilesFile[0] === '{' && mbtilesFile[mbtilesFile.length - 1] === '}'; inputSource[0] === '{' && inputSource[inputSource.length - 1] === '}';
if (fromData) { if (fromData) {
mbtilesFile = mbtilesFile.substr(1, mbtilesFile.length - 2); inputSource = inputSource.substr(1, inputSource.length - 2);
const mapsTo = (params.mapping || {})[mbtilesFile]; const mapsTo = (params.mapping || {})[inputSource];
if (mapsTo) { if (mapsTo) {
mbtilesFile = mapsTo; inputSource = mapsTo;
} }
} }
const identifier = reportTiles(mbtilesFile, fromData); const identifier = reportTiles(inputSource, fromData);
if (!identifier) { if (!identifier) {
return false; return false;
} }

View file

@ -181,15 +181,28 @@ function start(opts) {
item, item,
id, id,
opts.publicUrl, opts.publicUrl,
(mbtiles, fromData) => { (fileid, fromData) => {
let dataItemId; let dataItemId;
for (const id of Object.keys(data)) { for (const id of Object.keys(data)) {
if (fromData) { if (fromData) {
if (id === mbtiles) { if (id === fileid) {
dataItemId = id; dataItemId = id;
} }
} else { } else {
if (data[id].mbtiles === mbtiles) { if (
data[id].mbtiles !== undefined &&
data[id].mbtiles === fileid
) {
dataItemId = id;
} else if (
data[id].pmtiles !== undefined &&
data[id].pmtiles === fileid
) {
dataItemId = id;
} else if (
data[id].filename !== undefined &&
data[id].filename === fileid
) {
dataItemId = id; dataItemId = id;
} }
} }
@ -200,14 +213,14 @@ function start(opts) {
} else { } else {
if (fromData || !allowMoreData) { if (fromData || !allowMoreData) {
console.log( console.log(
`ERROR: style "${item.style}" using unknown mbtiles "${mbtiles}"! Skipping...`, `ERROR: style "${item.style}" using unknown mbtiles "${fileid}"! Skipping...`,
); );
return undefined; return undefined;
} else { } else {
let id = mbtiles.substr(0, mbtiles.lastIndexOf('.')) || mbtiles; let id = fileid.substr(0, fileid.lastIndexOf('.')) || fileid;
while (data[id]) id += '_'; while (data[id]) id += '_';
data[id] = { data[id] = {
mbtiles: mbtiles, filename: fileid,
}; };
return id; return id;
} }
@ -229,14 +242,24 @@ function start(opts) {
item, item,
id, id,
opts.publicUrl, opts.publicUrl,
(mbtiles) => { (fileid) => {
let mbtilesFile; let inputFile;
let fileType;
for (const id of Object.keys(data)) { for (const id of Object.keys(data)) {
if (id === mbtiles) { if (id === fileid) {
mbtilesFile = data[id].mbtiles; if (data[id].pmtiles !== undefined) {
inputFile = data[id].pmtiles;
fileType = 'pmtiles';
} else if (data[id].mbtiles !== undefined) {
inputFile = data[id].mbtiles;
fileType = 'mbtiles';
} else if (data[id].filename !== undefined) {
inputFile = data[id].fileid;
fileType = inputFile.split('.').pop().toLowerCase();
} }
} }
return mbtilesFile; }
return { inputfile: inputFile, filetype: fileType };
}, },
), ),
); );
@ -264,8 +287,12 @@ function start(opts) {
for (const id of Object.keys(data)) { for (const id of Object.keys(data)) {
const item = data[id]; const item = data[id];
if (!item.mbtiles || item.mbtiles.length === 0) { if (item.pmtiles && item.pmtiles.length !== 0) {
console.log(`Missing "mbtiles" property for ${id}`); // valid pmtiles
} else if (item.mbtiles && item.mbtiles.length !== 0) {
// valid mbtiles
} else {
console.log(`Missing "pmtiles" or "mbtiles" property for ${id}`);
continue; continue;
} }