aviation-chart 2.0.33 → 2.0.34
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/dist/nav-sdk.d.ts +1 -0
- package/dist/nav-sdk.esm.js +97 -13
- package/package.json +2 -1
package/dist/nav-sdk.d.ts
CHANGED
package/dist/nav-sdk.esm.js
CHANGED
|
@@ -9810,7 +9810,8 @@ class TileCipher {
|
|
|
9810
9810
|
const blob = b64ToBytes(wrapped);
|
|
9811
9811
|
return aesGcmDecrypt(this.customerKeyRaw, blob.slice(0, IV_LEN), blob.slice(IV_LEN));
|
|
9812
9812
|
}
|
|
9813
|
-
async decrypt(realUrl, envelope) {
|
|
9813
|
+
async decrypt(realUrl, envelope, signal) {
|
|
9814
|
+
signal?.throwIfAborted();
|
|
9814
9815
|
const m = realUrl.match(/\/tiles\/e\/([^/]+)\//);
|
|
9815
9816
|
const period = m?.[1];
|
|
9816
9817
|
if (!period)
|
|
@@ -9825,13 +9826,103 @@ class TileCipher {
|
|
|
9825
9826
|
const iv = bytes.slice(HEADER_LEN, HEADER_LEN + IV_LEN);
|
|
9826
9827
|
const ct = bytes.slice(HEADER_LEN + IV_LEN);
|
|
9827
9828
|
const key = await this.periodKey(period);
|
|
9829
|
+
signal?.throwIfAborted();
|
|
9828
9830
|
let plain = await aesGcmDecrypt(key, iv, ct, aad);
|
|
9831
|
+
signal?.throwIfAborted();
|
|
9829
9832
|
if (flags & FLAG_GZIP)
|
|
9830
9833
|
plain = await gunzip(plain);
|
|
9834
|
+
signal?.throwIfAborted();
|
|
9831
9835
|
return plain.buffer.slice(plain.byteOffset, plain.byteOffset + plain.byteLength);
|
|
9832
9836
|
}
|
|
9833
9837
|
}
|
|
9834
9838
|
|
|
9839
|
+
function createTileProtocol(cipher, fetchImpl = fetch) {
|
|
9840
|
+
return async (params, controller) => {
|
|
9841
|
+
const signal = controller.signal;
|
|
9842
|
+
signal.throwIfAborted();
|
|
9843
|
+
const url = String(params.url).replace(/^kunyu:\/\//, "");
|
|
9844
|
+
const response = await fetchImpl(url, {
|
|
9845
|
+
signal,
|
|
9846
|
+
...(params.headers ? { headers: params.headers } : {}),
|
|
9847
|
+
...(params.credentials ? { credentials: params.credentials } : {}),
|
|
9848
|
+
});
|
|
9849
|
+
if (!response.ok)
|
|
9850
|
+
throw new Error(`tile ${response.status}`);
|
|
9851
|
+
const envelope = await response.arrayBuffer();
|
|
9852
|
+
signal.throwIfAborted();
|
|
9853
|
+
const data = envelope.byteLength ? await cipher.decrypt(url, envelope, signal) : new ArrayBuffer(0);
|
|
9854
|
+
signal.throwIfAborted();
|
|
9855
|
+
return {
|
|
9856
|
+
data,
|
|
9857
|
+
cacheControl: response.headers.get("Cache-Control"),
|
|
9858
|
+
expires: response.headers.get("Expires"),
|
|
9859
|
+
};
|
|
9860
|
+
};
|
|
9861
|
+
}
|
|
9862
|
+
|
|
9863
|
+
function watchAMMVersion(map, fetchImpl = fetch, intervalMs = 60000) {
|
|
9864
|
+
let stopped = false;
|
|
9865
|
+
let pending;
|
|
9866
|
+
let appliedSource;
|
|
9867
|
+
let appliedTiles = "";
|
|
9868
|
+
let appliedVersion = "";
|
|
9869
|
+
async function refresh() {
|
|
9870
|
+
if (stopped || pending)
|
|
9871
|
+
return;
|
|
9872
|
+
const source = map.getSource("amm");
|
|
9873
|
+
const definition = map.getStyle()?.sources["amm"];
|
|
9874
|
+
const tiles = definition?.tiles;
|
|
9875
|
+
const template = tiles?.[0];
|
|
9876
|
+
if (!source?.setTiles || !tiles || !template)
|
|
9877
|
+
return;
|
|
9878
|
+
const position = template.indexOf("/amm/{z}/{x}/{y}.pbf");
|
|
9879
|
+
if (position < 0 || template.startsWith("pmtiles:"))
|
|
9880
|
+
return;
|
|
9881
|
+
const controller = new AbortController();
|
|
9882
|
+
pending = controller;
|
|
9883
|
+
const timeout = setTimeout(() => controller.abort(), 10000);
|
|
9884
|
+
try {
|
|
9885
|
+
const response = await fetchImpl(template.slice(0, position) + "/amm/manifest", {
|
|
9886
|
+
cache: "no-store", signal: controller.signal,
|
|
9887
|
+
});
|
|
9888
|
+
if (!response.ok)
|
|
9889
|
+
return;
|
|
9890
|
+
const manifest = await response.json();
|
|
9891
|
+
if (stopped || controller.signal.aborted || map.getSource("amm") !== source ||
|
|
9892
|
+
!manifest?.available || typeof manifest.version !== "string" || !manifest.version)
|
|
9893
|
+
return;
|
|
9894
|
+
if (source === appliedSource && manifest.version === appliedVersion && JSON.stringify(tiles) === appliedTiles)
|
|
9895
|
+
return;
|
|
9896
|
+
const next = tiles.map(tile => {
|
|
9897
|
+
const [path, query = ""] = tile.split("?");
|
|
9898
|
+
const params = new URLSearchParams(query);
|
|
9899
|
+
params.set("v", manifest.version);
|
|
9900
|
+
return path + "?" + params.toString();
|
|
9901
|
+
});
|
|
9902
|
+
source.setTiles(next);
|
|
9903
|
+
appliedSource = source;
|
|
9904
|
+
appliedTiles = JSON.stringify(next);
|
|
9905
|
+
appliedVersion = manifest.version;
|
|
9906
|
+
}
|
|
9907
|
+
catch {
|
|
9908
|
+
}
|
|
9909
|
+
finally {
|
|
9910
|
+
clearTimeout(timeout);
|
|
9911
|
+
pending = undefined;
|
|
9912
|
+
}
|
|
9913
|
+
}
|
|
9914
|
+
const timer = setInterval(() => { void refresh(); }, intervalMs);
|
|
9915
|
+
const stop = () => {
|
|
9916
|
+
stopped = true;
|
|
9917
|
+
clearInterval(timer);
|
|
9918
|
+
pending?.abort();
|
|
9919
|
+
map.off("remove", stop);
|
|
9920
|
+
};
|
|
9921
|
+
map.on("remove", stop);
|
|
9922
|
+
void refresh();
|
|
9923
|
+
return stop;
|
|
9924
|
+
}
|
|
9925
|
+
|
|
9835
9926
|
// ICAO aviation chart layer styles — token-driven multi-theme.
|
|
9836
9927
|
//
|
|
9837
9928
|
// 单一 buildLayers(T):图层结构只写一份(以 light 为准);凡随主题变化的值
|
|
@@ -11118,18 +11209,7 @@ class MapSDK {
|
|
|
11118
11209
|
if (options.licenseKey) {
|
|
11119
11210
|
try {
|
|
11120
11211
|
this._tileCipher = new TileCipher(this._chartApiUrl, this._apiVersion, options.licenseKey);
|
|
11121
|
-
|
|
11122
|
-
_mlGlExports.addProtocol("kunyu", async (params) => {
|
|
11123
|
-
const realUrl = String(params.url).replace(/^kunyu:\/\//, "");
|
|
11124
|
-
const resp = await fetch(realUrl, { signal: params.signal });
|
|
11125
|
-
if (!resp.ok)
|
|
11126
|
-
throw new Error(`tile ${resp.status}`);
|
|
11127
|
-
const buf = await resp.arrayBuffer();
|
|
11128
|
-
if (buf.byteLength === 0)
|
|
11129
|
-
return { data: null };
|
|
11130
|
-
const data = await cipher.decrypt(realUrl, buf);
|
|
11131
|
-
return { data };
|
|
11132
|
-
});
|
|
11212
|
+
_mlGlExports.addProtocol("kunyu", createTileProtocol(this._tileCipher));
|
|
11133
11213
|
}
|
|
11134
11214
|
catch (e) {
|
|
11135
11215
|
this._tileCipher = undefined;
|
|
@@ -11176,6 +11256,8 @@ class MapSDK {
|
|
|
11176
11256
|
this.initializeChartFeatures();
|
|
11177
11257
|
if (!options.style) {
|
|
11178
11258
|
this.initializeAviationLayers();
|
|
11259
|
+
this._stopAMMVersioning?.();
|
|
11260
|
+
this._stopAMMVersioning = watchAMMVersion(this.map);
|
|
11179
11261
|
}
|
|
11180
11262
|
this.map.fire("loadComplete", { notam: this.notam, adsb: this.adsb });
|
|
11181
11263
|
this.map.fire("aviation:ready", { notam: this.notam, adsb: this.adsb });
|
|
@@ -11769,6 +11851,8 @@ class MapSDK {
|
|
|
11769
11851
|
destroy() {
|
|
11770
11852
|
if (this.isDestroyed)
|
|
11771
11853
|
return;
|
|
11854
|
+
this._stopAMMVersioning?.();
|
|
11855
|
+
this._stopAMMVersioning = undefined;
|
|
11772
11856
|
this.globalConfig.setMapReinitCallback(null);
|
|
11773
11857
|
this.pluginManager.destroy();
|
|
11774
11858
|
this.performanceManager.destroy();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aviation-chart",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.34",
|
|
4
4
|
"description": "KunYu aviation map SDK",
|
|
5
5
|
"main": "dist/nav-sdk.esm.js",
|
|
6
6
|
"module": "dist/nav-sdk.esm.js",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"dist/sdk.style.css"
|
|
20
20
|
],
|
|
21
21
|
"scripts": {
|
|
22
|
+
"test:unit": "node --test tests/*.test.mjs",
|
|
22
23
|
"dev": "vite",
|
|
23
24
|
"build:dev": "rollup -c --environment NODE_ENV:development && node scripts/version-dist.mjs",
|
|
24
25
|
"build:prod": "rollup -c --environment NODE_ENV:production && node scripts/version-dist.mjs",
|