@auxilium/datalynk-client 1.3.22 → 1.4.0

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/api.d.ts CHANGED
@@ -9,6 +9,7 @@ import { ApiCall, Slice } from './slice';
9
9
  import { Socket } from './socket';
10
10
  import { Superuser } from './superuser';
11
11
  import { WebRtc } from './webrtc';
12
+ import { Gps, GpsOptions } from './gps';
12
13
  export type JwtPayload = {
13
14
  aud: string;
14
15
  email: string;
@@ -45,6 +46,8 @@ export type ApiOptions = {
45
46
  serviceWorker?: string;
46
47
  /** Disable sockets with false or override socket URL */
47
48
  socket?: false | string;
49
+ /** GPS live tracking over socket-server/Redis */
50
+ gps?: GpsOptions;
48
51
  /** WebRTC TURN server URL */
49
52
  webrtc?: {
50
53
  /** Additional ICE servers */
@@ -122,6 +125,8 @@ export declare class Api {
122
125
  readonly pwa: PWA;
123
126
  /** Socket */
124
127
  readonly socket: Socket;
128
+ /** GPS */
129
+ readonly gps: Gps;
125
130
  /** Superuser */
126
131
  readonly superuser: Superuser;
127
132
  /** WebRTC */
package/dist/api.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
package/dist/gps.d.ts ADDED
@@ -0,0 +1,124 @@
1
+ import { Api } from './api';
2
+ import { Unsubscribe } from './socket';
3
+ /** GPS connection options */
4
+ export type GpsOptions = false | {
5
+ /**
6
+ * Start browser GPS automatically after a token is available.
7
+ * Set false when an app already owns GPS collection and only wants api.gps.send(...).
8
+ */
9
+ autoStart?: boolean;
10
+ /** Dedicated GPS socket URL override. Defaults to the standard socket-server URL */
11
+ socketUrl?: string;
12
+ /** Slice used by socket-server GPS storage */
13
+ slice: number | string;
14
+ /** Field key used by socket-server GPS storage. Default is coords */
15
+ field?: string;
16
+ /**
17
+ * Stable tracking ID for the object/person/vehicle being tracked.
18
+ *
19
+ * If omitted, datalynk-client generates a unique tracker ID for this Gps
20
+ * instance. The default tracking ID is intentionally not based on sessionId,
21
+ * because one logged-in session/device may start more than one active tracker.
22
+ */
23
+ trackingId?: string;
24
+ /** Stable device ID. Default is stored in localStorage */
25
+ deviceId?: string;
26
+ /** Human-readable label passed through to listeners */
27
+ label?: string;
28
+ /** Source/app label passed through to listeners */
29
+ source?: string;
30
+ /** Send a heartbeat even when the GPS position has not changed. Default is 5000 */
31
+ heartbeatMs?: number;
32
+ /** Minimum movement before sending a non-heartbeat update. Default is 3 */
33
+ minDistanceMeters?: number;
34
+ /** Do not send non-heartbeat positions worse than this accuracy. Default is 200 */
35
+ maxAccuracyMeters?: number;
36
+ /** Use browser high-accuracy GPS. Default is true */
37
+ highAccuracy?: boolean;
38
+ /** Browser geolocation timeout. Default is 10000 */
39
+ timeoutMs?: number;
40
+ /** Reject GPS fixes older than this. Default is 4000 */
41
+ maxStaleMs?: number;
42
+ /** Restart watchPosition if no fresh fix arrives. Default is 60000 */
43
+ watchdogMs?: number;
44
+ };
45
+ export type GpsPositionPayload = {
46
+ lat: number;
47
+ lng: number;
48
+ accuracy: number | null;
49
+ altitude: number | null;
50
+ altitudeAccuracy: number | null;
51
+ heading: number | null;
52
+ speed: number | null;
53
+ timestamp: string;
54
+ timestampMs: number;
55
+ };
56
+ export type GpsManualPositionPayload = Omit<Partial<GpsPositionPayload>, 'lat' | 'lng' | 'timestampMs'> & {
57
+ lat?: number | string;
58
+ lng?: number | string;
59
+ lon?: number | string;
60
+ latitude?: number | string;
61
+ longitude?: number | string;
62
+ timestampMs?: number | string;
63
+ };
64
+ export type GpsListenOptions = {
65
+ slice?: number | string;
66
+ field?: string;
67
+ includeTrails?: boolean;
68
+ trailLimit?: number;
69
+ };
70
+ export type GpsListener = (event: any) => any;
71
+ /** Browser/manual GPS sender backed by socket-server Redis GPS storage */
72
+ export declare class Gps {
73
+ private readonly api;
74
+ private deviceId;
75
+ private heartbeat?;
76
+ private lastFixAt;
77
+ private lastPosition?;
78
+ private lastSentAt;
79
+ private lastSentPosition?;
80
+ private pendingPayloads;
81
+ private retryWatchdog?;
82
+ private seq;
83
+ private sessionId;
84
+ private socket?;
85
+ private trackerId;
86
+ private started;
87
+ private unsubs;
88
+ private watchId?;
89
+ private watchStartedAt;
90
+ readonly options?: Exclude<GpsOptions, false>;
91
+ constructor(api: Api, options?: GpsOptions);
92
+ /** Start sharing browser GPS to socket-server */
93
+ start(): void;
94
+ /** Stop sharing GPS and close the dedicated GPS socket */
95
+ stop(): void;
96
+ /** Send a raw GPS message. Useful when an app already has its own GPS engine */
97
+ send(position: GpsManualPositionPayload, extra?: any): void;
98
+ /** Listen to GPS updates for the configured slice/field */
99
+ listen(callback: GpsListener, options?: GpsListenOptions): Unsubscribe;
100
+ private bindResumeEvents;
101
+ private connectSocket;
102
+ private createId;
103
+ private flushPendingPayloads;
104
+ private getClientDetails;
105
+ private getOrCreateDeviceId;
106
+ private getTrackingId;
107
+ private isFresh;
108
+ private metersBetween;
109
+ private normalizeNullableNumber;
110
+ private normalizeOptionalNumber;
111
+ private normalizePosition;
112
+ private onPosition;
113
+ private onPositionError;
114
+ private restartWatch;
115
+ private sendPayload;
116
+ private sendPosition;
117
+ private serializePosition;
118
+ private shouldSendPosition;
119
+ private startHeartbeat;
120
+ private startWatch;
121
+ private startWatchdog;
122
+ private startWhenAuthenticated;
123
+ }
124
+ //# sourceMappingURL=gps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gps.d.ts","sourceRoot":"","sources":["../src/gps.ts"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -3774,7 +3774,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
3774
3774
  } });
3775
3775
  }
3776
3776
  }
3777
- const version = "1.3.22";
3777
+ const version = "1.4.0";
3778
3778
  class WebRtc {
3779
3779
  constructor(api) {
3780
3780
  __publicField(this, "ice");
@@ -3895,6 +3895,360 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
3895
3895
  return session;
3896
3896
  }
3897
3897
  }
3898
+ class Gps {
3899
+ constructor(api, options) {
3900
+ __publicField(this, "deviceId");
3901
+ __publicField(this, "heartbeat");
3902
+ __publicField(this, "lastFixAt", 0);
3903
+ __publicField(this, "lastPosition");
3904
+ __publicField(this, "lastSentAt", 0);
3905
+ __publicField(this, "lastSentPosition");
3906
+ __publicField(this, "pendingPayloads", []);
3907
+ __publicField(this, "retryWatchdog");
3908
+ __publicField(this, "seq", 0);
3909
+ __publicField(this, "sessionId");
3910
+ __publicField(this, "socket");
3911
+ __publicField(this, "trackerId");
3912
+ __publicField(this, "started", false);
3913
+ __publicField(this, "unsubs", []);
3914
+ __publicField(this, "watchId");
3915
+ __publicField(this, "watchStartedAt", 0);
3916
+ __publicField(this, "options");
3917
+ __publicField(this, "onPosition", (position) => {
3918
+ if (!this.options) return;
3919
+ if (!this.isFresh(position)) return;
3920
+ this.lastFixAt = Date.now();
3921
+ this.lastPosition = position;
3922
+ if (this.shouldSendPosition(position, false)) this.sendPosition(position, false);
3923
+ });
3924
+ __publicField(this, "onPositionError", (error) => {
3925
+ console.warn("Datalynk GPS error:", error.message);
3926
+ });
3927
+ this.api = api;
3928
+ if (options === false || options == null) return;
3929
+ this.options = {
3930
+ autoStart: true,
3931
+ field: "coords",
3932
+ heartbeatMs: 5e3,
3933
+ minDistanceMeters: 3,
3934
+ maxAccuracyMeters: 200,
3935
+ highAccuracy: true,
3936
+ timeoutMs: 1e4,
3937
+ maxStaleMs: 4e3,
3938
+ watchdogMs: 6e4,
3939
+ ...options
3940
+ };
3941
+ this.deviceId = this.options.deviceId || this.getOrCreateDeviceId();
3942
+ this.sessionId = this.createId();
3943
+ this.trackerId = this.options.trackingId || this.createId();
3944
+ if (this.options.autoStart !== false) this.startWhenAuthenticated();
3945
+ }
3946
+ /** Start sharing browser GPS to socket-server */
3947
+ start() {
3948
+ if (!this.options) throw new Error("Datalynk GPS is not configured");
3949
+ if (this.started) return;
3950
+ if (!this.api.token) throw new Error("Datalynk GPS cannot start before login");
3951
+ if (typeof navigator == "undefined" || !navigator.geolocation) throw new Error("Browser geolocation is not available");
3952
+ this.started = true;
3953
+ this.connectSocket();
3954
+ this.startWatch();
3955
+ this.startHeartbeat();
3956
+ this.startWatchdog();
3957
+ this.bindResumeEvents();
3958
+ }
3959
+ /** Stop sharing GPS and close the dedicated GPS socket */
3960
+ stop() {
3961
+ var _a;
3962
+ this.started = false;
3963
+ if (this.watchId != null && typeof navigator != "undefined") navigator.geolocation.clearWatch(this.watchId);
3964
+ this.watchId = void 0;
3965
+ if (this.heartbeat) clearInterval(this.heartbeat);
3966
+ this.heartbeat = void 0;
3967
+ if (this.retryWatchdog) clearInterval(this.retryWatchdog);
3968
+ this.retryWatchdog = void 0;
3969
+ this.unsubs.forEach((unsub) => unsub());
3970
+ this.unsubs = [];
3971
+ this.pendingPayloads = [];
3972
+ (_a = this.socket) == null ? void 0 : _a.close();
3973
+ this.socket = void 0;
3974
+ }
3975
+ /** Send a raw GPS message. Useful when an app already has its own GPS engine */
3976
+ send(position, extra = {}) {
3977
+ if (!this.options) throw new Error("Datalynk GPS is not configured");
3978
+ if (!this.api.token) throw new Error("Datalynk GPS cannot send before login");
3979
+ this.connectSocket();
3980
+ this.sendPayload({
3981
+ ...extra,
3982
+ position: this.normalizePosition(position)
3983
+ });
3984
+ }
3985
+ /** Listen to GPS updates for the configured slice/field */
3986
+ listen(callback, options = {}) {
3987
+ if (!this.options) throw new Error("Datalynk GPS is not configured");
3988
+ if (!this.api.token) throw new Error("Datalynk GPS cannot listen before login");
3989
+ this.connectSocket();
3990
+ const request = {
3991
+ gpsListen: {
3992
+ slice: options.slice || this.options.slice,
3993
+ field: options.field || this.options.field || "coords",
3994
+ includeTrails: options.includeTrails ?? false,
3995
+ trailLimit: options.trailLimit ?? 0
3996
+ }
3997
+ };
3998
+ return this.socket.addListener((event) => {
3999
+ var _a, _b;
4000
+ const payload = event;
4001
+ const gps = ((_a = payload == null ? void 0 : payload.data) == null ? void 0 : _a.gps) || (payload == null ? void 0 : payload.gps);
4002
+ if ((payload == null ? void 0 : payload.type) == "sliceEvents" && ((_b = payload == null ? void 0 : payload.data) == null ? void 0 : _b.type) == "gps.position" && gps) callback(gps);
4003
+ else if ((payload == null ? void 0 : payload.type) == "gps.position" && gps) callback(gps);
4004
+ else if ((payload == null ? void 0 : payload.type) == "gpsListen" || (payload == null ? void 0 : payload.gpsListen)) callback(payload);
4005
+ }, () => this.socket.send(request));
4006
+ }
4007
+ bindResumeEvents() {
4008
+ if (typeof window == "undefined" || typeof document == "undefined") return;
4009
+ const restart = () => {
4010
+ if (!this.started) return;
4011
+ if (document.visibilityState && document.visibilityState !== "visible") return;
4012
+ this.restartWatch();
4013
+ };
4014
+ window.addEventListener("focus", restart);
4015
+ window.addEventListener("pageshow", restart);
4016
+ document.addEventListener("visibilitychange", restart);
4017
+ this.unsubs.push(() => {
4018
+ window.removeEventListener("focus", restart);
4019
+ window.removeEventListener("pageshow", restart);
4020
+ document.removeEventListener("visibilitychange", restart);
4021
+ });
4022
+ }
4023
+ connectSocket() {
4024
+ if (!this.options || this.socket) return;
4025
+ if (!this.api.token) throw new Error("Datalynk GPS socket cannot connect before login");
4026
+ this.socket = new Socket(this.api, { url: this.options.socketUrl });
4027
+ this.unsubs.push(this.socket.addListener(() => {
4028
+ }, () => this.flushPendingPayloads()));
4029
+ }
4030
+ createId() {
4031
+ if (typeof crypto != "undefined" && crypto.randomUUID) return crypto.randomUUID();
4032
+ return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
4033
+ }
4034
+ flushPendingPayloads() {
4035
+ var _a;
4036
+ if (!((_a = this.socket) == null ? void 0 : _a.open)) return;
4037
+ while (this.pendingPayloads.length) {
4038
+ this.socket.send(this.pendingPayloads.shift());
4039
+ }
4040
+ }
4041
+ getClientDetails() {
4042
+ if (typeof navigator == "undefined") return {};
4043
+ return {
4044
+ userAgent: navigator.userAgent,
4045
+ language: navigator.language,
4046
+ platform: navigator.platform,
4047
+ vendor: navigator.vendor,
4048
+ screen: typeof screen == "undefined" ? void 0 : {
4049
+ width: screen.width,
4050
+ height: screen.height,
4051
+ pixelRatio: typeof devicePixelRatio == "undefined" ? void 0 : devicePixelRatio
4052
+ },
4053
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
4054
+ };
4055
+ }
4056
+ getOrCreateDeviceId() {
4057
+ const key = "datalynk-gps-device-id";
4058
+ if (typeof localStorage != "undefined") {
4059
+ const existing = localStorage.getItem(key);
4060
+ if (existing) return existing;
4061
+ const id = this.createId();
4062
+ localStorage.setItem(key, id);
4063
+ return id;
4064
+ }
4065
+ return this.createId();
4066
+ }
4067
+ getTrackingId() {
4068
+ var _a;
4069
+ if (!this.options) return this.trackerId || this.createId();
4070
+ if (this.options.trackingId) return this.options.trackingId;
4071
+ const uid = (_a = this.api.jwtPayload) == null ? void 0 : _a.uid;
4072
+ return uid ? `user:${uid}:tracker:${this.trackerId}` : `device:${this.deviceId}:tracker:${this.trackerId}`;
4073
+ }
4074
+ isFresh(position) {
4075
+ if (!this.options) return false;
4076
+ if (this.lastPosition && position.timestamp <= this.lastPosition.timestamp) return false;
4077
+ return Date.now() - position.timestamp <= (this.options.maxStaleMs || 4e3);
4078
+ }
4079
+ metersBetween(a, b) {
4080
+ const earthRadius = 6371e3;
4081
+ const lat1 = a.coords.latitude * Math.PI / 180;
4082
+ const lat2 = b.coords.latitude * Math.PI / 180;
4083
+ const dLat = (b.coords.latitude - a.coords.latitude) * Math.PI / 180;
4084
+ const dLng = (b.coords.longitude - a.coords.longitude) * Math.PI / 180;
4085
+ const x = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
4086
+ return earthRadius * 2 * Math.atan2(Math.sqrt(x), Math.sqrt(1 - x));
4087
+ }
4088
+ normalizeNullableNumber(value, field) {
4089
+ if (value == null || value === "") return null;
4090
+ const number = Number(value);
4091
+ if (!Number.isFinite(number)) throw new Error(`GPS ${field} must be a valid number`);
4092
+ return number;
4093
+ }
4094
+ normalizeOptionalNumber(value, field) {
4095
+ if (value == null || value === "") return void 0;
4096
+ const number = Number(value);
4097
+ if (!Number.isFinite(number)) throw new Error(`GPS ${field} must be a valid number`);
4098
+ return number;
4099
+ }
4100
+ normalizePosition(position) {
4101
+ const lat = Number(position.lat ?? position.latitude);
4102
+ const lng = Number(position.lng ?? position.lon ?? position.longitude);
4103
+ if (!Number.isFinite(lat) || lat < -90 || lat > 90) {
4104
+ throw new Error("GPS position must include a valid lat/latitude between -90 and 90");
4105
+ }
4106
+ if (!Number.isFinite(lng) || lng < -180 || lng > 180) {
4107
+ throw new Error("GPS position must include a valid lng/lon/longitude between -180 and 180");
4108
+ }
4109
+ const accuracy = this.normalizeNullableNumber(position.accuracy, "accuracy");
4110
+ if (accuracy != null && accuracy < 0) throw new Error("GPS accuracy must be zero or greater");
4111
+ const altitude = this.normalizeNullableNumber(position.altitude, "altitude");
4112
+ const altitudeAccuracy = this.normalizeNullableNumber(position.altitudeAccuracy, "altitudeAccuracy");
4113
+ if (altitudeAccuracy != null && altitudeAccuracy < 0) throw new Error("GPS altitudeAccuracy must be zero or greater");
4114
+ const heading = this.normalizeNullableNumber(position.heading, "heading");
4115
+ if (heading != null && (heading < 0 || heading >= 360)) throw new Error("GPS heading must be between 0 and 360");
4116
+ const speed = this.normalizeNullableNumber(position.speed, "speed");
4117
+ if (speed != null && speed < 0) throw new Error("GPS speed must be zero or greater");
4118
+ const timestampMs = this.normalizeOptionalNumber(position.timestampMs, "timestampMs") ?? Date.now();
4119
+ if (timestampMs <= 0) throw new Error("GPS timestampMs must be greater than zero");
4120
+ let timestamp = position.timestamp;
4121
+ if (timestamp) {
4122
+ const parsed = Date.parse(timestamp);
4123
+ if (!Number.isFinite(parsed)) throw new Error("GPS timestamp must be a valid date string");
4124
+ } else {
4125
+ timestamp = new Date(timestampMs).toISOString();
4126
+ }
4127
+ return {
4128
+ lat,
4129
+ lng,
4130
+ accuracy,
4131
+ altitude,
4132
+ altitudeAccuracy,
4133
+ heading,
4134
+ speed,
4135
+ timestamp,
4136
+ timestampMs
4137
+ };
4138
+ }
4139
+ restartWatch() {
4140
+ if (!this.options || !this.started || typeof navigator == "undefined" || !navigator.geolocation) return;
4141
+ if (this.watchId != null) navigator.geolocation.clearWatch(this.watchId);
4142
+ this.watchId = void 0;
4143
+ this.startWatch();
4144
+ }
4145
+ sendPayload(payload) {
4146
+ var _a, _b;
4147
+ if (!this.options) return;
4148
+ this.connectSocket();
4149
+ const message = {
4150
+ gps: {
4151
+ slice: this.options.slice,
4152
+ field: this.options.field || "coords",
4153
+ trackingId: this.getTrackingId(),
4154
+ trackerId: this.trackerId,
4155
+ sessionId: this.sessionId,
4156
+ deviceId: this.deviceId,
4157
+ seq: ++this.seq,
4158
+ client: this.getClientDetails(),
4159
+ sentAt: (/* @__PURE__ */ new Date()).toISOString(),
4160
+ gpsTimestamp: ((_a = payload.position) == null ? void 0 : _a.timestamp) || null,
4161
+ label: this.options.label,
4162
+ source: this.options.source,
4163
+ ...payload
4164
+ }
4165
+ };
4166
+ if (!((_b = this.socket) == null ? void 0 : _b.open)) {
4167
+ this.pendingPayloads.push(message);
4168
+ this.pendingPayloads = this.pendingPayloads.slice(-25);
4169
+ return;
4170
+ }
4171
+ this.socket.send(message);
4172
+ }
4173
+ sendPosition(position, force) {
4174
+ this.sendPayload({
4175
+ force,
4176
+ position: this.serializePosition(position)
4177
+ });
4178
+ this.lastSentPosition = position;
4179
+ this.lastSentAt = Date.now();
4180
+ }
4181
+ serializePosition(position) {
4182
+ return {
4183
+ lat: position.coords.latitude,
4184
+ lng: position.coords.longitude,
4185
+ accuracy: position.coords.accuracy,
4186
+ altitude: position.coords.altitude,
4187
+ altitudeAccuracy: position.coords.altitudeAccuracy,
4188
+ heading: position.coords.heading,
4189
+ speed: position.coords.speed,
4190
+ timestamp: new Date(position.timestamp).toISOString(),
4191
+ timestampMs: position.timestamp
4192
+ };
4193
+ }
4194
+ shouldSendPosition(position, force) {
4195
+ if (!this.options) return false;
4196
+ if (force) return true;
4197
+ const accuracy = Number(position.coords.accuracy || 0);
4198
+ if (accuracy && accuracy > (this.options.maxAccuracyMeters || 200)) return false;
4199
+ if (!this.lastSentPosition) return true;
4200
+ const movedMeters = this.metersBetween(this.lastSentPosition, position);
4201
+ const accuracyImproved = Number(position.coords.accuracy || 999999) < Number(this.lastSentPosition.coords.accuracy || 999999);
4202
+ const heartbeatDue = Date.now() - this.lastSentAt >= (this.options.heartbeatMs || 5e3);
4203
+ return movedMeters >= (this.options.minDistanceMeters || 3) || accuracyImproved || heartbeatDue;
4204
+ }
4205
+ startHeartbeat() {
4206
+ if (!this.options || this.heartbeat) return;
4207
+ this.heartbeat = setInterval(() => {
4208
+ if (!this.started || !this.lastPosition) return;
4209
+ this.sendPosition(this.lastPosition, true);
4210
+ }, this.options.heartbeatMs || 5e3);
4211
+ }
4212
+ startWatch() {
4213
+ if (!this.options || this.watchId != null) return;
4214
+ this.watchStartedAt = Date.now();
4215
+ this.watchId = navigator.geolocation.watchPosition(this.onPosition, this.onPositionError, {
4216
+ enableHighAccuracy: this.options.highAccuracy !== false,
4217
+ maximumAge: 0,
4218
+ timeout: this.options.timeoutMs || 1e4
4219
+ });
4220
+ }
4221
+ startWatchdog() {
4222
+ if (!this.options || this.retryWatchdog) return;
4223
+ this.retryWatchdog = setInterval(() => {
4224
+ if (!this.started) return;
4225
+ const lastActivity = this.lastFixAt || this.watchStartedAt;
4226
+ if (lastActivity && Date.now() - lastActivity >= (this.options.watchdogMs || 6e4)) this.restartWatch();
4227
+ }, Math.min(this.options.watchdogMs || 6e4, 15e3));
4228
+ }
4229
+ startWhenAuthenticated() {
4230
+ if (!this.options) return;
4231
+ if (this.api.token) {
4232
+ setTimeout(() => {
4233
+ try {
4234
+ this.start();
4235
+ } catch (error) {
4236
+ console.warn("Datalynk GPS auto-start failed:", error);
4237
+ }
4238
+ }, 0);
4239
+ return;
4240
+ }
4241
+ const sub = this.api.token$.subscribe((token) => {
4242
+ if (!token || this.started || !this.options || this.options.autoStart === false) return;
4243
+ try {
4244
+ this.start();
4245
+ } catch (error) {
4246
+ console.warn("Datalynk GPS auto-start failed:", error);
4247
+ }
4248
+ });
4249
+ this.unsubs.push(() => sub.unsubscribe());
4250
+ }
4251
+ }
3898
4252
  const _Api = class _Api {
3899
4253
  /**
3900
4254
  * Connect to Datalynk & send requests
@@ -3933,6 +4287,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
3933
4287
  __publicField(this, "pwa");
3934
4288
  /** Socket */
3935
4289
  __publicField(this, "socket");
4290
+ /** GPS */
4291
+ __publicField(this, "gps");
3936
4292
  /** Superuser */
3937
4293
  __publicField(this, "superuser");
3938
4294
  /** WebRTC */
@@ -3978,6 +4334,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
3978
4334
  });
3979
4335
  }
3980
4336
  this.socket = new Socket(this, { url: options.socket });
4337
+ this.gps = new Gps(this, options.gps);
3981
4338
  this.auth = new Auth(this);
3982
4339
  this.files = new Files(this);
3983
4340
  this.pdf = new Pdf(this);
@@ -4283,6 +4640,7 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
4283
4640
  exports2.ApiCall = ApiCall;
4284
4641
  exports2.Auth = Auth;
4285
4642
  exports2.Files = Files;
4643
+ exports2.Gps = Gps;
4286
4644
  exports2.LoginPrompt = LoginPrompt;
4287
4645
  exports2.PWA = PWA;
4288
4646
  exports2.Pdf = Pdf;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from './api';
2
2
  export * from './auth';
3
3
  export * from './files';
4
+ export * from './gps';
4
5
  export * from './login-prompt';
5
6
  export * from './meta';
6
7
  export * from './pdf';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC;AACtB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC;AACtB,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,gBAAgB,CAAC;AAC/B,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,OAAO,CAAC;AACtB,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
package/dist/index.mjs CHANGED
@@ -3770,7 +3770,7 @@ class Superuser {
3770
3770
  } });
3771
3771
  }
3772
3772
  }
3773
- const version = "1.3.22";
3773
+ const version = "1.4.0";
3774
3774
  class WebRtc {
3775
3775
  constructor(api) {
3776
3776
  __publicField(this, "ice");
@@ -3891,6 +3891,360 @@ class WebRtc {
3891
3891
  return session;
3892
3892
  }
3893
3893
  }
3894
+ class Gps {
3895
+ constructor(api, options) {
3896
+ __publicField(this, "deviceId");
3897
+ __publicField(this, "heartbeat");
3898
+ __publicField(this, "lastFixAt", 0);
3899
+ __publicField(this, "lastPosition");
3900
+ __publicField(this, "lastSentAt", 0);
3901
+ __publicField(this, "lastSentPosition");
3902
+ __publicField(this, "pendingPayloads", []);
3903
+ __publicField(this, "retryWatchdog");
3904
+ __publicField(this, "seq", 0);
3905
+ __publicField(this, "sessionId");
3906
+ __publicField(this, "socket");
3907
+ __publicField(this, "trackerId");
3908
+ __publicField(this, "started", false);
3909
+ __publicField(this, "unsubs", []);
3910
+ __publicField(this, "watchId");
3911
+ __publicField(this, "watchStartedAt", 0);
3912
+ __publicField(this, "options");
3913
+ __publicField(this, "onPosition", (position) => {
3914
+ if (!this.options) return;
3915
+ if (!this.isFresh(position)) return;
3916
+ this.lastFixAt = Date.now();
3917
+ this.lastPosition = position;
3918
+ if (this.shouldSendPosition(position, false)) this.sendPosition(position, false);
3919
+ });
3920
+ __publicField(this, "onPositionError", (error) => {
3921
+ console.warn("Datalynk GPS error:", error.message);
3922
+ });
3923
+ this.api = api;
3924
+ if (options === false || options == null) return;
3925
+ this.options = {
3926
+ autoStart: true,
3927
+ field: "coords",
3928
+ heartbeatMs: 5e3,
3929
+ minDistanceMeters: 3,
3930
+ maxAccuracyMeters: 200,
3931
+ highAccuracy: true,
3932
+ timeoutMs: 1e4,
3933
+ maxStaleMs: 4e3,
3934
+ watchdogMs: 6e4,
3935
+ ...options
3936
+ };
3937
+ this.deviceId = this.options.deviceId || this.getOrCreateDeviceId();
3938
+ this.sessionId = this.createId();
3939
+ this.trackerId = this.options.trackingId || this.createId();
3940
+ if (this.options.autoStart !== false) this.startWhenAuthenticated();
3941
+ }
3942
+ /** Start sharing browser GPS to socket-server */
3943
+ start() {
3944
+ if (!this.options) throw new Error("Datalynk GPS is not configured");
3945
+ if (this.started) return;
3946
+ if (!this.api.token) throw new Error("Datalynk GPS cannot start before login");
3947
+ if (typeof navigator == "undefined" || !navigator.geolocation) throw new Error("Browser geolocation is not available");
3948
+ this.started = true;
3949
+ this.connectSocket();
3950
+ this.startWatch();
3951
+ this.startHeartbeat();
3952
+ this.startWatchdog();
3953
+ this.bindResumeEvents();
3954
+ }
3955
+ /** Stop sharing GPS and close the dedicated GPS socket */
3956
+ stop() {
3957
+ var _a;
3958
+ this.started = false;
3959
+ if (this.watchId != null && typeof navigator != "undefined") navigator.geolocation.clearWatch(this.watchId);
3960
+ this.watchId = void 0;
3961
+ if (this.heartbeat) clearInterval(this.heartbeat);
3962
+ this.heartbeat = void 0;
3963
+ if (this.retryWatchdog) clearInterval(this.retryWatchdog);
3964
+ this.retryWatchdog = void 0;
3965
+ this.unsubs.forEach((unsub) => unsub());
3966
+ this.unsubs = [];
3967
+ this.pendingPayloads = [];
3968
+ (_a = this.socket) == null ? void 0 : _a.close();
3969
+ this.socket = void 0;
3970
+ }
3971
+ /** Send a raw GPS message. Useful when an app already has its own GPS engine */
3972
+ send(position, extra = {}) {
3973
+ if (!this.options) throw new Error("Datalynk GPS is not configured");
3974
+ if (!this.api.token) throw new Error("Datalynk GPS cannot send before login");
3975
+ this.connectSocket();
3976
+ this.sendPayload({
3977
+ ...extra,
3978
+ position: this.normalizePosition(position)
3979
+ });
3980
+ }
3981
+ /** Listen to GPS updates for the configured slice/field */
3982
+ listen(callback, options = {}) {
3983
+ if (!this.options) throw new Error("Datalynk GPS is not configured");
3984
+ if (!this.api.token) throw new Error("Datalynk GPS cannot listen before login");
3985
+ this.connectSocket();
3986
+ const request = {
3987
+ gpsListen: {
3988
+ slice: options.slice || this.options.slice,
3989
+ field: options.field || this.options.field || "coords",
3990
+ includeTrails: options.includeTrails ?? false,
3991
+ trailLimit: options.trailLimit ?? 0
3992
+ }
3993
+ };
3994
+ return this.socket.addListener((event) => {
3995
+ var _a, _b;
3996
+ const payload = event;
3997
+ const gps = ((_a = payload == null ? void 0 : payload.data) == null ? void 0 : _a.gps) || (payload == null ? void 0 : payload.gps);
3998
+ if ((payload == null ? void 0 : payload.type) == "sliceEvents" && ((_b = payload == null ? void 0 : payload.data) == null ? void 0 : _b.type) == "gps.position" && gps) callback(gps);
3999
+ else if ((payload == null ? void 0 : payload.type) == "gps.position" && gps) callback(gps);
4000
+ else if ((payload == null ? void 0 : payload.type) == "gpsListen" || (payload == null ? void 0 : payload.gpsListen)) callback(payload);
4001
+ }, () => this.socket.send(request));
4002
+ }
4003
+ bindResumeEvents() {
4004
+ if (typeof window == "undefined" || typeof document == "undefined") return;
4005
+ const restart = () => {
4006
+ if (!this.started) return;
4007
+ if (document.visibilityState && document.visibilityState !== "visible") return;
4008
+ this.restartWatch();
4009
+ };
4010
+ window.addEventListener("focus", restart);
4011
+ window.addEventListener("pageshow", restart);
4012
+ document.addEventListener("visibilitychange", restart);
4013
+ this.unsubs.push(() => {
4014
+ window.removeEventListener("focus", restart);
4015
+ window.removeEventListener("pageshow", restart);
4016
+ document.removeEventListener("visibilitychange", restart);
4017
+ });
4018
+ }
4019
+ connectSocket() {
4020
+ if (!this.options || this.socket) return;
4021
+ if (!this.api.token) throw new Error("Datalynk GPS socket cannot connect before login");
4022
+ this.socket = new Socket(this.api, { url: this.options.socketUrl });
4023
+ this.unsubs.push(this.socket.addListener(() => {
4024
+ }, () => this.flushPendingPayloads()));
4025
+ }
4026
+ createId() {
4027
+ if (typeof crypto != "undefined" && crypto.randomUUID) return crypto.randomUUID();
4028
+ return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
4029
+ }
4030
+ flushPendingPayloads() {
4031
+ var _a;
4032
+ if (!((_a = this.socket) == null ? void 0 : _a.open)) return;
4033
+ while (this.pendingPayloads.length) {
4034
+ this.socket.send(this.pendingPayloads.shift());
4035
+ }
4036
+ }
4037
+ getClientDetails() {
4038
+ if (typeof navigator == "undefined") return {};
4039
+ return {
4040
+ userAgent: navigator.userAgent,
4041
+ language: navigator.language,
4042
+ platform: navigator.platform,
4043
+ vendor: navigator.vendor,
4044
+ screen: typeof screen == "undefined" ? void 0 : {
4045
+ width: screen.width,
4046
+ height: screen.height,
4047
+ pixelRatio: typeof devicePixelRatio == "undefined" ? void 0 : devicePixelRatio
4048
+ },
4049
+ timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
4050
+ };
4051
+ }
4052
+ getOrCreateDeviceId() {
4053
+ const key = "datalynk-gps-device-id";
4054
+ if (typeof localStorage != "undefined") {
4055
+ const existing = localStorage.getItem(key);
4056
+ if (existing) return existing;
4057
+ const id = this.createId();
4058
+ localStorage.setItem(key, id);
4059
+ return id;
4060
+ }
4061
+ return this.createId();
4062
+ }
4063
+ getTrackingId() {
4064
+ var _a;
4065
+ if (!this.options) return this.trackerId || this.createId();
4066
+ if (this.options.trackingId) return this.options.trackingId;
4067
+ const uid = (_a = this.api.jwtPayload) == null ? void 0 : _a.uid;
4068
+ return uid ? `user:${uid}:tracker:${this.trackerId}` : `device:${this.deviceId}:tracker:${this.trackerId}`;
4069
+ }
4070
+ isFresh(position) {
4071
+ if (!this.options) return false;
4072
+ if (this.lastPosition && position.timestamp <= this.lastPosition.timestamp) return false;
4073
+ return Date.now() - position.timestamp <= (this.options.maxStaleMs || 4e3);
4074
+ }
4075
+ metersBetween(a, b) {
4076
+ const earthRadius = 6371e3;
4077
+ const lat1 = a.coords.latitude * Math.PI / 180;
4078
+ const lat2 = b.coords.latitude * Math.PI / 180;
4079
+ const dLat = (b.coords.latitude - a.coords.latitude) * Math.PI / 180;
4080
+ const dLng = (b.coords.longitude - a.coords.longitude) * Math.PI / 180;
4081
+ const x = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
4082
+ return earthRadius * 2 * Math.atan2(Math.sqrt(x), Math.sqrt(1 - x));
4083
+ }
4084
+ normalizeNullableNumber(value, field) {
4085
+ if (value == null || value === "") return null;
4086
+ const number = Number(value);
4087
+ if (!Number.isFinite(number)) throw new Error(`GPS ${field} must be a valid number`);
4088
+ return number;
4089
+ }
4090
+ normalizeOptionalNumber(value, field) {
4091
+ if (value == null || value === "") return void 0;
4092
+ const number = Number(value);
4093
+ if (!Number.isFinite(number)) throw new Error(`GPS ${field} must be a valid number`);
4094
+ return number;
4095
+ }
4096
+ normalizePosition(position) {
4097
+ const lat = Number(position.lat ?? position.latitude);
4098
+ const lng = Number(position.lng ?? position.lon ?? position.longitude);
4099
+ if (!Number.isFinite(lat) || lat < -90 || lat > 90) {
4100
+ throw new Error("GPS position must include a valid lat/latitude between -90 and 90");
4101
+ }
4102
+ if (!Number.isFinite(lng) || lng < -180 || lng > 180) {
4103
+ throw new Error("GPS position must include a valid lng/lon/longitude between -180 and 180");
4104
+ }
4105
+ const accuracy = this.normalizeNullableNumber(position.accuracy, "accuracy");
4106
+ if (accuracy != null && accuracy < 0) throw new Error("GPS accuracy must be zero or greater");
4107
+ const altitude = this.normalizeNullableNumber(position.altitude, "altitude");
4108
+ const altitudeAccuracy = this.normalizeNullableNumber(position.altitudeAccuracy, "altitudeAccuracy");
4109
+ if (altitudeAccuracy != null && altitudeAccuracy < 0) throw new Error("GPS altitudeAccuracy must be zero or greater");
4110
+ const heading = this.normalizeNullableNumber(position.heading, "heading");
4111
+ if (heading != null && (heading < 0 || heading >= 360)) throw new Error("GPS heading must be between 0 and 360");
4112
+ const speed = this.normalizeNullableNumber(position.speed, "speed");
4113
+ if (speed != null && speed < 0) throw new Error("GPS speed must be zero or greater");
4114
+ const timestampMs = this.normalizeOptionalNumber(position.timestampMs, "timestampMs") ?? Date.now();
4115
+ if (timestampMs <= 0) throw new Error("GPS timestampMs must be greater than zero");
4116
+ let timestamp = position.timestamp;
4117
+ if (timestamp) {
4118
+ const parsed = Date.parse(timestamp);
4119
+ if (!Number.isFinite(parsed)) throw new Error("GPS timestamp must be a valid date string");
4120
+ } else {
4121
+ timestamp = new Date(timestampMs).toISOString();
4122
+ }
4123
+ return {
4124
+ lat,
4125
+ lng,
4126
+ accuracy,
4127
+ altitude,
4128
+ altitudeAccuracy,
4129
+ heading,
4130
+ speed,
4131
+ timestamp,
4132
+ timestampMs
4133
+ };
4134
+ }
4135
+ restartWatch() {
4136
+ if (!this.options || !this.started || typeof navigator == "undefined" || !navigator.geolocation) return;
4137
+ if (this.watchId != null) navigator.geolocation.clearWatch(this.watchId);
4138
+ this.watchId = void 0;
4139
+ this.startWatch();
4140
+ }
4141
+ sendPayload(payload) {
4142
+ var _a, _b;
4143
+ if (!this.options) return;
4144
+ this.connectSocket();
4145
+ const message = {
4146
+ gps: {
4147
+ slice: this.options.slice,
4148
+ field: this.options.field || "coords",
4149
+ trackingId: this.getTrackingId(),
4150
+ trackerId: this.trackerId,
4151
+ sessionId: this.sessionId,
4152
+ deviceId: this.deviceId,
4153
+ seq: ++this.seq,
4154
+ client: this.getClientDetails(),
4155
+ sentAt: (/* @__PURE__ */ new Date()).toISOString(),
4156
+ gpsTimestamp: ((_a = payload.position) == null ? void 0 : _a.timestamp) || null,
4157
+ label: this.options.label,
4158
+ source: this.options.source,
4159
+ ...payload
4160
+ }
4161
+ };
4162
+ if (!((_b = this.socket) == null ? void 0 : _b.open)) {
4163
+ this.pendingPayloads.push(message);
4164
+ this.pendingPayloads = this.pendingPayloads.slice(-25);
4165
+ return;
4166
+ }
4167
+ this.socket.send(message);
4168
+ }
4169
+ sendPosition(position, force) {
4170
+ this.sendPayload({
4171
+ force,
4172
+ position: this.serializePosition(position)
4173
+ });
4174
+ this.lastSentPosition = position;
4175
+ this.lastSentAt = Date.now();
4176
+ }
4177
+ serializePosition(position) {
4178
+ return {
4179
+ lat: position.coords.latitude,
4180
+ lng: position.coords.longitude,
4181
+ accuracy: position.coords.accuracy,
4182
+ altitude: position.coords.altitude,
4183
+ altitudeAccuracy: position.coords.altitudeAccuracy,
4184
+ heading: position.coords.heading,
4185
+ speed: position.coords.speed,
4186
+ timestamp: new Date(position.timestamp).toISOString(),
4187
+ timestampMs: position.timestamp
4188
+ };
4189
+ }
4190
+ shouldSendPosition(position, force) {
4191
+ if (!this.options) return false;
4192
+ if (force) return true;
4193
+ const accuracy = Number(position.coords.accuracy || 0);
4194
+ if (accuracy && accuracy > (this.options.maxAccuracyMeters || 200)) return false;
4195
+ if (!this.lastSentPosition) return true;
4196
+ const movedMeters = this.metersBetween(this.lastSentPosition, position);
4197
+ const accuracyImproved = Number(position.coords.accuracy || 999999) < Number(this.lastSentPosition.coords.accuracy || 999999);
4198
+ const heartbeatDue = Date.now() - this.lastSentAt >= (this.options.heartbeatMs || 5e3);
4199
+ return movedMeters >= (this.options.minDistanceMeters || 3) || accuracyImproved || heartbeatDue;
4200
+ }
4201
+ startHeartbeat() {
4202
+ if (!this.options || this.heartbeat) return;
4203
+ this.heartbeat = setInterval(() => {
4204
+ if (!this.started || !this.lastPosition) return;
4205
+ this.sendPosition(this.lastPosition, true);
4206
+ }, this.options.heartbeatMs || 5e3);
4207
+ }
4208
+ startWatch() {
4209
+ if (!this.options || this.watchId != null) return;
4210
+ this.watchStartedAt = Date.now();
4211
+ this.watchId = navigator.geolocation.watchPosition(this.onPosition, this.onPositionError, {
4212
+ enableHighAccuracy: this.options.highAccuracy !== false,
4213
+ maximumAge: 0,
4214
+ timeout: this.options.timeoutMs || 1e4
4215
+ });
4216
+ }
4217
+ startWatchdog() {
4218
+ if (!this.options || this.retryWatchdog) return;
4219
+ this.retryWatchdog = setInterval(() => {
4220
+ if (!this.started) return;
4221
+ const lastActivity = this.lastFixAt || this.watchStartedAt;
4222
+ if (lastActivity && Date.now() - lastActivity >= (this.options.watchdogMs || 6e4)) this.restartWatch();
4223
+ }, Math.min(this.options.watchdogMs || 6e4, 15e3));
4224
+ }
4225
+ startWhenAuthenticated() {
4226
+ if (!this.options) return;
4227
+ if (this.api.token) {
4228
+ setTimeout(() => {
4229
+ try {
4230
+ this.start();
4231
+ } catch (error) {
4232
+ console.warn("Datalynk GPS auto-start failed:", error);
4233
+ }
4234
+ }, 0);
4235
+ return;
4236
+ }
4237
+ const sub = this.api.token$.subscribe((token) => {
4238
+ if (!token || this.started || !this.options || this.options.autoStart === false) return;
4239
+ try {
4240
+ this.start();
4241
+ } catch (error) {
4242
+ console.warn("Datalynk GPS auto-start failed:", error);
4243
+ }
4244
+ });
4245
+ this.unsubs.push(() => sub.unsubscribe());
4246
+ }
4247
+ }
3894
4248
  const _Api = class _Api {
3895
4249
  /**
3896
4250
  * Connect to Datalynk & send requests
@@ -3929,6 +4283,8 @@ const _Api = class _Api {
3929
4283
  __publicField(this, "pwa");
3930
4284
  /** Socket */
3931
4285
  __publicField(this, "socket");
4286
+ /** GPS */
4287
+ __publicField(this, "gps");
3932
4288
  /** Superuser */
3933
4289
  __publicField(this, "superuser");
3934
4290
  /** WebRTC */
@@ -3974,6 +4330,7 @@ const _Api = class _Api {
3974
4330
  });
3975
4331
  }
3976
4332
  this.socket = new Socket(this, { url: options.socket });
4333
+ this.gps = new Gps(this, options.gps);
3977
4334
  this.auth = new Auth(this);
3978
4335
  this.files = new Files(this);
3979
4336
  this.pdf = new Pdf(this);
@@ -4280,6 +4637,7 @@ export {
4280
4637
  ApiCall,
4281
4638
  Auth,
4282
4639
  Files,
4640
+ Gps,
4283
4641
  LoginPrompt,
4284
4642
  PWA,
4285
4643
  Pdf,
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@auxilium/datalynk-client",
3
3
  "description": "Datalynk client library",
4
4
  "repository": "https://gitlab.auxiliumgroup.com/auxilium/datalynk/datalynk-client",
5
- "version": "1.3.22",
5
+ "version": "1.4.0",
6
6
  "author": "Zak Timson <zaktimson@gmail.com>",
7
7
  "private": false,
8
8
  "main": "./dist/index.cjs",