feat: allow 'pmtiles:' in configs. open file less
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
This commit is contained in:
parent
98995ab1be
commit
0b99d8ddd1
6 changed files with 223 additions and 154 deletions
67
src/main.js
67
src/main.js
|
|
@ -8,7 +8,11 @@ import { fileURLToPath } from 'url';
|
|||
import request from 'request';
|
||||
import { server } from './server.js';
|
||||
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 __dirname = path.dirname(__filename);
|
||||
|
|
@ -80,18 +84,18 @@ const startServer = (configPath, config) => {
|
|||
});
|
||||
};
|
||||
|
||||
const startWithInputFile = async (inputfile) => {
|
||||
console.log(`[INFO] Automatically creating config file for ${inputfile}`);
|
||||
const startWithinputFile = async (inputFile) => {
|
||||
console.log(`[INFO] Automatically creating config file for ${inputFile}`);
|
||||
console.log(`[INFO] Only a basic preview style will be used.`);
|
||||
console.log(
|
||||
`[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);
|
||||
if (!inputfileStats.isFile() || inputfileStats.size === 0) {
|
||||
console.log(`ERROR: Not a valid input file: ${inputfile}`);
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
console.log(`ERROR: Not a valid input file: ${inputFile}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
|
@ -106,24 +110,27 @@ const startWithInputFile = async (inputfile) => {
|
|||
root: styleDir,
|
||||
fonts: 'fonts',
|
||||
styles: 'styles',
|
||||
mbtiles: path.dirname(inputfile),
|
||||
mbtiles: path.dirname(inputFile),
|
||||
pmtiles: path.dirname(inputFile),
|
||||
},
|
||||
},
|
||||
styles: {},
|
||||
data: {},
|
||||
};
|
||||
|
||||
const extension = inputfile.split('.').pop().toLowerCase();
|
||||
const extension = inputFile.split('.').pop().toLowerCase();
|
||||
if (extension === 'pmtiles') {
|
||||
const info = await GetPMtilesInfo(inputfile);
|
||||
const FileDescriptor = PMtilesOpen(inputFile);
|
||||
const info = await GetPMtilesInfo(FileDescriptor);
|
||||
const metadata = info.metadata;
|
||||
PMtilesClose(FileDescriptor);
|
||||
|
||||
if (
|
||||
metadata.format === 'pbf' &&
|
||||
metadata.name.toLowerCase().indexOf('openmaptiles') > -1
|
||||
) {
|
||||
config['data'][`v3`] = {
|
||||
mbtiles: path.basename(inputfile),
|
||||
pmtiles: path.basename(inputFile),
|
||||
};
|
||||
|
||||
const styles = fs.readdirSync(path.resolve(styleDir, 'styles'));
|
||||
|
|
@ -143,8 +150,8 @@ const startWithInputFile = async (inputfile) => {
|
|||
console.log(
|
||||
`WARN: PMTiles not in "openmaptiles" format. Serving raw data only...`,
|
||||
);
|
||||
config['data'][(metadata.id || 'mbtiles').replace(/[?/:]/g, '_')] = {
|
||||
mbtiles: path.basename(inputfile),
|
||||
config['data'][(metadata.id || 'pmtiles').replace(/[?/:]/g, '_')] = {
|
||||
pmtiles: path.basename(inputFile),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -156,10 +163,10 @@ const startWithInputFile = async (inputfile) => {
|
|||
|
||||
return startServer(null, config);
|
||||
} else {
|
||||
const instance = new MBTiles(inputfile + '?mode=ro', (err) => {
|
||||
const instance = new MBTiles(inputFile + '?mode=ro', (err) => {
|
||||
if (err) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +174,7 @@ const startWithInputFile = async (inputfile) => {
|
|||
if (err || !info) {
|
||||
console.log('ERROR: Metadata missing in the MBTiles.');
|
||||
console.log(
|
||||
`Make sure ${path.basename(inputfile)} is valid MBTiles.`,
|
||||
`Make sure ${path.basename(inputFile)} is valid MBTiles.`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
|
@ -178,7 +185,7 @@ const startWithInputFile = async (inputfile) => {
|
|||
info.name.toLowerCase().indexOf('openmaptiles') > -1
|
||||
) {
|
||||
config['data'][`v3`] = {
|
||||
mbtiles: path.basename(inputfile),
|
||||
mbtiles: path.basename(inputFile),
|
||||
};
|
||||
|
||||
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...`,
|
||||
);
|
||||
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) => {
|
||||
if (err || !stats.isFile() || stats.size === 0) {
|
||||
let inputfile;
|
||||
let inputFile;
|
||||
if (opts.file) {
|
||||
inputfile = opts.file;
|
||||
inputFile = opts.file;
|
||||
} else if (opts.mbtiles) {
|
||||
inputfile = opts.mbtiles;
|
||||
inputFile = opts.mbtiles;
|
||||
}
|
||||
|
||||
if (inputfile) {
|
||||
return startWithInputFile(inputfile);
|
||||
if (inputFile) {
|
||||
return startWithinputFile(inputFile);
|
||||
} else {
|
||||
// try to find in the cwd
|
||||
const files = fs.readdirSync(process.cwd());
|
||||
for (const filename of files) {
|
||||
if (filename.endsWith('.mbtiles') || filename.endsWith('.pmtiles')) {
|
||||
const InputFilesStats = fs.statSync(filename);
|
||||
if (InputFilesStats.isFile() && InputFilesStats.size > 0) {
|
||||
inputfile = filename;
|
||||
const inputFilesStats = fs.statSync(filename);
|
||||
if (inputFilesStats.isFile() && inputFilesStats.size > 0) {
|
||||
inputFile = filename;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inputfile) {
|
||||
console.log(`No input file specified, using ${inputfile}`);
|
||||
return startWithInputFile(inputfile);
|
||||
if (inputFile) {
|
||||
console.log(`No input file specified, using ${inputFile}`);
|
||||
return startWithinputFile(inputFile);
|
||||
} else {
|
||||
const url =
|
||||
'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);
|
||||
console.log(`No input file found`);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,25 @@
|
|||
import fs from 'node:fs';
|
||||
import PMTiles from 'pmtiles';
|
||||
|
||||
const PMTilesLocalSource = class {
|
||||
constructor(file) {
|
||||
this.file = file;
|
||||
export const PMtilesOpen = (FilePath) => {
|
||||
const fd = fs.openSync(FilePath, 'r');
|
||||
return fd;
|
||||
};
|
||||
|
||||
export const PMtilesClose = (fd) => {
|
||||
fs.closeSync(fd);
|
||||
};
|
||||
|
||||
const PMTilesFileDescriptorSource = class {
|
||||
constructor(fd) {
|
||||
this.fd = fd;
|
||||
}
|
||||
getKey() {
|
||||
return this.file.name;
|
||||
return this.fd;
|
||||
}
|
||||
async getBytes(offset, length) {
|
||||
const buffer = Buffer.alloc(length);
|
||||
const fd = fs.openSync(this.file, 'r'); //Open the file in read mode
|
||||
await ReadBytes(fd, buffer, offset); //Read the specifed bytes from the file
|
||||
fs.closeSync(fd); //close the file
|
||||
await ReadBytes(this.fd, buffer, offset);
|
||||
return { data: BufferToArrayBuffer(buffer) };
|
||||
}
|
||||
};
|
||||
|
|
@ -28,8 +35,8 @@ const ReadBytes = async (fd, buffer, offset) => {
|
|||
});
|
||||
};
|
||||
|
||||
export const GetPMtilesInfo = async (pmtilesFile) => {
|
||||
const source = new PMTilesLocalSource(pmtilesFile);
|
||||
export const GetPMtilesInfo = async (fd) => {
|
||||
const source = new PMTilesFileDescriptorSource(fd);
|
||||
const pmtiles = new PMTiles.PMTiles(source);
|
||||
const header = await pmtiles.getHeader();
|
||||
const metadata = await pmtiles.getMetadata();
|
||||
|
|
@ -47,8 +54,8 @@ export const GetPMtilesInfo = async (pmtilesFile) => {
|
|||
return { header: header, metadata: metadata };
|
||||
};
|
||||
|
||||
export const GetPMtilesTile = async (pmtilesFile, z, x, y) => {
|
||||
const source = new PMTilesLocalSource(pmtilesFile);
|
||||
export const GetPMtilesTile = async (fd, z, x, y) => {
|
||||
const source = new PMTilesFileDescriptorSource(fd);
|
||||
const pmtiles = new PMTiles.PMTiles(source);
|
||||
const header = await pmtiles.getHeader();
|
||||
const TileType = GetPmtilesTileType(header.tileType);
|
||||
|
|
|
|||
|
|
@ -11,7 +11,12 @@ import Pbf from 'pbf';
|
|||
import { VectorTile } from '@mapbox/vector-tile';
|
||||
|
||||
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 = {
|
||||
init: (options, repo) => {
|
||||
|
|
@ -187,22 +192,33 @@ export const serve_data = {
|
|||
return app;
|
||||
},
|
||||
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 = {
|
||||
tiles: params.domains || options.domains,
|
||||
};
|
||||
|
||||
const mbtilesFileStats = fs.statSync(mbtilesFile);
|
||||
if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) {
|
||||
throw Error(`Not valid MBTiles file: ${mbtilesFile}`);
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
throw Error(`Not valid input file: ${inputFile}`);
|
||||
}
|
||||
|
||||
const extension = mbtilesFile.split('.').pop().toLowerCase();
|
||||
let source;
|
||||
if (extension === 'pmtiles') {
|
||||
const info = await GetPMtilesInfo(mbtilesFile);
|
||||
let source_type;
|
||||
if (inputType === 'pmtiles') {
|
||||
const FileDescriptor = PMtilesOpen(inputFile);
|
||||
const info = await GetPMtilesInfo(FileDescriptor);
|
||||
const metadata = info.metadata;
|
||||
source = mbtilesFile;
|
||||
source = FileDescriptor;
|
||||
source_type = 'pmtiles';
|
||||
|
||||
tileJSON['name'] = id;
|
||||
tileJSON['format'] = 'pbf';
|
||||
|
|
@ -220,9 +236,10 @@ export const serve_data = {
|
|||
if (options.dataDecoratorFunc) {
|
||||
tileJSON = options.dataDecoratorFunc(id, 'tilejson', tileJSON);
|
||||
}
|
||||
} else {
|
||||
} else if (inputType === 'mbtiles') {
|
||||
source_type = 'mbtiles';
|
||||
const sourceInfoPromise = new Promise((resolve, reject) => {
|
||||
source = new MBTiles(mbtilesFile + '?mode=ro', (err) => {
|
||||
source = new MBTiles(inputFile + '?mode=ro', (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
return;
|
||||
|
|
@ -261,6 +278,7 @@ export const serve_data = {
|
|||
tileJSON,
|
||||
publicUrl,
|
||||
source,
|
||||
source_type,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ import path from 'path';
|
|||
import url from 'url';
|
||||
import util from 'util';
|
||||
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 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 Color from 'color';
|
||||
import express from 'express';
|
||||
|
|
@ -19,7 +20,12 @@ import polyline from '@mapbox/polyline';
|
|||
import proj4 from 'proj4';
|
||||
import request from 'request';
|
||||
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 PATH_PATTERN =
|
||||
|
|
@ -1211,6 +1217,7 @@ export const serve_rendered = {
|
|||
renderers: [],
|
||||
renderers_static: [],
|
||||
sources: {},
|
||||
source_types: {},
|
||||
};
|
||||
|
||||
let styleJSON;
|
||||
|
|
@ -1221,7 +1228,7 @@ export const serve_rendered = {
|
|||
ratio: ratio,
|
||||
request: async (req, callback) => {
|
||||
const protocol = req.url.split(':')[0];
|
||||
console.log('Handling request:', req);
|
||||
// console.log('Handling request:', req);
|
||||
if (protocol === 'sprites') {
|
||||
const dir = options.paths[protocol];
|
||||
const file = unescape(req.url).substring(protocol.length + 3);
|
||||
|
|
@ -1246,10 +1253,11 @@ export const serve_rendered = {
|
|||
callback(err, { data: null });
|
||||
},
|
||||
);
|
||||
} else if (protocol === 'mbtiles') {
|
||||
} else if (protocol === 'mbtiles' || protocol === 'pmtiles') {
|
||||
const parts = req.url.split('/');
|
||||
const sourceId = parts[2];
|
||||
const source = map.sources[sourceId];
|
||||
const source_type = map.source_types[sourceId];
|
||||
const sourceInfo = styleJSON.sources[sourceId];
|
||||
|
||||
const z = parts[3] | 0;
|
||||
|
|
@ -1257,17 +1265,8 @@ export const serve_rendered = {
|
|||
const y = parts[5].split('.')[0] | 0;
|
||||
const format = parts[5].split('.')[1];
|
||||
|
||||
if (
|
||||
typeof map.sources[sourceId] === 'string' &&
|
||||
map.sources[sourceId].split('.').pop().toLowerCase() ===
|
||||
'pmtiles'
|
||||
) {
|
||||
let tileinfo = await GetPMtilesTile(
|
||||
map.sources[sourceId],
|
||||
z,
|
||||
x,
|
||||
y,
|
||||
);
|
||||
if (source_type === 'pmtiles') {
|
||||
let tileinfo = await GetPMtilesTile(source, z, x, y);
|
||||
let data = tileinfo.data;
|
||||
let headers = tileinfo.header;
|
||||
if (data == undefined) {
|
||||
|
|
@ -1301,7 +1300,7 @@ export const serve_rendered = {
|
|||
|
||||
callback(null, response);
|
||||
}
|
||||
} else {
|
||||
} else if (source_type === 'mbtiles') {
|
||||
source.getTile(z, x, y, (err, data, headers) => {
|
||||
if (err) {
|
||||
if (options.verbose)
|
||||
|
|
@ -1463,39 +1462,46 @@ export const serve_rendered = {
|
|||
|
||||
const queue = [];
|
||||
for (const name of Object.keys(styleJSON.sources)) {
|
||||
let source = styleJSON.sources[name];
|
||||
const source = styleJSON.sources[name];
|
||||
const url = source.url;
|
||||
let source_type;
|
||||
|
||||
if (url && url.lastIndexOf('mbtiles:', 0) === 0) {
|
||||
// found mbtiles source, replace with info from local file
|
||||
delete source.url;
|
||||
|
||||
let mbtilesFile = url.substring('mbtiles://'.length);
|
||||
let inputFile = url.replace('pmtiles://', '').replace('mbtiles://', '');
|
||||
const fromData =
|
||||
mbtilesFile[0] === '{' && mbtilesFile[mbtilesFile.length - 1] === '}';
|
||||
inputFile[0] === '{' && inputFile[inputFile.length - 1] === '}';
|
||||
|
||||
if (fromData) {
|
||||
mbtilesFile = mbtilesFile.substr(1, mbtilesFile.length - 2);
|
||||
const mapsTo = (params.mapping || {})[mbtilesFile];
|
||||
inputFile = inputFile.substr(1, inputFile.length - 2);
|
||||
const mapsTo = (params.mapping || {})[inputFile];
|
||||
if (mapsTo) {
|
||||
mbtilesFile = mapsTo;
|
||||
inputFile = mapsTo;
|
||||
}
|
||||
mbtilesFile = dataResolver(mbtilesFile);
|
||||
if (!mbtilesFile) {
|
||||
console.error(`ERROR: data "${mbtilesFile}" not found!`);
|
||||
|
||||
const DataInfo = dataResolver(inputFile);
|
||||
if (DataInfo.inputfile) {
|
||||
inputFile = DataInfo.inputfile;
|
||||
source_type = DataInfo.filetype;
|
||||
} else {
|
||||
console.error(`ERROR: data "${inputFile}" not found!`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const mbtilesFileStats = fs.statSync(mbtilesFile);
|
||||
if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) {
|
||||
throw Error(`Not valid MBTiles file: ${mbtilesFile}`);
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
throw Error(`Not valid MBTiles file: ${inputFile}`);
|
||||
}
|
||||
const extension = mbtilesFile.split('.').pop().toLowerCase();
|
||||
if (extension === 'pmtiles') {
|
||||
const info = await GetPMtilesInfo(mbtilesFile);
|
||||
|
||||
if (source_type === 'pmtiles') {
|
||||
let FileDescriptor = PMtilesOpen(inputFile);
|
||||
const info = await GetPMtilesInfo(FileDescriptor);
|
||||
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) {
|
||||
// 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'}`,
|
||||
];
|
||||
delete source.scheme;
|
||||
//console.log(source);
|
||||
|
||||
if (
|
||||
!attributionOverride &&
|
||||
|
|
@ -1531,62 +1536,60 @@ export const serve_rendered = {
|
|||
} else {
|
||||
queue.push(
|
||||
new Promise((resolve, reject) => {
|
||||
mbtilesFile = path.resolve(options.paths.mbtiles, mbtilesFile);
|
||||
const mbtilesFileStats = fs.statSync(mbtilesFile);
|
||||
if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) {
|
||||
throw Error(`Not valid MBTiles file: ${mbtilesFile}`);
|
||||
inputFile = path.resolve(options.paths.mbtiles, inputFile);
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
throw Error(`Not valid MBTiles file: ${inputFile}`);
|
||||
}
|
||||
map.sources[name] = new MBTiles(
|
||||
mbtilesFile + '?mode=ro',
|
||||
(err) => {
|
||||
map.sources[name].getInfo((err, info) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
map.sources[name] = new MBTiles(inputFile + '?mode=ro', (err) => {
|
||||
map.sources[name].getInfo((err, info) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
map.source_types[name] = 'mbtiles';
|
||||
|
||||
if (!repoobj.dataProjWGStoInternalWGS && info.proj4) {
|
||||
// how to do this for multiple sources with different proj4 defs?
|
||||
const to3857 = proj4('EPSG:3857');
|
||||
const toDataProj = proj4(info.proj4);
|
||||
repoobj.dataProjWGStoInternalWGS = (xy) =>
|
||||
to3857.inverse(toDataProj.forward(xy));
|
||||
}
|
||||
if (!repoobj.dataProjWGStoInternalWGS && info.proj4) {
|
||||
// how to do this for multiple sources with different proj4 defs?
|
||||
const to3857 = proj4('EPSG:3857');
|
||||
const toDataProj = proj4(info.proj4);
|
||||
repoobj.dataProjWGStoInternalWGS = (xy) =>
|
||||
to3857.inverse(toDataProj.forward(xy));
|
||||
}
|
||||
|
||||
const type = source.type;
|
||||
info['extension'] = 'mbtiles';
|
||||
Object.assign(source, info);
|
||||
source.type = type;
|
||||
source.tiles = [
|
||||
// meta url which will be detected when requested
|
||||
`mbtiles://${name}/{z}/{x}/{y}.${info.format || 'pbf'}`,
|
||||
];
|
||||
delete source.scheme;
|
||||
const type = source.type;
|
||||
info['extension'] = 'mbtiles';
|
||||
Object.assign(source, info);
|
||||
source.type = type;
|
||||
source.tiles = [
|
||||
// meta url which will be detected when requested
|
||||
`mbtiles://${name}/{z}/{x}/{y}.${info.format || 'pbf'}`,
|
||||
];
|
||||
delete source.scheme;
|
||||
|
||||
if (options.dataDecoratorFunc) {
|
||||
source = options.dataDecoratorFunc(
|
||||
name,
|
||||
'tilejson',
|
||||
source,
|
||||
);
|
||||
}
|
||||
if (options.dataDecoratorFunc) {
|
||||
source = options.dataDecoratorFunc(
|
||||
name,
|
||||
'tilejson',
|
||||
source,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!attributionOverride &&
|
||||
source.attribution &&
|
||||
source.attribution.length > 0
|
||||
) {
|
||||
if (!tileJSON.attribution.includes(source.attribution)) {
|
||||
if (tileJSON.attribution.length > 0) {
|
||||
tileJSON.attribution += ' | ';
|
||||
}
|
||||
tileJSON.attribution += source.attribution;
|
||||
if (
|
||||
!attributionOverride &&
|
||||
source.attribution &&
|
||||
source.attribution.length > 0
|
||||
) {
|
||||
if (!tileJSON.attribution.includes(source.attribution)) {
|
||||
if (tileJSON.attribution.length > 0) {
|
||||
tileJSON.attribution += ' | ';
|
||||
}
|
||||
tileJSON.attribution += source.attribution;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,19 +111,26 @@ export const serve_style = {
|
|||
for (const name of Object.keys(styleJSON.sources)) {
|
||||
const source = styleJSON.sources[name];
|
||||
const url = source.url;
|
||||
if (url && url.lastIndexOf('mbtiles:', 0) === 0) {
|
||||
let mbtilesFile = url.substring('mbtiles://'.length);
|
||||
if (
|
||||
url &&
|
||||
(url.lastIndexOf('pmtiles:', 0) === 0 ||
|
||||
url.lastIndexOf('mbtiles:', 0) === 0)
|
||||
) {
|
||||
let inputSource = url
|
||||
.replace('pmtiles://', '')
|
||||
.replace('mbtiles://', '');
|
||||
|
||||
const fromData =
|
||||
mbtilesFile[0] === '{' && mbtilesFile[mbtilesFile.length - 1] === '}';
|
||||
inputSource[0] === '{' && inputSource[inputSource.length - 1] === '}';
|
||||
|
||||
if (fromData) {
|
||||
mbtilesFile = mbtilesFile.substr(1, mbtilesFile.length - 2);
|
||||
const mapsTo = (params.mapping || {})[mbtilesFile];
|
||||
inputSource = inputSource.substr(1, inputSource.length - 2);
|
||||
const mapsTo = (params.mapping || {})[inputSource];
|
||||
if (mapsTo) {
|
||||
mbtilesFile = mapsTo;
|
||||
inputSource = mapsTo;
|
||||
}
|
||||
}
|
||||
const identifier = reportTiles(mbtilesFile, fromData);
|
||||
const identifier = reportTiles(inputSource, fromData);
|
||||
if (!identifier) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -181,15 +181,28 @@ function start(opts) {
|
|||
item,
|
||||
id,
|
||||
opts.publicUrl,
|
||||
(mbtiles, fromData) => {
|
||||
(fileid, fromData) => {
|
||||
let dataItemId;
|
||||
for (const id of Object.keys(data)) {
|
||||
if (fromData) {
|
||||
if (id === mbtiles) {
|
||||
if (id === fileid) {
|
||||
dataItemId = id;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
|
@ -200,14 +213,14 @@ function start(opts) {
|
|||
} else {
|
||||
if (fromData || !allowMoreData) {
|
||||
console.log(
|
||||
`ERROR: style "${item.style}" using unknown mbtiles "${mbtiles}"! Skipping...`,
|
||||
`ERROR: style "${item.style}" using unknown mbtiles "${fileid}"! Skipping...`,
|
||||
);
|
||||
return undefined;
|
||||
} else {
|
||||
let id = mbtiles.substr(0, mbtiles.lastIndexOf('.')) || mbtiles;
|
||||
let id = fileid.substr(0, fileid.lastIndexOf('.')) || fileid;
|
||||
while (data[id]) id += '_';
|
||||
data[id] = {
|
||||
mbtiles: mbtiles,
|
||||
filename: fileid,
|
||||
};
|
||||
return id;
|
||||
}
|
||||
|
|
@ -229,14 +242,24 @@ function start(opts) {
|
|||
item,
|
||||
id,
|
||||
opts.publicUrl,
|
||||
(mbtiles) => {
|
||||
let mbtilesFile;
|
||||
(fileid) => {
|
||||
let inputFile;
|
||||
let fileType;
|
||||
for (const id of Object.keys(data)) {
|
||||
if (id === mbtiles) {
|
||||
mbtilesFile = data[id].mbtiles;
|
||||
if (id === fileid) {
|
||||
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)) {
|
||||
const item = data[id];
|
||||
if (!item.mbtiles || item.mbtiles.length === 0) {
|
||||
console.log(`Missing "mbtiles" property for ${id}`);
|
||||
if (item.pmtiles && item.pmtiles.length !== 0) {
|
||||
// valid pmtiles
|
||||
} else if (item.mbtiles && item.mbtiles.length !== 0) {
|
||||
// valid mbtiles
|
||||
} else {
|
||||
console.log(`Missing "pmtiles" or "mbtiles" property for ${id}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue