mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 10:51:07 +00:00
Support for both maplibre v3 and v4 addProtocol. (#339)
Adds support for MapLibre v4.x, which changed the addProtocol interface. This remains backwards-compatible with MapLibre v3.x and earlier.
This commit is contained in:
133
js/adapters.ts
133
js/adapters.ts
@@ -85,6 +85,19 @@ export const leafletRasterLayer = (source: PMTiles, options: unknown) => {
|
|||||||
return new cls(options);
|
return new cls(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type GetResourceResponse<T> = ExpiryData & {
|
||||||
|
data: T;
|
||||||
|
};
|
||||||
|
type AddProtocolAction = (
|
||||||
|
requestParameters: RequestParameters,
|
||||||
|
abortController: AbortController
|
||||||
|
) => Promise<GetResourceResponse<unknown>>;
|
||||||
|
|
||||||
|
type ExpiryData = {
|
||||||
|
cacheControl?: string | null;
|
||||||
|
expires?: string | null; // MapLibre can be a Date object
|
||||||
|
};
|
||||||
|
|
||||||
// copied from MapLibre /util/ajax.ts
|
// copied from MapLibre /util/ajax.ts
|
||||||
type RequestParameters = {
|
type RequestParameters = {
|
||||||
url: string;
|
url: string;
|
||||||
@@ -96,15 +109,50 @@ type RequestParameters = {
|
|||||||
collectResourceTiming?: boolean;
|
collectResourceTiming?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ResponseCallback = (
|
// for legacy maplibre-3 interop
|
||||||
error?: Error | null,
|
type ResponseCallbackV3 = (
|
||||||
data?: unknown | null,
|
error?: Error | undefined,
|
||||||
cacheControl?: string | null,
|
data?: unknown | undefined,
|
||||||
expires?: string | null
|
cacheControl?: string | undefined,
|
||||||
|
expires?: string | undefined
|
||||||
) => void;
|
) => void;
|
||||||
|
|
||||||
type Cancelable = {
|
type V3OrV4Protocol = <
|
||||||
cancel: () => void;
|
T extends AbortController | ResponseCallbackV3,
|
||||||
|
R = T extends AbortController
|
||||||
|
? Promise<GetResourceResponse<unknown>>
|
||||||
|
: { cancel: () => void },
|
||||||
|
>(
|
||||||
|
requestParameters: RequestParameters,
|
||||||
|
arg2: T
|
||||||
|
) => R;
|
||||||
|
|
||||||
|
const v3compat =
|
||||||
|
(v4: AddProtocolAction): V3OrV4Protocol =>
|
||||||
|
(requestParameters, arg2) => {
|
||||||
|
if (arg2 instanceof AbortController) {
|
||||||
|
// biome-ignore lint: overloading return type not handled by compiler
|
||||||
|
return v4(requestParameters, arg2) as any;
|
||||||
|
}
|
||||||
|
const abortController = new AbortController();
|
||||||
|
v4(requestParameters, abortController)
|
||||||
|
.then(
|
||||||
|
(result) => {
|
||||||
|
return arg2(
|
||||||
|
undefined,
|
||||||
|
result.data,
|
||||||
|
result.cacheControl || "",
|
||||||
|
result.expires || ""
|
||||||
|
);
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
return arg2(err);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.catch((e) => {
|
||||||
|
return arg2(e);
|
||||||
|
});
|
||||||
|
return { cancel: () => abortController.abort() };
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Protocol {
|
export class Protocol {
|
||||||
@@ -122,10 +170,10 @@ export class Protocol {
|
|||||||
return this.tiles.get(url);
|
return this.tiles.get(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
tile = (
|
tilev4 = async (
|
||||||
params: RequestParameters,
|
params: RequestParameters,
|
||||||
callback: ResponseCallback
|
abortController: AbortController
|
||||||
): Cancelable => {
|
) => {
|
||||||
if (params.type === "json") {
|
if (params.type === "json") {
|
||||||
const pmtilesUrl = params.url.substr(10);
|
const pmtilesUrl = params.url.substr(10);
|
||||||
let instance = this.tiles.get(pmtilesUrl);
|
let instance = this.tiles.get(pmtilesUrl);
|
||||||
@@ -134,23 +182,15 @@ export class Protocol {
|
|||||||
this.tiles.set(pmtilesUrl, instance);
|
this.tiles.set(pmtilesUrl, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance
|
const h = await instance.getHeader();
|
||||||
.getHeader()
|
|
||||||
.then((h) => {
|
return {
|
||||||
const tilejson = {
|
data: {
|
||||||
tiles: [`${params.url}/{z}/{x}/{y}`],
|
tiles: [`${params.url}/{z}/{x}/{y}`],
|
||||||
minzoom: h.minZoom,
|
minzoom: h.minZoom,
|
||||||
maxzoom: h.maxZoom,
|
maxzoom: h.maxZoom,
|
||||||
bounds: [h.minLon, h.minLat, h.maxLon, h.maxLat],
|
bounds: [h.minLon, h.minLat, h.maxLon, h.maxLat],
|
||||||
};
|
},
|
||||||
callback(null, tilejson, null, null);
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
callback(e, null, null, null);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
cancel: () => {},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const re = new RegExp(/pmtiles:\/\/(.+)\/(\d+)\/(\d+)\/(\d+)/);
|
const re = new RegExp(/pmtiles:\/\/(.+)\/(\d+)\/(\d+)\/(\d+)/);
|
||||||
@@ -169,39 +209,20 @@ export class Protocol {
|
|||||||
const x = result[3];
|
const x = result[3];
|
||||||
const y = result[4];
|
const y = result[4];
|
||||||
|
|
||||||
const controller = new AbortController();
|
const header = await instance.getHeader();
|
||||||
const signal = controller.signal;
|
const resp = await instance?.getZxy(+z, +x, +y, abortController.signal);
|
||||||
const cancel = () => {
|
if (resp) {
|
||||||
controller.abort();
|
return {
|
||||||
|
data: new Uint8Array(resp.data),
|
||||||
|
cacheControl: resp.cacheControl,
|
||||||
|
expires: resp.expires,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (header.tileType === TileType.Mvt) {
|
||||||
|
return { data: new Uint8Array() };
|
||||||
|
}
|
||||||
|
return { data: null };
|
||||||
};
|
};
|
||||||
|
|
||||||
instance.getHeader().then((header) => {
|
tile = v3compat(this.tilev4);
|
||||||
instance
|
|
||||||
?.getZxy(+z, +x, +y, signal)
|
|
||||||
.then((resp) => {
|
|
||||||
if (resp) {
|
|
||||||
callback(
|
|
||||||
null,
|
|
||||||
new Uint8Array(resp.data),
|
|
||||||
resp.cacheControl,
|
|
||||||
resp.expires
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if (header.tileType === TileType.Mvt) {
|
|
||||||
callback(null, new Uint8Array(), null, null);
|
|
||||||
} else {
|
|
||||||
callback(null, null, null, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((e) => {
|
|
||||||
if ((e as Error).name !== "AbortError") {
|
|
||||||
callback(e, null, null, null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return {
|
|
||||||
cancel: cancel,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user