MapComplete/scripts/serverPmTileExtracts.ts

82 lines
3.4 KiB
TypeScript
Raw Normal View History

import { Server } from "./server"
import Script from "./Script"
import { OfflineBasemapManager } from "../src/Logic/OfflineBasemapManager"
import http from "node:http"
import { ServerResponse } from "http"
2025-09-26 13:51:12 +02:00
import { existsSync, statSync, writeFileSync } from "fs"
import ScriptUtils from "./ScriptUtils"
import { PmTilesExtractGenerator } from "./pmTilesExtractGenerator"
class ServerPmTileExtracts extends Script {
2025-09-26 13:51:12 +02:00
private static FILE_IS_STALE_AFTER_SEC = 30 * 24 * 60 * 60
constructor() {
super("Starts a server that serves PMtiles. Usage:\n" +
"sourceFile cachedir [portnumber??2346]")
}
async main(args: string[]): Promise<void> {
if(args.length < 2){
this.printHelp()
2025-09-26 02:09:12 +02:00
throw ("!!! Please, specify a source- and cachedir !!!")
}
const sourcefile = args[0]
const targetDir = args[1]
const port = Number(args[2] ?? "2346")
const zoomlevels = OfflineBasemapManager.zoomelevels
const generator = new PmTilesExtractGenerator(sourcefile, targetDir)
2025-09-26 13:51:12 +02:00
const creationDates = new Map<string, Date>()
new Server(port, {},
[
{
mustMatch: /\d+\/\d+\/\d+.pmtiles/,
unmanaged: true,
mimetype: "application/octet-stream",
handle: async (path: string,
queryParams: URLSearchParams,
req: http.IncomingMessage,
body: string,
res: ServerResponse) => {
const [z,x,y] = path.split(".")[0].split("/").map(x => Number(x))
2025-09-26 02:34:10 +02:00
if(!(z in zoomlevels)){
throw `Invalid zoomlevel ${z} (x: ${x}, y: ${y}, must be one of ${Array.from(Object.keys(zoomlevels)).join(", ")}`
}
const targetFile = generator.getFilename(z, x, y)
2025-09-26 13:51:12 +02:00
let targetCreationDate = creationDates.get(targetFile)
let isStale = targetCreationDate === undefined ? false : new Date().getTime() - targetCreationDate.getTime() > 1000 * ServerPmTileExtracts.FILE_IS_STALE_AFTER_SEC
if (isStale || !existsSync(targetFile)) {
ScriptUtils.createParentDir(targetFile)
console.log("Creating", targetFile)
2025-09-26 13:51:12 +02:00
const start = new Date()
await generator.generateArchive(z, x, y)
2025-09-26 13:51:12 +02:00
const stop = new Date()
console.log("Creating ", targetFile, "took", (stop.getTime() - start.getTime()) + "ms")
} else if (targetCreationDate === undefined) {
const stats = statSync(targetFile)
creationDates.set(targetFile, stats.mtime)
}
2025-09-26 13:51:12 +02:00
if(req.destroyed){
return null
}
2025-09-26 14:06:45 +02:00
const origin = req.headers.origin
res.writeHead(200, { "Content-Type": "application/octet-stream" , "Access-Control-Allow-Origin": origin})
Server.sendFile(targetFile, res)
return null
},
},
],
)
}
}
new ServerPmTileExtracts().run()