diff --git a/js/src/adapters.ts b/js/src/adapters.ts index b0e67f0c..bd89255f 100644 --- a/js/src/adapters.ts +++ b/js/src/adapters.ts @@ -33,9 +33,12 @@ export const leafletRasterLayer = (source: PMTiles, options: unknown) => { }; if (!loaded) { source.getHeader().then((header) => { - if (header.tileType === TileType.Mvt) { + if ( + header.tileType === TileType.Mvt || + header.tileType === TileType.Mlt + ) { console.error( - "Error: archive contains MVT vector tiles, but leafletRasterLayer is for displaying raster tiles. See https://github.com/protomaps/PMTiles/tree/main/js for details." + "Error: archive contains vector tiles, but leafletRasterLayer is for displaying raster tiles. See https://github.com/protomaps/PMTiles/tree/main/js for details." ); } else if (header.tileType === 2) { mimeType = "image/png"; @@ -267,7 +270,7 @@ export class Protocol { }; } const header = await instance.getHeader(); - if (header.tileType === TileType.Mvt) { + if (header.tileType === TileType.Mvt || header.tileType === TileType.Mlt) { if (this.errorOnMissingTile) { throw new Error("Tile not found."); } diff --git a/js/test/adapter.test.ts b/js/test/adapter.test.ts index 5d6f61cb..a6f0b501 100644 --- a/js/test/adapter.test.ts +++ b/js/test/adapter.test.ts @@ -44,7 +44,7 @@ describe("Protocol", () => { assert.strictEqual(result.data.length, 49); }); - test("returns empty data for missing tile if errorOnMissingTile is false", async () => { + test("returns empty data for missing MVT tile if errorOnMissingTile is false", async () => { const pmtiles = new PMTiles("http://localhost:1337/example.pmtiles"); const protocol = new Protocol({ errorOnMissingTile: false }); protocol.add(pmtiles); @@ -61,7 +61,7 @@ describe("Protocol", () => { assert.strictEqual(result.data.length, 0); }); - test("throws error for missing tile if errorOnMissingTile is true", async () => { + test("throws error for missing MVT tile if errorOnMissingTile is true", async () => { const pmtiles = new PMTiles("http://localhost:1337/example.pmtiles"); const protocol = new Protocol({ errorOnMissingTile: true }); protocol.add(pmtiles); @@ -77,6 +77,39 @@ describe("Protocol", () => { assert.rejects(promise, { message: "Tile not found." }); }); + test("returns empty data for missing MLT tile if errorOnMissingTile is false", async () => { + const pmtiles = new PMTiles("http://localhost:1337/mlt.pmtiles"); + const protocol = new Protocol({ errorOnMissingTile: false }); + protocol.add(pmtiles); + + const result = await protocol.tilev4( + { + url: "pmtiles://http://localhost:1337/mlt.pmtiles/25/0/0", + type: "arrayBuffer", + }, + new AbortController() + ); + + assert.ok(result.data instanceof Uint8Array); + assert.strictEqual(result.data.length, 0); + }); + + test("throws error for missing MLT tile if errorOnMissingTile is true", async () => { + const pmtiles = new PMTiles("http://localhost:1337/mlt.pmtiles"); + const protocol = new Protocol({ errorOnMissingTile: true }); + protocol.add(pmtiles); + + const promise = protocol.tilev4( + { + url: "pmtiles://http://localhost:1337/mlt.pmtiles/25/0/0", + type: "arrayBuffer", + }, + new AbortController() + ); + + assert.rejects(promise, { message: "Tile not found." }); + }); + test("throws AbortError when AbortController is signaled while accessing TileJSON", async () => { const pmtiles = new PMTiles("http://localhost:1337/example.pmtiles"); const protocol = new Protocol(); diff --git a/js/test/data/test_fixture_mlt.pmtiles b/js/test/data/test_fixture_mlt.pmtiles new file mode 100644 index 00000000..f5d4c7eb Binary files /dev/null and b/js/test/data/test_fixture_mlt.pmtiles differ diff --git a/js/test/utils.ts b/js/test/utils.ts index d70d752a..f9928838 100644 --- a/js/test/utils.ts +++ b/js/test/utils.ts @@ -20,6 +20,9 @@ class MockServer { this.etag = undefined; this.lastRequestHeaders = null; const serverBuffer = fs.readFileSync("test/data/test_fixture_1.pmtiles"); + const serverBufferMlt = fs.readFileSync( + "test/data/test_fixture_mlt.pmtiles" + ); const server = setupServer( http.get( "http://localhost:1337/example.pmtiles", @@ -65,6 +68,24 @@ class MockServer { status: 206, headers: { etag: this.etag } as HeadersInit, }); + }), + http.get("http://localhost:1337/mlt.pmtiles", ({ request, params }) => { + this.lastCache = request.cache; + this.lastRequestHeaders = request.headers; + this.lastCredentials = request.credentials; + this.numRequests++; + const range = request.headers.get("range")?.substr(6).split("-"); + if (!range) { + throw new Error("invalid range"); + } + const offset = +range[0]; + const length = +range[1]; + const body = serverBufferMlt.slice(offset, offset + length - 1); + return new HttpResponse(body, { + status: 206, + statusText: "OK", + headers: { etag: this.etag } as HeadersInit, + }); }) ); server.listen({ onUnhandledRequest: "error" });