@nanolink/mirrors 1.1.75 → 1.1.76

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.
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.tripRouteKey = tripRouteKey;
4
+ exports.parseTripRouteKey = parseTripRouteKey;
5
+ exports.tripRoute = tripRoute;
6
+ exports.readVarint = readVarint;
7
+ exports.decodeTripRouteRecord = decodeTripRouteRecord;
8
+ const decoders_1 = require("./decoders");
9
+ const KEY = /^([^/]+)\/(-?\d+)\/(\d+)$/;
10
+ const ROUTE_SPEED_NONE = 65535;
11
+ const ROUTE_COORD_UNIT = 1e7;
12
+ const ROUTE_SPEED_UNIT = 10;
13
+ const HEX = '0123456789abcdef';
14
+ /** The mirror key of a chunk: `<vid>/<tripStart>/<chunk>`. */
15
+ function tripRouteKey(trackerVID, tripStart, chunk) {
16
+ return `${trackerVID}/${tripStart}/${chunk}`;
17
+ }
18
+ /** The parts of a mirror key, or null when it is not a trip route key. */
19
+ function parseTripRouteKey(id) {
20
+ const m = KEY.exec(id);
21
+ if (!m)
22
+ return null;
23
+ return { trackerVID: m[1], tripStart: Number(m[2]), chunk: Number(m[3]) };
24
+ }
25
+ /**
26
+ * The route of one trip: the points of its contiguous chunks from 0, in
27
+ * order, stopping at the first chunk the mirror does not hold.
28
+ */
29
+ function tripRoute(mirror, trackerVID, tripStart) {
30
+ const points = [];
31
+ for (let chunk = 0;; chunk++) {
32
+ const item = mirror.get(tripRouteKey(trackerVID, tripStart, chunk));
33
+ if (!item || !Array.isArray(item.points))
34
+ break;
35
+ for (const p of item.points)
36
+ points.push(p);
37
+ }
38
+ return points;
39
+ }
40
+ function hex(bytes, start, end) {
41
+ let s = '';
42
+ for (let i = start; i < end; i++)
43
+ s += HEX[bytes[i] >> 4] + HEX[bytes[i] & 15];
44
+ return s;
45
+ }
46
+ /** int64 LE as a number: two uint32 halves, lo + hi * 2^32 (hi signed). */
47
+ function int64(view, offset) {
48
+ return view.getInt32(offset + 4, true) * 4294967296 + view.getUint32(offset, true);
49
+ }
50
+ /**
51
+ * Reads a zigzag varint (Go's binary.Varint): LEB128 unsigned, then
52
+ * even -> n/2, odd -> -(n+1)/2.
53
+ */
54
+ function readVarint(bytes, offset) {
55
+ let result = 0;
56
+ let scale = 1;
57
+ let at = offset;
58
+ for (;;) {
59
+ if (at >= bytes.length)
60
+ throw new Error('truncated statetriproute varint');
61
+ const byte = bytes[at++];
62
+ result += (byte & 0x7f) * scale;
63
+ if ((byte & 0x80) === 0)
64
+ break;
65
+ scale *= 128;
66
+ if (scale > Math.pow(2, 56))
67
+ throw new Error('statetriproute varint too long');
68
+ }
69
+ const signed = result % 2 === 0 ? result / 2 : -(result + 1) / 2;
70
+ return { value: signed, offset: at };
71
+ }
72
+ function routePoint(stamp, lon, lat, speed) {
73
+ return {
74
+ stamp,
75
+ longitude: lon / ROUTE_COORD_UNIT,
76
+ latitude: lat / ROUTE_COORD_UNIT,
77
+ speed: speed === ROUTE_SPEED_NONE ? null : speed / ROUTE_SPEED_UNIT,
78
+ };
79
+ }
80
+ /**
81
+ * Decodes a statetriproute record. The value is `[version: 12][count: u16]`
82
+ * and, with a count above 0, the first point absolute (stamp int64 LE,
83
+ * longitude and latitude int32 LE at 1e-7 degrees, speed uint16 LE at
84
+ * 0.1 km/h, 65535 for none) followed by every further point as four zigzag
85
+ * varints: the deltas of the stamp, the longitude, the latitude and the
86
+ * speed, in the same units. The key is `<vid>/<tripStart>/<chunk>`.
87
+ */
88
+ function decodeTripRouteRecord(key, value) {
89
+ const parsed = parseTripRouteKey(key);
90
+ if (!parsed)
91
+ throw new Error(`invalid statetriproute key: ${key}`);
92
+ if (value.length < 14)
93
+ throw new Error(`statetriproute record too short: ${value.length}`);
94
+ const view = new DataView(value.buffer, value.byteOffset, value.byteLength);
95
+ const count = view.getUint16(12, true);
96
+ const points = [];
97
+ let offset = 14;
98
+ if (count > 0) {
99
+ if (value.length < 32)
100
+ throw new Error('truncated statetriproute first point');
101
+ let stamp = int64(view, 14);
102
+ let lon = view.getInt32(22, true);
103
+ let lat = view.getInt32(26, true);
104
+ let speed = view.getUint16(30, true);
105
+ points.push(routePoint(stamp, lon, lat, speed));
106
+ offset = 32;
107
+ for (let i = 1; i < count; i++) {
108
+ const dStamp = readVarint(value, offset);
109
+ const dLon = readVarint(value, dStamp.offset);
110
+ const dLat = readVarint(value, dLon.offset);
111
+ const dSpeed = readVarint(value, dLat.offset);
112
+ offset = dSpeed.offset;
113
+ stamp += dStamp.value;
114
+ lon += dLon.value;
115
+ lat += dLat.value;
116
+ speed += dSpeed.value;
117
+ if (speed < 0 || speed > ROUTE_SPEED_NONE)
118
+ throw new Error(`statetriproute point ${i} speed out of range`);
119
+ points.push(routePoint(stamp, lon, lat, speed));
120
+ }
121
+ }
122
+ if (offset !== value.length)
123
+ throw new Error(`statetriproute has ${value.length - offset} trailing bytes`);
124
+ return {
125
+ id: key,
126
+ trackerVID: parsed.trackerVID,
127
+ tripStart: parsed.tripStart,
128
+ chunk: parsed.chunk,
129
+ points,
130
+ opVersion: hex(value, 0, 12),
131
+ deleted: false,
132
+ };
133
+ }
134
+ (0, decoders_1.registerDecoder)('tripRoutes', decodeTripRouteRecord);
135
+ //# sourceMappingURL=triproute.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"triproute.js","sourceRoot":"","sources":["../src/triproute.ts"],"names":[],"mappings":";;AAsCA,oCAEC;AAGD,8CAIC;AAMD,8BAQC;AAiBD,gCAcC;AAmBD,sDAwCC;AAtJD,yCAA6C;AA8B7C,MAAM,GAAG,GAAG,2BAA2B,CAAC;AACxC,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,GAAG,GAAG,kBAAkB,CAAC;AAE/B,8DAA8D;AAC9D,SAAgB,YAAY,CAAC,UAAkB,EAAE,SAAiB,EAAE,KAAa;IAC7E,OAAO,GAAG,UAAU,IAAI,SAAS,IAAI,KAAK,EAAE,CAAC;AACjD,CAAC;AAED,0EAA0E;AAC1E,SAAgB,iBAAiB,CAAC,EAAU;IACxC,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvB,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACpB,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9E,CAAC;AAED;;;GAGG;AACH,SAAgB,SAAS,CAAC,MAAoC,EAAE,UAAkB,EAAE,SAAiB;IACjG,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,KAAK,IAAI,KAAK,GAAG,CAAC,GAAI,KAAK,EAAE,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,CAA8B,CAAC;QACjG,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,MAAM;QAChD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,GAAG,CAAC,KAAiB,EAAE,KAAa,EAAE,GAAW;IACtD,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE;QAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC/E,OAAO,CAAC,CAAC;AACb,CAAC;AAED,2EAA2E;AAC3E,SAAS,KAAK,CAAC,IAAc,EAAE,MAAc;IACzC,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACvF,CAAC;AAED;;;GAGG;AACH,SAAgB,UAAU,CAAC,KAAiB,EAAE,MAAc;IACxD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,EAAE,GAAG,MAAM,CAAC;IAChB,SAAS,CAAC;QACN,IAAI,EAAE,IAAI,KAAK,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QAC3E,MAAM,IAAI,GAAG,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;QACzB,MAAM,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC;YAAE,MAAM;QAC/B,KAAK,IAAI,GAAG,CAAC;QACb,IAAI,KAAK,GAAG,SAAA,CAAC,EAAI,EAAE,CAAA;YAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACzC,CAAC;AAED,SAAS,UAAU,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW,EAAE,KAAa;IACtE,OAAO;QACH,KAAK;QACL,SAAS,EAAE,GAAG,GAAG,gBAAgB;QACjC,QAAQ,EAAE,GAAG,GAAG,gBAAgB;QAChC,KAAK,EAAE,KAAK,KAAK,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,gBAAgB;KACtE,CAAC;AACN,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,qBAAqB,CAAC,GAAW,EAAE,KAAiB;IAChE,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAC;IACnE,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3F,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACvC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACZ,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC/E,IAAI,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC5B,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAClC,IAAI,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QACrC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QAChD,MAAM,GAAG,EAAE,CAAC;QACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACzC,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9C,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5C,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC9C,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YACvB,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;YACtB,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC;YAClB,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC;YAClB,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC;YACtB,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,gBAAgB;gBAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,qBAAqB,CAAC,CAAC;YAC3G,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QACpD,CAAC;IACL,CAAC;IACD,IAAI,MAAM,KAAK,KAAK,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,CAAC,MAAM,GAAG,MAAM,iBAAiB,CAAC,CAAC;IAC3G,OAAO;QACH,EAAE,EAAE,GAAG;QACP,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,MAAM;QACN,SAAS,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,OAAO,EAAE,KAAK;KACjB,CAAC;AACN,CAAC;AAED,IAAA,0BAAe,EAAC,YAAY,EAAE,qBAAqB,CAAC,CAAC"}
@@ -71,13 +71,75 @@ __export(index_exports, {
71
71
  SubscriptionClient: () => SubscriptionClient_default,
72
72
  Subscriptions: () => Subscriptions,
73
73
  TempSubscriptions: () => TempSubscriptions2,
74
+ decodeTripRouteRecord: () => decodeTripRouteRecord,
74
75
  draftMirrors: () => draftMirrors,
75
- exposedMirrors: () => exposedMirrors
76
+ exposedMirrors: () => exposedMirrors,
77
+ getDecoder: () => getDecoder,
78
+ parseTripRouteKey: () => parseTripRouteKey,
79
+ registerDecoder: () => registerDecoder,
80
+ tripRoute: () => tripRoute,
81
+ tripRouteKey: () => tripRouteKey
76
82
  });
77
83
  module.exports = __toCommonJS(index_exports);
78
84
 
79
85
  // src/MirrorSync.ts
80
86
  var import_eventemitter3 = __toESM(require("eventemitter3"));
87
+
88
+ // src/data64.ts
89
+ function base64ToBytes(data64) {
90
+ if (typeof Buffer !== "undefined" && typeof Buffer.from === "function") {
91
+ const buf = Buffer.from(data64, "base64");
92
+ return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
93
+ }
94
+ if (typeof atob !== "function") throw new Error("data64: no base64 decoder available");
95
+ const binary = atob(data64);
96
+ const out = new Uint8Array(binary.length);
97
+ for (let i = 0; i < binary.length; i++) out[i] = binary.charCodeAt(i);
98
+ return out;
99
+ }
100
+ function utf8(bytes) {
101
+ if (typeof TextDecoder !== "undefined") return new TextDecoder().decode(bytes);
102
+ if (typeof Buffer !== "undefined") return Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).toString("utf8");
103
+ let s = "";
104
+ for (let i = 0; i < bytes.length; i++) s += String.fromCharCode(bytes[i]);
105
+ return s;
106
+ }
107
+ function readFrames(bytes) {
108
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
109
+ const frames = [];
110
+ let at = 0;
111
+ while (at < bytes.length) {
112
+ if (at + 2 > bytes.length) throw new Error(`data64: truncated key length at ${at}`);
113
+ const keyLength = view.getUint16(at, true);
114
+ at += 2;
115
+ if (at + keyLength + 2 > bytes.length) throw new Error(`data64: truncated key at ${at}`);
116
+ const key = utf8(bytes.subarray(at, at + keyLength));
117
+ at += keyLength;
118
+ const valueLength = view.getUint16(at, true);
119
+ at += 2;
120
+ if (at + valueLength > bytes.length) throw new Error(`data64: truncated value for '${key}' at ${at}`);
121
+ frames.push({ key, value: bytes.subarray(at, at + valueLength) });
122
+ at += valueLength;
123
+ }
124
+ return frames;
125
+ }
126
+ function decodeData64Frames(data64) {
127
+ return readFrames(base64ToBytes(data64));
128
+ }
129
+
130
+ // src/decoders.ts
131
+ var decoders = /* @__PURE__ */ new Map();
132
+ function registerDecoder(rootField, decoder) {
133
+ decoders.set(rootField, decoder);
134
+ }
135
+ function getDecoder(rootField) {
136
+ return decoders.get(rootField);
137
+ }
138
+ function decodeData64(data64, decoder) {
139
+ return decodeData64Frames(data64).map((f) => decoder(f.key, f.value));
140
+ }
141
+
142
+ // src/MirrorSync.ts
81
143
  var MirrorSync = class extends import_eventemitter3.default {
82
144
  constructor(client, options) {
83
145
  super();
@@ -250,7 +312,11 @@ var MirrorSync = class extends import_eventemitter3.default {
250
312
  break;
251
313
  }
252
314
  case "UPDATED" /* UPDATED */:
253
- this.applyUpdated(msg.data);
315
+ if (msg.data !== void 0 && msg.data !== null) this.applyUpdated(msg.data);
316
+ if (typeof msg.data64 === "string") {
317
+ const items = this.decodeData64(firstKey, msg.data64);
318
+ if (items) this.applyUpdated(items);
319
+ }
254
320
  break;
255
321
  case "DELETED" /* DELETED */:
256
322
  this.applyDeleted(msg.deleteId, msg.deleteVersion, msg.deleteOpVersion);
@@ -292,6 +358,26 @@ var MirrorSync = class extends import_eventemitter3.default {
292
358
  this.subscribeInternal(this.currentVersion, this.currentOpVersion);
293
359
  }, 0);
294
360
  }
361
+ /**
362
+ * Decodes a `data64` frame through the decoder registered for the root
363
+ * field. No decoder, or a record that does not decode: emits 'error' and
364
+ * returns undefined so the frame is skipped; never throws.
365
+ */
366
+ decodeData64(rootField, data64) {
367
+ const decoder = getDecoder(rootField);
368
+ if (!decoder) {
369
+ this.l("no data64 decoder", { rootField });
370
+ this.emit("error", new Error(`No data64 decoder registered for root field '${rootField}'`));
371
+ return void 0;
372
+ }
373
+ try {
374
+ return decodeData64(data64, decoder);
375
+ } catch (err) {
376
+ this.l("data64 decode failed", { rootField, err });
377
+ this.emit("error", err);
378
+ return void 0;
379
+ }
380
+ }
295
381
  normalizeItems(data) {
296
382
  if (!data) return [];
297
383
  return Array.isArray(data) ? data : [data];
@@ -2655,6 +2741,16 @@ var trackerState = `subscription trackerState($opVersion: String) {
2655
2741
  }
2656
2742
  }`;
2657
2743
 
2744
+ // src/definitions/opsubscriptions/triproutes.ts
2745
+ var tripRoutes = `subscription tripRoutes($opVersion: String, $trackerVIDs: [String!]) {
2746
+ tripRoutes(opversion: $opVersion, trackerVIDs: $trackerVIDs) {
2747
+ type
2748
+ data64
2749
+ deleteId
2750
+ deleteOpVersion
2751
+ }
2752
+ }`;
2753
+
2658
2754
  // src/definitions/opsubscriptions/trips.ts
2659
2755
  var trips2 = `subscription stateTrips($opVersion: String) {
2660
2756
  stateTrips(opversion: $opVersion) {
@@ -2841,6 +2937,7 @@ var OpSubscriptions = {
2841
2937
  stateLinks,
2842
2938
  stateRefLinks,
2843
2939
  trackerState,
2940
+ tripRoutes,
2844
2941
  trips3: trips2
2845
2942
  };
2846
2943
  var RequiredMirrors = {
@@ -3203,6 +3300,103 @@ function draftMirrors() {
3203
3300
  );
3204
3301
  }
3205
3302
 
3303
+ // src/triproute.ts
3304
+ var KEY = /^([^/]+)\/(-?\d+)\/(\d+)$/;
3305
+ var ROUTE_SPEED_NONE = 65535;
3306
+ var ROUTE_COORD_UNIT = 1e7;
3307
+ var ROUTE_SPEED_UNIT = 10;
3308
+ var HEX = "0123456789abcdef";
3309
+ function tripRouteKey(trackerVID, tripStart, chunk) {
3310
+ return `${trackerVID}/${tripStart}/${chunk}`;
3311
+ }
3312
+ function parseTripRouteKey(id) {
3313
+ const m = KEY.exec(id);
3314
+ if (!m) return null;
3315
+ return { trackerVID: m[1], tripStart: Number(m[2]), chunk: Number(m[3]) };
3316
+ }
3317
+ function tripRoute(mirror, trackerVID, tripStart) {
3318
+ const points = [];
3319
+ for (let chunk = 0; ; chunk++) {
3320
+ const item = mirror.get(tripRouteKey(trackerVID, tripStart, chunk));
3321
+ if (!item || !Array.isArray(item.points)) break;
3322
+ for (const p of item.points) points.push(p);
3323
+ }
3324
+ return points;
3325
+ }
3326
+ function hex(bytes, start, end) {
3327
+ let s = "";
3328
+ for (let i = start; i < end; i++) s += HEX[bytes[i] >> 4] + HEX[bytes[i] & 15];
3329
+ return s;
3330
+ }
3331
+ function int64(view, offset) {
3332
+ return view.getInt32(offset + 4, true) * 4294967296 + view.getUint32(offset, true);
3333
+ }
3334
+ function readVarint(bytes, offset) {
3335
+ let result = 0;
3336
+ let scale = 1;
3337
+ let at = offset;
3338
+ for (; ; ) {
3339
+ if (at >= bytes.length) throw new Error("truncated statetriproute varint");
3340
+ const byte = bytes[at++];
3341
+ result += (byte & 127) * scale;
3342
+ if ((byte & 128) === 0) break;
3343
+ scale *= 128;
3344
+ if (scale > 2 ** 56) throw new Error("statetriproute varint too long");
3345
+ }
3346
+ const signed = result % 2 === 0 ? result / 2 : -(result + 1) / 2;
3347
+ return { value: signed, offset: at };
3348
+ }
3349
+ function routePoint(stamp, lon, lat, speed) {
3350
+ return {
3351
+ stamp,
3352
+ longitude: lon / ROUTE_COORD_UNIT,
3353
+ latitude: lat / ROUTE_COORD_UNIT,
3354
+ speed: speed === ROUTE_SPEED_NONE ? null : speed / ROUTE_SPEED_UNIT
3355
+ };
3356
+ }
3357
+ function decodeTripRouteRecord(key, value) {
3358
+ const parsed = parseTripRouteKey(key);
3359
+ if (!parsed) throw new Error(`invalid statetriproute key: ${key}`);
3360
+ if (value.length < 14) throw new Error(`statetriproute record too short: ${value.length}`);
3361
+ const view = new DataView(value.buffer, value.byteOffset, value.byteLength);
3362
+ const count = view.getUint16(12, true);
3363
+ const points = [];
3364
+ let offset = 14;
3365
+ if (count > 0) {
3366
+ if (value.length < 32) throw new Error("truncated statetriproute first point");
3367
+ let stamp = int64(view, 14);
3368
+ let lon = view.getInt32(22, true);
3369
+ let lat = view.getInt32(26, true);
3370
+ let speed = view.getUint16(30, true);
3371
+ points.push(routePoint(stamp, lon, lat, speed));
3372
+ offset = 32;
3373
+ for (let i = 1; i < count; i++) {
3374
+ const dStamp = readVarint(value, offset);
3375
+ const dLon = readVarint(value, dStamp.offset);
3376
+ const dLat = readVarint(value, dLon.offset);
3377
+ const dSpeed = readVarint(value, dLat.offset);
3378
+ offset = dSpeed.offset;
3379
+ stamp += dStamp.value;
3380
+ lon += dLon.value;
3381
+ lat += dLat.value;
3382
+ speed += dSpeed.value;
3383
+ if (speed < 0 || speed > ROUTE_SPEED_NONE) throw new Error(`statetriproute point ${i} speed out of range`);
3384
+ points.push(routePoint(stamp, lon, lat, speed));
3385
+ }
3386
+ }
3387
+ if (offset !== value.length) throw new Error(`statetriproute has ${value.length - offset} trailing bytes`);
3388
+ return {
3389
+ id: key,
3390
+ trackerVID: parsed.trackerVID,
3391
+ tripStart: parsed.tripStart,
3392
+ chunk: parsed.chunk,
3393
+ points,
3394
+ opVersion: hex(value, 0, 12),
3395
+ deleted: false
3396
+ };
3397
+ }
3398
+ registerDecoder("tripRoutes", decodeTripRouteRecord);
3399
+
3206
3400
  // src/index.ts
3207
3401
  var Connection = class extends SubscriptionClient_default {
3208
3402
  constructor() {