import { Server } from "./server" import Script from "./Script" import { OfflineBasemapManager } from "../src/Logic/OfflineBasemapManager" import http from "node:http" import { ServerResponse } from "http" import { existsSync, statSync, writeFileSync } from "fs" import ScriptUtils from "./ScriptUtils" import { PmTilesExtractGenerator } from "./pmTilesExtractGenerator" class ServerPmTileExtracts extends Script { 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 { if(args.length < 2){ this.printHelp() 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) const creationDates = new Map() 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)) 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) 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) const start = new Date() await generator.generateArchive(z, x, y) 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) } if(req.destroyed){ return null } res.writeHead(200, { "Content-Type": "application/octet-stream" , "Access-Control-Allow-Origin": "*"}) Server.sendFile(targetFile, res) return null }, }, ], ) } } new ServerPmTileExtracts().run()