@maptrip/map-tiles 1.2.1 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/dist/api-extensions/leaflet/MapTripLeafletGridLayer.d.ts +11 -0
- package/dist/api-extensions/openlayers/MapTripOpenLayersSource.d.ts +7 -0
- package/dist/map-tiles.d.ts +2 -1
- package/dist/map-tiles.js +166 -5
- package/dist/map-tiles.js.map +1 -1
- package/dist/types/interfaces.d.ts +1 -0
- package/dist/util/MapReleaseFetcher.d.ts +10 -0
- package/lib/api-extensions/leaflet/MapTripLeafletGridLayer.ts +94 -3
- package/lib/api-extensions/openlayers/MapTripOpenLayersSource.ts +37 -1
- package/lib/core/VectorTileFactory.ts +1 -1
- package/lib/core/constants.ts +3 -2
- package/lib/main.ts +3 -0
- package/lib/types/interfaces.ts +1 -0
- package/lib/util/MapReleaseFetcher.ts +66 -0
- package/package.json +3 -2
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class MapReleaseFetcher {
|
|
2
|
+
private _token;
|
|
3
|
+
private _tomtom;
|
|
4
|
+
private _osm;
|
|
5
|
+
private _here;
|
|
6
|
+
constructor(token: string);
|
|
7
|
+
getRelease(provider: string): Promise<string | null | undefined>;
|
|
8
|
+
fetchAndExtractRelease(url: string): Promise<string | null>;
|
|
9
|
+
private extractTargetString;
|
|
10
|
+
}
|
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import L from "leaflet";
|
|
2
2
|
import { VectorTileFactory } from "../../core/VectorTileFactory.js";
|
|
3
3
|
import { MIN_ZOOM, MAX_ZOOM, ATTRIBUTION } from "../../core/constants.js";
|
|
4
|
+
import { MapReleaseFetcher } from "../../util/MapReleaseFetcher.js";
|
|
4
5
|
import type { PointXY } from "../../types/interfaces.js";
|
|
5
|
-
import {
|
|
6
|
-
RENDERING_CONFIG
|
|
7
|
-
} from "../../types/interfaces.js";
|
|
6
|
+
import { RENDERING_CONFIG } from "../../types/interfaces.js";
|
|
8
7
|
|
|
9
8
|
class MapTripLeafletGridLayer extends L.GridLayer {
|
|
10
9
|
MIN_ZOOM = MIN_ZOOM;
|
|
11
10
|
MAX_ZOOM = MAX_ZOOM;
|
|
12
11
|
token: string;
|
|
13
12
|
factory: VectorTileFactory;
|
|
13
|
+
releaseFetcher: MapReleaseFetcher;
|
|
14
|
+
provider: string;
|
|
15
|
+
attribution: string;
|
|
16
|
+
release: string;
|
|
17
|
+
releaseDate: boolean;
|
|
18
|
+
|
|
14
19
|
constructor(options: {
|
|
15
20
|
provider?: string;
|
|
16
21
|
baseMap?: boolean;
|
|
@@ -23,12 +28,33 @@ class MapTripLeafletGridLayer extends L.GridLayer {
|
|
|
23
28
|
attribution?: string;
|
|
24
29
|
minZoom?: number;
|
|
25
30
|
maxZoom?: number;
|
|
31
|
+
releaseDate?: boolean;
|
|
26
32
|
}) {
|
|
27
33
|
super(options as L.GridLayerOptions);
|
|
28
34
|
this.token = options.token!;
|
|
35
|
+
this.provider = options.provider
|
|
36
|
+
? options.provider?.toLowerCase()
|
|
37
|
+
: "openstreetmap";
|
|
38
|
+
|
|
29
39
|
this.options.attribution = options.attribution
|
|
30
40
|
? options.attribution
|
|
31
41
|
: ATTRIBUTION;
|
|
42
|
+
this.releaseFetcher = new MapReleaseFetcher(this.token);
|
|
43
|
+
this.release = "";
|
|
44
|
+
this.attribution = "";
|
|
45
|
+
|
|
46
|
+
this.releaseDate = options.releaseDate ? options.releaseDate : false;
|
|
47
|
+
if (this.releaseDate) {
|
|
48
|
+
this.initializeAttribution();
|
|
49
|
+
this.on("add", () => {
|
|
50
|
+
if (this._map) {
|
|
51
|
+
this._map.on("baselayerchange", (event) =>
|
|
52
|
+
this.onBaseLayerChange(event)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
|
|
32
58
|
//@ts-expect-error picking up LayerOptions rather than GridLayerOptions
|
|
33
59
|
this.options.minZoom = options.minZoom
|
|
34
60
|
? Math.max(this.MIN_ZOOM, options.minZoom)
|
|
@@ -37,12 +63,77 @@ class MapTripLeafletGridLayer extends L.GridLayer {
|
|
|
37
63
|
this.options.maxZoom = options.maxZoom
|
|
38
64
|
? Math.min(this.MAX_ZOOM, options.maxZoom)
|
|
39
65
|
: this.MAX_ZOOM;
|
|
66
|
+
|
|
40
67
|
this.factory = VectorTileFactory.createFactory(options);
|
|
41
68
|
}
|
|
42
69
|
|
|
43
70
|
createTile(coords: PointXY) {
|
|
44
71
|
return this.factory.getJsonTile(coords.z!, coords.x, coords.y, this.token);
|
|
45
72
|
}
|
|
73
|
+
|
|
74
|
+
private async initializeAttribution() {
|
|
75
|
+
await this.setRelease();
|
|
76
|
+
await this.setAttribution();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Set an original release
|
|
80
|
+
private async setRelease() {
|
|
81
|
+
const release = await this.releaseFetcher.getRelease(this.provider);
|
|
82
|
+
if (release) {
|
|
83
|
+
this.release = release;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private async setAttribution() {
|
|
88
|
+
if (!this._map) return;
|
|
89
|
+
try {
|
|
90
|
+
// check if base layer changes to a new provider
|
|
91
|
+
const newRelease = await this.releaseFetcher.getRelease(this.provider);
|
|
92
|
+
if (newRelease && newRelease !== this.release) {
|
|
93
|
+
this.release = newRelease;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// remove the original attribution in order to append the release date
|
|
97
|
+
this._map.attributionControl.removeAttribution(this.options.attribution!);
|
|
98
|
+
this.attribution = `${this.options.attribution} ${this.release}`;
|
|
99
|
+
this._map.attributionControl.addAttribution(this.attribution!);
|
|
100
|
+
|
|
101
|
+
// remove the attribution with release date from map for instances where different layers have different preferences for setting release date
|
|
102
|
+
const map = this._map;
|
|
103
|
+
this._map.addEventListener("baselayerchange", () => {
|
|
104
|
+
map.attributionControl.removeAttribution(this.attribution);
|
|
105
|
+
});
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error("Error fetching release version: ", error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private async onBaseLayerChange(event: L.LayersControlEvent) {
|
|
112
|
+
if (!this._map) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
this._map.attributionControl.removeAttribution(this.attribution);
|
|
117
|
+
|
|
118
|
+
//@ts-expect-error doesn't recognize provider in options object
|
|
119
|
+
const eventProvider = event.layer.options.provider;
|
|
120
|
+
let newProvider: string;
|
|
121
|
+
if (eventProvider) {
|
|
122
|
+
if (eventProvider.toLowerCase() === "opensreetmap") {
|
|
123
|
+
newProvider = "openstreetmap";
|
|
124
|
+
} else if (eventProvider.toLowerCase() === "tomtom") {
|
|
125
|
+
newProvider = "tomtom";
|
|
126
|
+
} else if (eventProvider.toLowerCase() === "here") {
|
|
127
|
+
newProvider = "here";
|
|
128
|
+
} else {
|
|
129
|
+
newProvider = "openstreetmap";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this.provider = newProvider;
|
|
133
|
+
|
|
134
|
+
await this.setAttribution();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
46
137
|
}
|
|
47
138
|
|
|
48
139
|
export { MapTripLeafletGridLayer };
|
|
@@ -4,10 +4,15 @@ import { XYZOptions, createXYZ, extentFromProjection } from "ol/tilegrid.js";
|
|
|
4
4
|
import { VectorTileFactory } from "../../core/VectorTileFactory.js";
|
|
5
5
|
import { MIN_ZOOM, MAX_ZOOM, ATTRIBUTION } from "../../core/constants.js";
|
|
6
6
|
import { RENDERING_CONFIG } from "../../types/interfaces.js";
|
|
7
|
+
import { MapReleaseFetcher } from "../../main.js";
|
|
7
8
|
|
|
8
9
|
class MapTripOpenLayersSource extends XYZ {
|
|
9
10
|
token: string;
|
|
10
11
|
factory: VectorTileFactory;
|
|
12
|
+
release: string = "";
|
|
13
|
+
releaseFetcher: MapReleaseFetcher;
|
|
14
|
+
releaseDate: boolean;
|
|
15
|
+
|
|
11
16
|
constructor(properties: {
|
|
12
17
|
provider?: string;
|
|
13
18
|
baseMap?: boolean;
|
|
@@ -17,8 +22,8 @@ class MapTripOpenLayersSource extends XYZ {
|
|
|
17
22
|
detourProfile?: string;
|
|
18
23
|
renderingConfig?: RENDERING_CONFIG;
|
|
19
24
|
token?: string;
|
|
25
|
+
releaseDate?: boolean;
|
|
20
26
|
}) {
|
|
21
|
-
super();
|
|
22
27
|
const options: XYZOptions = {};
|
|
23
28
|
const projection = "EPSG:3857";
|
|
24
29
|
|
|
@@ -56,6 +61,37 @@ class MapTripOpenLayersSource extends XYZ {
|
|
|
56
61
|
|
|
57
62
|
this.token = properties.token!;
|
|
58
63
|
this.factory = VectorTileFactory.createFactory(properties)!;
|
|
64
|
+
this.releaseFetcher = new MapReleaseFetcher(this.token);
|
|
65
|
+
this.releaseDate = properties.releaseDate ? properties.releaseDate : false;
|
|
66
|
+
|
|
67
|
+
if (this.releaseDate) {
|
|
68
|
+
this.fetchAndSetAttribution(properties.provider!, properties.token!);
|
|
69
|
+
this.on("change", () => this.updateAttribution(properties.provider!));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private async fetchAndSetAttribution(provider: string, token: string) {
|
|
74
|
+
try {
|
|
75
|
+
const release = await this.releaseFetcher.getRelease(provider);
|
|
76
|
+
if (release) {
|
|
77
|
+
this.release = release;
|
|
78
|
+
this.setAttributions(`${ATTRIBUTION} ${this.release}`);
|
|
79
|
+
}
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error("Error fetching release version: ", error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private async updateAttribution(provider: string) {
|
|
86
|
+
try {
|
|
87
|
+
const release = await this.releaseFetcher.getRelease(provider);
|
|
88
|
+
if (release && release !== this.release) {
|
|
89
|
+
this.release = release;
|
|
90
|
+
this.setAttributions(`${ATTRIBUTION} ${this.release}`);
|
|
91
|
+
}
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error("Error updating attribution: ", error);
|
|
94
|
+
}
|
|
59
95
|
}
|
|
60
96
|
}
|
|
61
97
|
|
|
@@ -95,7 +95,7 @@ class VectorTileFactory {
|
|
|
95
95
|
this._properties.traffic &&
|
|
96
96
|
!PROVIDER_TRAFFIC[this._properties.provider]
|
|
97
97
|
) {
|
|
98
|
-
throw new Error("There is
|
|
98
|
+
throw new Error("There is no traffic information for this provider");
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
// assert there is either a base map or traffic (or both)
|
package/lib/core/constants.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
export const URL_TEMPLATE =
|
|
2
2
|
"https://v${index}.maptrip.de/?tilex=${x}&tiley=${y}&acao=true&context=tomtom${z}&project=${project}&projection=wgs84";
|
|
3
3
|
|
|
4
|
+
|
|
4
5
|
export const PROVIDER_PROJECTS: { [key: string]: string } = {
|
|
5
6
|
tomtom: "TomTom_latest",
|
|
6
|
-
here: "
|
|
7
|
-
openstreetmap: "
|
|
7
|
+
here: "HERE_latest",
|
|
8
|
+
openstreetmap: "OSM_latest",
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
export const PROVIDER_TRAFFIC: { [key: string]: string | null } = {
|
package/lib/main.ts
CHANGED
|
@@ -3,6 +3,8 @@ import { RENDERING_CONFIG_DEFAULT } from "./core/rendering_config_default.js";
|
|
|
3
3
|
import { RENDERING_CONFIG_GRAYSCALE } from "./core/rendering_config_grayscale.js";
|
|
4
4
|
import { RENDERING_CONFIG_TRAFFIC } from "./core/rendering_config_traffic.js";
|
|
5
5
|
|
|
6
|
+
import { MapReleaseFetcher } from "./util/MapReleaseFetcher.js";
|
|
7
|
+
|
|
6
8
|
import { MapTripGoogleMapType } from "./api-extensions/google/MapTripGoogleMapType.js";
|
|
7
9
|
import { MapTripLeafletGridLayer } from "./api-extensions/leaflet/MapTripLeafletGridLayer.js";
|
|
8
10
|
import { MapTripOpenLayersSource } from "./api-extensions/openlayers/MapTripOpenLayersSource.js";
|
|
@@ -12,6 +14,7 @@ export {
|
|
|
12
14
|
RENDERING_CONFIG_DEFAULT,
|
|
13
15
|
RENDERING_CONFIG_GRAYSCALE,
|
|
14
16
|
RENDERING_CONFIG_TRAFFIC,
|
|
17
|
+
MapReleaseFetcher,
|
|
15
18
|
MapTripLeafletGridLayer,
|
|
16
19
|
MapTripGoogleMapType,
|
|
17
20
|
MapTripOpenLayersSource,
|
package/lib/types/interfaces.ts
CHANGED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
export class MapReleaseFetcher {
|
|
2
|
+
private _token: string;
|
|
3
|
+
|
|
4
|
+
private _tomtom: Promise<string | null> | null = null;
|
|
5
|
+
private _osm: Promise<string | null> | null = null;
|
|
6
|
+
private _here: Promise<string | null> | null = null;
|
|
7
|
+
|
|
8
|
+
constructor(token: string) {
|
|
9
|
+
this._token = token;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
async getRelease(provider: string) {
|
|
13
|
+
if (provider === "tomtom") {
|
|
14
|
+
if (!this._tomtom) {
|
|
15
|
+
const url =
|
|
16
|
+
"https://v1.maptrip.de/?CMD=GETFILE&PROJECT=TomTom_latest&RELATIVEPATH=/data/mapset/data/routing_geocoder/admin.bin&acao=true";
|
|
17
|
+
this._tomtom = this.fetchAndExtractRelease(url);
|
|
18
|
+
}
|
|
19
|
+
return this._tomtom;
|
|
20
|
+
} else if (provider === "here") {
|
|
21
|
+
if (!this._here) {
|
|
22
|
+
const url =
|
|
23
|
+
"https://v1.maptrip.de/?CMD=GETFILE&PROJECT=HERE_latest&RELATIVEPATH=/data/mapset/data/routing_geocoder/admin.bin&acao=true";
|
|
24
|
+
this._here = this.fetchAndExtractRelease(url);
|
|
25
|
+
}
|
|
26
|
+
return this._here;
|
|
27
|
+
} else if (provider === "openstreetmap") {
|
|
28
|
+
if (!this._osm) {
|
|
29
|
+
const url =
|
|
30
|
+
"https://v1.maptrip.de/?CMD=GETFILE&PROJECT=OSM_latest&RELATIVEPATH=/data/mapset/data/routing_geocoder/admin.bin&acao=true";
|
|
31
|
+
this._osm = this.fetchAndExtractRelease(url);
|
|
32
|
+
}
|
|
33
|
+
return this._osm;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async fetchAndExtractRelease(url: string): Promise<string | null> {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
var xhr = new XMLHttpRequest();
|
|
40
|
+
xhr.onreadystatechange = () => {
|
|
41
|
+
if (xhr.readyState !== XMLHttpRequest.DONE) return;
|
|
42
|
+
|
|
43
|
+
if (xhr.status === 200) {
|
|
44
|
+
const text = new TextDecoder("latin1").decode(xhr.response);
|
|
45
|
+
const textString = this.extractTargetString(text);
|
|
46
|
+
const formattedString = textString!.split("Q").join(" Q");
|
|
47
|
+
const release = ` ${formattedString}`;
|
|
48
|
+
|
|
49
|
+
resolve(release);
|
|
50
|
+
} else {
|
|
51
|
+
reject(`Error fetching: ${xhr.status}`);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
xhr.open("GET", url, true);
|
|
55
|
+
xhr.setRequestHeader("Authorization", `Bearer ${this._token}`);
|
|
56
|
+
xhr.setRequestHeader("Accept", "*/*");
|
|
57
|
+
xhr.setRequestHeader("Content-Type", "application/octet-stream");
|
|
58
|
+
xhr.responseType = "arraybuffer";
|
|
59
|
+
xhr.send(null);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
private extractTargetString(text: string): string | null {
|
|
63
|
+
const match = text.match(/2\d{3}Q[1-4]/);
|
|
64
|
+
return match ? match[0] : null;
|
|
65
|
+
}
|
|
66
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@maptrip/map-tiles",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "API to use MapTrip map tiles in other map APIs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"map",
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"scripts": {
|
|
21
21
|
"dev": "vite src",
|
|
22
22
|
"prepublish": "tsc",
|
|
23
|
-
"build": "tsc && vite build"
|
|
23
|
+
"build": "tsc && vite build",
|
|
24
|
+
"publish": "tsc && vite build && npm login --scope=@maptrip && npm publish"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
27
|
"@googlemaps/js-api-loader": "^1.16.2",
|