@flighthq/geolocation 0.5.1-next.815.cc08b93 → 0.5.1-next.903.f434bc2
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 +2 -2
- package/dist/contract.d.ts +1 -0
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +1 -0
- package/dist/contract.js.map +1 -1
- package/dist/geolocation.d.ts +8 -13
- package/dist/geolocation.d.ts.map +1 -1
- package/dist/geolocation.js +103 -168
- package/dist/geolocation.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/geolocation.test.ts +55 -180
package/README.md
CHANGED
|
@@ -13,5 +13,5 @@ Import the supported application-facing API from `@flighthq/geolocation`. The `@
|
|
|
13
13
|
This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
|
|
14
14
|
|
|
15
15
|
- [Flight project](https://github.com/flighthq/flight)
|
|
16
|
-
- [Source for @flighthq/geolocation@0.5.1-next.
|
|
17
|
-
- [License](https://github.com/flighthq/flight/blob/
|
|
16
|
+
- [Source for @flighthq/geolocation@0.5.1-next.903.f434bc2](https://github.com/flighthq/flight/tree/f434bc233778d75aeea61995df3a8cfaec459a85/packages/geolocation)
|
|
17
|
+
- [License](https://github.com/flighthq/flight/blob/f434bc233778d75aeea61995df3a8cfaec459a85/LICENSE.md)
|
package/dist/contract.d.ts
CHANGED
package/dist/contract.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"contract.d.ts","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/contract.js
CHANGED
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/geolocation.d.ts
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export declare function clearGeolocationWatch(id: number): void;
|
|
1
|
+
import type { GeolocationBackend, GeolocationErrorReason, GeolocationRequestOptions, GeoPosition, GeoPositionResult, HasSystemGeolocation, EntityConstruction } from '@flighthq/types/contract';
|
|
2
|
+
export declare function clearGeolocationWatch(host: Readonly<HasSystemGeolocation>, id: number): void;
|
|
4
3
|
export declare function createGeoPosition(): GeoPosition;
|
|
5
4
|
export declare function createWebGeolocationBackend(): GeolocationBackend;
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
10
|
-
export declare function
|
|
11
|
-
export declare function
|
|
12
|
-
export declare function observeGeolocationHostResult(operation: string, succeeded: boolean): void;
|
|
13
|
-
export declare function resetGeolocationBackendForTest(): void;
|
|
14
|
-
export declare function setGeolocationBackend(backend: GeolocationBackend | null): void;
|
|
15
|
-
export declare function watchGeolocationPosition(handler: (position: Readonly<GeoPosition>) => void, options?: Readonly<GeolocationRequestOptions>, onError?: (reason: GeolocationErrorReason) => void): number;
|
|
5
|
+
export declare function getCurrentGeoPosition(host: Readonly<HasSystemGeolocation>, options?: Readonly<GeolocationRequestOptions>): Promise<GeoPosition | null>;
|
|
6
|
+
export declare function getCurrentGeoPositionResult(host: Readonly<HasSystemGeolocation>, options?: Readonly<GeolocationRequestOptions>): Promise<GeoPositionResult>;
|
|
7
|
+
export declare function initializeGeoPosition(out: EntityConstruction<GeoPosition>): void;
|
|
8
|
+
export declare function initializeWebGeolocationBackend(out: EntityConstruction<GeolocationBackend>): void;
|
|
9
|
+
export declare function isGeolocationAvailable(host: Readonly<HasSystemGeolocation>): boolean;
|
|
10
|
+
export declare function watchGeolocationPosition(host: Readonly<HasSystemGeolocation>, handler: (position: Readonly<GeoPosition>) => void, options?: Readonly<GeolocationRequestOptions>, onError?: (reason: GeolocationErrorReason) => void): number;
|
|
16
11
|
//# sourceMappingURL=geolocation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geolocation.d.ts","sourceRoot":"","sources":["../src/geolocation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"geolocation.d.ts","sourceRoot":"","sources":["../src/geolocation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,kBAAkB,EAClB,sBAAsB,EACtB,yBAAyB,EACzB,WAAW,EACX,iBAAiB,EACjB,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAElC,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAE5F;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAI/C;AAED,wBAAgB,2BAA2B,IAAI,kBAAkB,CAIhE;AAED,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EACpC,OAAO,CAAC,EAAE,QAAQ,CAAC,yBAAyB,CAAC,GAC5C,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAE7B;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EACpC,OAAO,CAAC,EAAE,QAAQ,CAAC,yBAAyB,CAAC,GAC5C,OAAO,CAAC,iBAAiB,CAAC,CAE5B;AAED,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,kBAAkB,CAAC,WAAW,CAAC,GAAG,IAAI,CAUhF;AAED,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,kBAAkB,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAgFjG;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,OAAO,CAEpF;AAED,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,QAAQ,CAAC,oBAAoB,CAAC,EACpC,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,KAAK,IAAI,EAClD,OAAO,CAAC,EAAE,QAAQ,CAAC,yBAAyB,CAAC,EAC7C,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,sBAAsB,KAAK,IAAI,GACjD,MAAM,CAER"}
|
package/dist/geolocation.js
CHANGED
|
@@ -1,178 +1,115 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export function clearGeolocationWatch(id) {
|
|
3
|
-
|
|
1
|
+
import { allocateEntity, finishEntity } from '@flighthq/entity/contract';
|
|
2
|
+
export function clearGeolocationWatch(host, id) {
|
|
3
|
+
host.system.geolocation.clearWatch(id);
|
|
4
4
|
}
|
|
5
5
|
export function createGeoPosition() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
altitudeAccuracy: 0,
|
|
10
|
-
floorLevel: 0,
|
|
11
|
-
heading: 0,
|
|
12
|
-
latitude: 0,
|
|
13
|
-
longitude: 0,
|
|
14
|
-
speed: 0,
|
|
15
|
-
timestamp: 0,
|
|
16
|
-
});
|
|
6
|
+
const out = allocateEntity();
|
|
7
|
+
initializeGeoPosition(out);
|
|
8
|
+
return finishEntity(out);
|
|
17
9
|
}
|
|
18
|
-
// Builds the default web backend over navigator.geolocation. Position reads resolve to null and
|
|
19
|
-
// permission requests resolve to false when the API is absent (insecure context, jsdom) or the user
|
|
20
|
-
// denies access — location access is not guaranteed.
|
|
21
10
|
export function createWebGeolocationBackend() {
|
|
22
|
-
|
|
23
|
-
|
|
11
|
+
const out = allocateEntity();
|
|
12
|
+
initializeWebGeolocationBackend(out);
|
|
13
|
+
return finishEntity(out);
|
|
14
|
+
}
|
|
15
|
+
export function getCurrentGeoPosition(host, options) {
|
|
16
|
+
return host.system.geolocation.getCurrentPosition(options ?? _emptyOptions);
|
|
17
|
+
}
|
|
18
|
+
export function getCurrentGeoPositionResult(host, options) {
|
|
19
|
+
return host.system.geolocation.getCurrentPositionResult(options ?? _emptyOptions);
|
|
20
|
+
}
|
|
21
|
+
export function initializeGeoPosition(out) {
|
|
22
|
+
out.accuracy = 0;
|
|
23
|
+
out.altitude = 0;
|
|
24
|
+
out.altitudeAccuracy = 0;
|
|
25
|
+
out.floorLevel = 0;
|
|
26
|
+
out.heading = 0;
|
|
27
|
+
out.latitude = 0;
|
|
28
|
+
out.longitude = 0;
|
|
29
|
+
out.speed = 0;
|
|
30
|
+
out.timestamp = 0;
|
|
31
|
+
}
|
|
32
|
+
export function initializeWebGeolocationBackend(out) {
|
|
33
|
+
out.clearWatch = (id) => {
|
|
34
|
+
const geo = getWebGeolocation();
|
|
35
|
+
if (geo === null || typeof geo.clearWatch !== 'function')
|
|
36
|
+
return;
|
|
37
|
+
try {
|
|
38
|
+
geo.clearWatch(id);
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// Expected failure: the watch may already be gone or the host may deny access.
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
out.getCurrentPosition = (options) => {
|
|
45
|
+
return new Promise((resolve) => {
|
|
24
46
|
const geo = getWebGeolocation();
|
|
25
|
-
if (geo === null || typeof geo.
|
|
47
|
+
if (geo === null || typeof geo.getCurrentPosition !== 'function') {
|
|
48
|
+
resolve(null);
|
|
26
49
|
return;
|
|
50
|
+
}
|
|
27
51
|
try {
|
|
28
|
-
geo.
|
|
52
|
+
geo.getCurrentPosition((position) => resolve(mapWebPosition(position)), () => resolve(null), toPositionOptions(options));
|
|
29
53
|
}
|
|
30
54
|
catch {
|
|
31
|
-
|
|
55
|
+
resolve(null);
|
|
32
56
|
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (geo === null || typeof geo.getCurrentPosition !== 'function') {
|
|
38
|
-
resolve(null);
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
try {
|
|
42
|
-
geo.getCurrentPosition((position) => resolve(mapWebPosition(position)), () => resolve(null), toPositionOptions(options));
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
resolve(null);
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
},
|
|
49
|
-
getCurrentPositionResult(options) {
|
|
50
|
-
return new Promise((resolve) => {
|
|
51
|
-
const geo = getWebGeolocation();
|
|
52
|
-
if (geo === null || typeof geo.getCurrentPosition !== 'function') {
|
|
53
|
-
resolve({ position: null, reason: 'unavailable' });
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
geo.getCurrentPosition((position) => resolve({ position: mapWebPosition(position), reason: null }), (error) => resolve({ position: null, reason: mapWebPositionError(error) }), toPositionOptions(options));
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
resolve({ position: null, reason: 'unavailable' });
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
},
|
|
64
|
-
isAvailable() {
|
|
65
|
-
if (typeof window !== 'undefined' && window.isSecureContext === false)
|
|
66
|
-
return false;
|
|
67
|
-
return getWebGeolocation() !== null;
|
|
68
|
-
},
|
|
69
|
-
// The web has no permission-request API: the prompt is raised as a side effect of a position
|
|
70
|
-
// read. Code 1 is a refusal; code 3 is an acquisition TIMEOUT and says nothing about the user, so
|
|
71
|
-
// it is reported as such rather than guessed at. 'dismissed' is reachable only on hosts that can
|
|
72
|
-
// actually observe a closed-undecided prompt, which the web cannot.
|
|
73
|
-
promptForAccess() {
|
|
74
|
-
return new Promise((resolve) => {
|
|
75
|
-
const geo = getWebGeolocation();
|
|
76
|
-
if (geo === null || typeof geo.getCurrentPosition !== 'function') {
|
|
77
|
-
resolve({ reason: 'runtime-unavailable' });
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
try {
|
|
81
|
-
geo.getCurrentPosition(() => resolve({ reason: 'granted' }), (error) => resolve({ reason: mapWebAccessError(error) }));
|
|
82
|
-
}
|
|
83
|
-
catch {
|
|
84
|
-
resolve({ reason: 'operation-failed' });
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
},
|
|
88
|
-
watchPosition(listener, options, onError) {
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
out.getCurrentPositionResult = (options) => {
|
|
60
|
+
return new Promise((resolve) => {
|
|
89
61
|
const geo = getWebGeolocation();
|
|
90
|
-
if (geo === null || typeof geo.
|
|
91
|
-
|
|
62
|
+
if (geo === null || typeof geo.getCurrentPosition !== 'function') {
|
|
63
|
+
resolve({ position: null, reason: 'unavailable' });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
92
66
|
try {
|
|
93
|
-
|
|
67
|
+
geo.getCurrentPosition((position) => resolve({ position: mapWebPosition(position), reason: null }), (error) => resolve({ position: null, reason: mapWebPositionError(error) }), toPositionOptions(options));
|
|
94
68
|
}
|
|
95
69
|
catch {
|
|
96
|
-
|
|
70
|
+
resolve({ position: null, reason: 'unavailable' });
|
|
97
71
|
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
_host = backend;
|
|
131
|
-
}
|
|
132
|
-
export function isGeolocationAvailable() {
|
|
133
|
-
return getGeolocationBackend().isAvailable();
|
|
134
|
-
}
|
|
135
|
-
export function observeGeolocationHostResult(operation, succeeded) {
|
|
136
|
-
_hostObservation = {
|
|
137
|
-
operation,
|
|
138
|
-
viability: succeeded ? 'available' : 'runtime-api-unavailable',
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
out.isAvailable = () => {
|
|
75
|
+
if (typeof window !== 'undefined' && window.isSecureContext === false)
|
|
76
|
+
return false;
|
|
77
|
+
return getWebGeolocation() !== null;
|
|
78
|
+
};
|
|
79
|
+
out.promptForAccess = () => {
|
|
80
|
+
return new Promise((resolve) => {
|
|
81
|
+
const geo = getWebGeolocation();
|
|
82
|
+
if (geo === null || typeof geo.getCurrentPosition !== 'function') {
|
|
83
|
+
resolve({ reason: 'runtime-unavailable' });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
geo.getCurrentPosition(() => resolve({ reason: 'granted' }), (error) => resolve({ reason: mapWebAccessError(error) }));
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
resolve({ reason: 'operation-failed' });
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
out.watchPosition = (listener, options, onError) => {
|
|
95
|
+
const geo = getWebGeolocation();
|
|
96
|
+
if (geo === null || typeof geo.watchPosition !== 'function')
|
|
97
|
+
return -1;
|
|
98
|
+
try {
|
|
99
|
+
return geo.watchPosition((position) => listener(mapWebPosition(position)), onError !== undefined ? (error) => onError(mapWebPositionError(error)) : () => { }, toPositionOptions(options));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return -1;
|
|
103
|
+
}
|
|
139
104
|
};
|
|
140
105
|
}
|
|
141
|
-
export function
|
|
142
|
-
|
|
143
|
-
_host = null;
|
|
144
|
-
_hostConflict = false;
|
|
145
|
-
_hostObservation = null;
|
|
146
|
-
}
|
|
147
|
-
export function setGeolocationBackend(backend) {
|
|
148
|
-
_custom = backend;
|
|
106
|
+
export function isGeolocationAvailable(host) {
|
|
107
|
+
return host.system.geolocation.isAvailable();
|
|
149
108
|
}
|
|
150
|
-
export function watchGeolocationPosition(handler, options, onError) {
|
|
151
|
-
return
|
|
109
|
+
export function watchGeolocationPosition(host, handler, options, onError) {
|
|
110
|
+
return host.system.geolocation.watchPosition(handler, options ?? _emptyOptions, onError);
|
|
152
111
|
}
|
|
153
|
-
let _custom = null;
|
|
154
|
-
let _host = null;
|
|
155
|
-
let _hostConflict = false;
|
|
156
|
-
let _hostObservation = null;
|
|
157
112
|
const _emptyOptions = {};
|
|
158
|
-
const _sentinel = createEntity({
|
|
159
|
-
clearWatch() { },
|
|
160
|
-
getCurrentPosition() {
|
|
161
|
-
return Promise.resolve(null);
|
|
162
|
-
},
|
|
163
|
-
getCurrentPositionResult() {
|
|
164
|
-
return Promise.resolve({ position: null, reason: 'unavailable' });
|
|
165
|
-
},
|
|
166
|
-
isAvailable() {
|
|
167
|
-
return false;
|
|
168
|
-
},
|
|
169
|
-
promptForAccess() {
|
|
170
|
-
return Promise.resolve({ reason: 'runtime-unavailable' });
|
|
171
|
-
},
|
|
172
|
-
watchPosition() {
|
|
173
|
-
return -1;
|
|
174
|
-
},
|
|
175
|
-
});
|
|
176
113
|
function getWebGeolocation() {
|
|
177
114
|
if (typeof navigator === 'undefined')
|
|
178
115
|
return null;
|
|
@@ -180,19 +117,17 @@ function getWebGeolocation() {
|
|
|
180
117
|
}
|
|
181
118
|
function mapWebPosition(position) {
|
|
182
119
|
const coords = position.coords;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
timestamp: position.timestamp,
|
|
195
|
-
});
|
|
120
|
+
const out = allocateEntity();
|
|
121
|
+
out.accuracy = coords.accuracy;
|
|
122
|
+
out.altitude = coords.altitude ?? 0;
|
|
123
|
+
out.altitudeAccuracy = coords.altitudeAccuracy ?? 0;
|
|
124
|
+
out.floorLevel = coords.floorLevel ?? 0;
|
|
125
|
+
out.heading = coords.heading ?? 0;
|
|
126
|
+
out.latitude = coords.latitude;
|
|
127
|
+
out.longitude = coords.longitude;
|
|
128
|
+
out.speed = coords.speed ?? 0;
|
|
129
|
+
out.timestamp = position.timestamp;
|
|
130
|
+
return finishEntity(out);
|
|
196
131
|
}
|
|
197
132
|
function mapWebAccessError(error) {
|
|
198
133
|
switch (error.code) {
|
package/dist/geolocation.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geolocation.js","sourceRoot":"","sources":["../src/geolocation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"geolocation.js","sourceRoot":"","sources":["../src/geolocation.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { clearGeolocationWatch, createGeoPosition, getCurrentGeoPosition, getCurrentGeoPositionResult, isGeolocationAvailable, promptForGeolocationAccess, watchGeolocationPosition, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { clearGeolocationWatch, createGeoPosition, getCurrentGeoPosition, getCurrentGeoPositionResult, isGeolocationAvailable, promptForGeolocationAccess, watchGeolocationPosition, } from './contract';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,EAC3B,sBAAsB,EACtB,0BAA0B,EAC1B,wBAAwB,GACzB,MAAM,YAAY,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flighthq/geolocation",
|
|
3
|
-
"version": "0.5.1-next.
|
|
3
|
+
"version": "0.5.1-next.903.f434bc2",
|
|
4
4
|
"author": "Joshua Granick and other contributors",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"clean:dist": "tsx ../../scripts/clean-package-dist.ts"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@flighthq/entity": "0.5.1-next.
|
|
42
|
-
"@flighthq/types": "0.5.1-next.
|
|
41
|
+
"@flighthq/entity": "0.5.1-next.903.f434bc2",
|
|
42
|
+
"@flighthq/types": "0.5.1-next.903.f434bc2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"typescript": "^5.3.0"
|
package/src/geolocation.test.ts
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
1
|
+
import { allocateEntity, finishEntity } from '@flighthq/entity/contract';
|
|
2
|
+
import type {
|
|
3
|
+
Entity,
|
|
4
|
+
GeolocationBackend,
|
|
5
|
+
GeolocationErrorReason,
|
|
6
|
+
GeoPosition,
|
|
7
|
+
HasSystemGeolocation,
|
|
8
|
+
} from '@flighthq/types/contract';
|
|
3
9
|
import { EntityRuntimeKey } from '@flighthq/types/contract';
|
|
4
10
|
|
|
5
11
|
import {
|
|
@@ -8,63 +14,55 @@ import {
|
|
|
8
14
|
createWebGeolocationBackend,
|
|
9
15
|
getCurrentGeoPosition,
|
|
10
16
|
getCurrentGeoPositionResult,
|
|
11
|
-
getGeolocationBackend,
|
|
12
17
|
isGeolocationAvailable,
|
|
13
|
-
setGeolocationBackend,
|
|
14
18
|
watchGeolocationPosition,
|
|
15
|
-
explainGeolocationBackend,
|
|
16
|
-
installGeolocationHostBackend,
|
|
17
|
-
observeGeolocationHostResult,
|
|
18
|
-
resetGeolocationBackendForTest,
|
|
19
19
|
} from './geolocation';
|
|
20
20
|
|
|
21
21
|
function fakeBackend(available: boolean = true): GeolocationBackend & { cleared: number[]; lastWatch: number } {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
22
|
+
const out = allocateEntity<any>();
|
|
23
|
+
out.cleared = [];
|
|
24
|
+
out.lastWatch = 0;
|
|
25
|
+
out.promptForAccess = () => Promise.resolve({ reason: 'granted' as const });
|
|
26
|
+
out.clearWatch = (id: number) => {
|
|
27
|
+
out.cleared.push(id);
|
|
28
|
+
};
|
|
29
|
+
out.getCurrentPosition = async () => {
|
|
30
|
+
const position = createGeoPosition();
|
|
31
|
+
position.latitude = 1;
|
|
32
|
+
position.longitude = 2;
|
|
33
|
+
return position;
|
|
34
|
+
};
|
|
35
|
+
out.getCurrentPositionResult = async () => {
|
|
36
|
+
const position = createGeoPosition();
|
|
37
|
+
position.latitude = 1;
|
|
38
|
+
position.longitude = 2;
|
|
39
|
+
return { position, reason: null };
|
|
40
|
+
};
|
|
41
|
+
out.isAvailable = () => {
|
|
42
|
+
return available;
|
|
43
|
+
};
|
|
44
|
+
out.watchPosition = (
|
|
45
|
+
listener: (position: GeoPosition) => void,
|
|
46
|
+
_options: Record<string, unknown>,
|
|
47
|
+
onError?: (reason: GeolocationErrorReason) => void,
|
|
48
|
+
) => {
|
|
49
|
+
const position = createGeoPosition();
|
|
50
|
+
position.latitude = 3;
|
|
51
|
+
listener(position);
|
|
52
|
+
if (onError) onError('denied');
|
|
53
|
+
return ++out.lastWatch;
|
|
54
|
+
};
|
|
55
|
+
return finishEntity(out);
|
|
52
56
|
}
|
|
53
57
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
});
|
|
58
|
+
function hostWith(backend: GeolocationBackend): HasSystemGeolocation {
|
|
59
|
+
return { system: { geolocation: backend } } as HasSystemGeolocation;
|
|
60
|
+
}
|
|
58
61
|
|
|
59
62
|
describe('clearGeolocationWatch', () => {
|
|
60
|
-
it('
|
|
61
|
-
expect(() => clearGeolocationWatch(0)).not.toThrow();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('forwards the id to the active backend', () => {
|
|
63
|
+
it('forwards the id to the host backend', () => {
|
|
65
64
|
const backend = fakeBackend();
|
|
66
|
-
|
|
67
|
-
clearGeolocationWatch(7);
|
|
65
|
+
clearGeolocationWatch(hostWith(backend), 7);
|
|
68
66
|
expect(backend.cleared).toEqual([7]);
|
|
69
67
|
});
|
|
70
68
|
});
|
|
@@ -153,40 +151,13 @@ describe('createWebGeolocationBackend', () => {
|
|
|
153
151
|
vi.stubGlobal('window', { isSecureContext: true });
|
|
154
152
|
expect(backend.isAvailable()).toBe(false);
|
|
155
153
|
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
describe('explainGeolocationBackend', () => {
|
|
159
|
-
afterEach(() => resetGeolocationBackendForTest());
|
|
160
|
-
|
|
161
|
-
it('reports host-not-enabled when no backend is installed', () => {
|
|
162
|
-
resetGeolocationBackendForTest();
|
|
163
|
-
const explanation = explainGeolocationBackend();
|
|
164
|
-
expect(explanation.layer).toBe('host-not-enabled');
|
|
165
|
-
expect(explanation.conflict).toBe(false);
|
|
166
|
-
expect(explanation.viability).toBe('unobserved');
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
it('reports custom layer when a custom backend is set', () => {
|
|
170
|
-
setGeolocationBackend(fakeBackend());
|
|
171
|
-
expect(explainGeolocationBackend().layer).toBe('custom');
|
|
172
|
-
});
|
|
173
154
|
|
|
174
|
-
|
|
175
|
-
installGeolocationHostBackend(fakeBackend());
|
|
176
|
-
expect(explainGeolocationBackend().layer).toBe('host');
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('reports conflict when two different host backends are installed', () => {
|
|
180
|
-
installGeolocationHostBackend(fakeBackend());
|
|
181
|
-
installGeolocationHostBackend(fakeBackend());
|
|
182
|
-
expect(explainGeolocationBackend().conflict).toBe(true);
|
|
183
|
-
});
|
|
155
|
+
afterEach(() => vi.unstubAllGlobals());
|
|
184
156
|
});
|
|
185
157
|
|
|
186
158
|
describe('getCurrentGeoPosition', () => {
|
|
187
159
|
it('returns the backend position', async () => {
|
|
188
|
-
|
|
189
|
-
const position = (await getCurrentGeoPosition()) as GeoPosition;
|
|
160
|
+
const position = (await getCurrentGeoPosition(hostWith(fakeBackend()))) as GeoPosition;
|
|
190
161
|
expect(position.latitude).toBe(1);
|
|
191
162
|
expect(position.longitude).toBe(2);
|
|
192
163
|
});
|
|
@@ -194,116 +165,24 @@ describe('getCurrentGeoPosition', () => {
|
|
|
194
165
|
|
|
195
166
|
describe('getCurrentGeoPositionResult', () => {
|
|
196
167
|
it('returns position and null reason on success', async () => {
|
|
197
|
-
|
|
198
|
-
const result = await getCurrentGeoPositionResult();
|
|
168
|
+
const result = await getCurrentGeoPositionResult(hostWith(fakeBackend()));
|
|
199
169
|
expect(result.position).not.toBeNull();
|
|
200
170
|
expect(result.position!.latitude).toBe(1);
|
|
201
171
|
expect(result.reason).toBeNull();
|
|
202
172
|
});
|
|
203
|
-
|
|
204
|
-
it('returns null position with a reason on failure (web backend in jsdom)', async () => {
|
|
205
|
-
const result = await getCurrentGeoPositionResult();
|
|
206
|
-
expect(result.position).toBeNull();
|
|
207
|
-
expect(result.reason).toBe('unavailable');
|
|
208
|
-
});
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
describe('getGeolocationBackend', () => {
|
|
212
|
-
it('falls back to a web backend', () => {
|
|
213
|
-
expect(getGeolocationBackend()).not.toBeNull();
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
it('returns the registered backend', () => {
|
|
217
|
-
const backend = fakeBackend();
|
|
218
|
-
setGeolocationBackend(backend);
|
|
219
|
-
expect(getGeolocationBackend()).toBe(backend);
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
describe('installGeolocationHostBackend', () => {
|
|
224
|
-
afterEach(() => resetGeolocationBackendForTest());
|
|
225
|
-
|
|
226
|
-
it('installs a host backend that getGeolocationBackend returns', () => {
|
|
227
|
-
const backend = fakeBackend();
|
|
228
|
-
installGeolocationHostBackend(backend);
|
|
229
|
-
expect(getGeolocationBackend()).toBe(backend);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it('is first-host-wins: a second different backend sets conflict', () => {
|
|
233
|
-
const first = fakeBackend();
|
|
234
|
-
const second = fakeBackend();
|
|
235
|
-
installGeolocationHostBackend(first);
|
|
236
|
-
installGeolocationHostBackend(second);
|
|
237
|
-
expect(getGeolocationBackend()).toBe(first);
|
|
238
|
-
expect(explainGeolocationBackend().conflict).toBe(true);
|
|
239
|
-
});
|
|
240
173
|
});
|
|
241
174
|
|
|
242
175
|
describe('isGeolocationAvailable', () => {
|
|
243
|
-
it('
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
expect(isGeolocationAvailable()).toBe(false);
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it('routes a custom available provider when DOM globals are absent', () => {
|
|
250
|
-
vi.stubGlobal('navigator', undefined);
|
|
251
|
-
vi.stubGlobal('window', undefined);
|
|
252
|
-
setGeolocationBackend(fakeBackend(true));
|
|
253
|
-
expect(isGeolocationAvailable()).toBe(true);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it('routes an unavailable host provider when browser geolocation exists', () => {
|
|
257
|
-
vi.stubGlobal('navigator', { geolocation: {} });
|
|
258
|
-
vi.stubGlobal('window', { isSecureContext: true });
|
|
259
|
-
installGeolocationHostBackend(fakeBackend(false));
|
|
260
|
-
expect(isGeolocationAvailable()).toBe(false);
|
|
261
|
-
});
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
describe('observeGeolocationHostResult', () => {
|
|
265
|
-
afterEach(() => resetGeolocationBackendForTest());
|
|
266
|
-
|
|
267
|
-
it('records a successful observation', () => {
|
|
268
|
-
installGeolocationHostBackend(fakeBackend());
|
|
269
|
-
observeGeolocationHostResult('clearWatch', true);
|
|
270
|
-
const explanation = explainGeolocationBackend();
|
|
271
|
-
expect(explanation.operation).toBe('clearWatch');
|
|
272
|
-
expect(explanation.viability).toBe('available');
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it('records a failed observation', () => {
|
|
276
|
-
installGeolocationHostBackend(fakeBackend());
|
|
277
|
-
observeGeolocationHostResult('clearWatch', false);
|
|
278
|
-
expect(explainGeolocationBackend().viability).toBe('runtime-api-unavailable');
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
describe('resetGeolocationBackendForTest', () => {
|
|
283
|
-
it('clears all backend slots', () => {
|
|
284
|
-
setGeolocationBackend(fakeBackend());
|
|
285
|
-
installGeolocationHostBackend(fakeBackend());
|
|
286
|
-
observeGeolocationHostResult('clearWatch', true);
|
|
287
|
-
resetGeolocationBackendForTest();
|
|
288
|
-
expect(explainGeolocationBackend().layer).toBe('host-not-enabled');
|
|
289
|
-
expect(explainGeolocationBackend().conflict).toBe(false);
|
|
290
|
-
expect(explainGeolocationBackend().viability).toBe('unobserved');
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
describe('setGeolocationBackend', () => {
|
|
295
|
-
it('clears back to the web fallback when passed null', () => {
|
|
296
|
-
setGeolocationBackend(fakeBackend());
|
|
297
|
-
setGeolocationBackend(null);
|
|
298
|
-
expect(getGeolocationBackend()).not.toBeNull();
|
|
176
|
+
it('routes the host backend availability', () => {
|
|
177
|
+
expect(isGeolocationAvailable(hostWith(fakeBackend(true)))).toBe(true);
|
|
178
|
+
expect(isGeolocationAvailable(hostWith(fakeBackend(false)))).toBe(false);
|
|
299
179
|
});
|
|
300
180
|
});
|
|
301
181
|
|
|
302
182
|
describe('watchGeolocationPosition', () => {
|
|
303
183
|
it('delivers positions and returns a watch id', () => {
|
|
304
|
-
setGeolocationBackend(fakeBackend());
|
|
305
184
|
let seen = 0;
|
|
306
|
-
const id = watchGeolocationPosition((position) => {
|
|
185
|
+
const id = watchGeolocationPosition(hostWith(fakeBackend()), (position) => {
|
|
307
186
|
seen = position.latitude;
|
|
308
187
|
});
|
|
309
188
|
expect(id).toBe(1);
|
|
@@ -311,17 +190,13 @@ describe('watchGeolocationPosition', () => {
|
|
|
311
190
|
});
|
|
312
191
|
|
|
313
192
|
it('delivers error reasons when onError is provided', () => {
|
|
314
|
-
setGeolocationBackend(fakeBackend());
|
|
315
193
|
const errors: GeolocationErrorReason[] = [];
|
|
316
194
|
watchGeolocationPosition(
|
|
195
|
+
hostWith(fakeBackend()),
|
|
317
196
|
() => {},
|
|
318
197
|
{},
|
|
319
198
|
(reason) => errors.push(reason),
|
|
320
199
|
);
|
|
321
200
|
expect(errors).toEqual(['denied']);
|
|
322
201
|
});
|
|
323
|
-
|
|
324
|
-
it('returns -1 from the web backend when watching is unavailable', () => {
|
|
325
|
-
expect(watchGeolocationPosition(() => {})).toBe(-1);
|
|
326
|
-
});
|
|
327
202
|
});
|