@umituz/react-native-location 1.0.6 → 1.0.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-location",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Device location services for React Native with GPS, permissions, caching, and reverse geocoding",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -1,23 +1 @@
1
- export interface Coordinates {
2
- latitude: number;
3
- longitude: number;
4
- }
5
-
6
- export interface LocationAddress {
7
- city?: string | null;
8
- region?: string | null;
9
- country?: string | null;
10
- street?: string | null;
11
- formattedAddress?: string | null;
12
- }
13
-
14
- export interface LocationData {
15
- coords: Coordinates;
16
- timestamp: number;
17
- address?: LocationAddress;
18
- }
19
-
20
- export interface LocationError {
21
- code: string;
22
- message: string;
23
- }
1
+ export * from "../../types/location.types";
package/src/index.ts CHANGED
@@ -1,3 +1,7 @@
1
1
  export * from "./domain/entities/Location";
2
+ export * from "./types/location.types";
2
3
  export * from "./infrastructure/services/LocationService";
4
+ export * from "./infrastructure/services/LocationWatcher";
5
+ export * from "./infrastructure/utils/LocationUtils";
3
6
  export * from "./presentation/hooks/useLocation";
7
+ export * from "./presentation/hooks/useLocationWatch";
@@ -1,53 +1,140 @@
1
1
  import * as Location from "expo-location";
2
- import { LocationData, LocationError } from "../../domain/entities/Location";
2
+ import { storageRepository, unwrap } from "@umituz/react-native-storage";
3
+ import {
4
+ LocationData,
5
+ LocationConfig,
6
+ DEFAULT_LOCATION_CONFIG,
7
+ CachedLocationData,
8
+ LocationErrorImpl,
9
+ LocationErrorCode,
10
+ } from "../../types/location.types";
11
+
12
+ declare const __DEV__: boolean;
3
13
 
4
14
  export class LocationService {
5
- /**
6
- * Requests foreground location permissions.
7
- * @returns boolean indicating if permission was granted.
8
- */
15
+ private config: LocationConfig;
16
+ private storage = storageRepository;
17
+
18
+ constructor(config: LocationConfig = {}) {
19
+ this.config = { ...DEFAULT_LOCATION_CONFIG, ...config };
20
+ }
21
+
22
+ private log(message: string, ...args: unknown[]): void {
23
+ if (__DEV__) {
24
+ console.log(`[LocationService] ${message}`, ...args);
25
+ }
26
+ }
27
+
28
+ private logError(message: string, error: unknown): void {
29
+ if (__DEV__) {
30
+ console.error(`[LocationService] ${message}`, error);
31
+ }
32
+ }
33
+
34
+ private logWarn(message: string, ...args: unknown[]): void {
35
+ if (__DEV__) {
36
+ console.warn(`[LocationService] ${message}`, ...args);
37
+ }
38
+ }
39
+
9
40
  async requestPermissions(): Promise<boolean> {
10
41
  try {
11
- console.log("[LocationService] Requesting permissions...");
42
+ this.log("Requesting permissions...");
12
43
  const { status } = await Location.requestForegroundPermissionsAsync();
13
- console.log("[LocationService] Permission status:", status);
44
+ this.log("Permission status:", status);
14
45
  return status === "granted";
15
46
  } catch (error) {
16
- console.error("[LocationService] Error requesting permissions:", error);
47
+ this.logError("Error requesting permissions:", error);
17
48
  return false;
18
49
  }
19
50
  }
20
51
 
21
- /**
22
- * Gets the current position of the device.
23
- * @param withAddress If true, also performs reverse geocoding.
24
- */
25
- async getCurrentPosition(withAddress: boolean = false): Promise<LocationData> {
26
- console.log("[LocationService] getCurrentPosition called");
52
+ private async getCachedLocation(): Promise<LocationData | null> {
53
+ if (!this.config.enableCache) {
54
+ return null;
55
+ }
56
+
57
+ try {
58
+ const cacheKey = `location_cache_${this.config.cacheKey}`;
59
+ const result = await this.storage.getItem<CachedLocationData | null>(cacheKey, null);
60
+ const cached = unwrap(result, null);
61
+
62
+ if (!cached) {
63
+ this.log("No cached location found");
64
+ return null;
65
+ }
66
+
67
+ const now = Date.now();
68
+ const cacheAge = now - cached.timestamp;
69
+ const cacheDuration = this.config.cacheDuration || 300000;
70
+
71
+ if (cacheAge > cacheDuration) {
72
+ this.log("Cache expired");
73
+ await this.storage.removeItem(cacheKey);
74
+ return null;
75
+ }
76
+
77
+ this.log("Using cached location");
78
+ return cached.location;
79
+ } catch (error) {
80
+ this.logError("Cache read error:", error);
81
+ return null;
82
+ }
83
+ }
84
+
85
+ private async cacheLocation(location: LocationData): Promise<void> {
86
+ if (!this.config.enableCache) {
87
+ return;
88
+ }
89
+
90
+ try {
91
+ const cacheKey = `location_cache_${this.config.cacheKey}`;
92
+ const cachedData: CachedLocationData = {
93
+ location,
94
+ timestamp: Date.now(),
95
+ };
96
+ await this.storage.setItem(cacheKey, cachedData);
97
+ this.log("Location cached successfully");
98
+ } catch (error) {
99
+ this.logError("Cache write error:", error);
100
+ }
101
+ }
102
+
103
+ async getCurrentPosition(): Promise<LocationData> {
104
+ const withAddress = this.config.withAddress ?? true;
105
+
106
+ this.log("getCurrentPosition called");
107
+
108
+ const cached = await this.getCachedLocation();
109
+ if (cached) {
110
+ this.log("Returning cached location");
111
+ return cached;
112
+ }
113
+
27
114
  const hasPermission = await this.requestPermissions();
28
115
  if (!hasPermission) {
29
- console.warn("[LocationService] Permission denied");
30
- throw { code: "PERMISSION_DENIED", message: "Location permission not granted" };
116
+ this.logWarn("Permission denied");
117
+ throw new LocationErrorImpl("PERMISSION_DENIED", "Location permission not granted");
31
118
  }
32
119
 
33
120
  try {
34
- console.log("[LocationService] getting position async...");
121
+ this.log("Getting position...");
35
122
  const location = await Location.getCurrentPositionAsync({
36
- accuracy: Location.Accuracy.Balanced,
123
+ accuracy: this.config.accuracy,
37
124
  });
38
- console.log("[LocationService] position obtained", location);
125
+ this.log("Position obtained", location);
39
126
 
40
127
  let addressData;
41
128
  if (withAddress) {
42
- console.log("[LocationService] reverse geocoding...");
129
+ this.log("Reverse geocoding...");
43
130
  addressData = await this.reverseGeocode(
44
131
  location.coords.latitude,
45
132
  location.coords.longitude
46
133
  );
47
- console.log("[LocationService] address obtained", addressData);
134
+ this.log("Address obtained", addressData);
48
135
  }
49
136
 
50
- return {
137
+ const locationData: LocationData = {
51
138
  coords: {
52
139
  latitude: location.coords.latitude,
53
140
  longitude: location.coords.longitude,
@@ -55,17 +142,27 @@ export class LocationService {
55
142
  timestamp: location.timestamp,
56
143
  address: addressData,
57
144
  };
145
+
146
+ await this.cacheLocation(locationData);
147
+
148
+ return locationData;
58
149
  } catch (error) {
59
- console.error("[LocationService] Error getting location:", error);
60
- // Type guard for error object
61
- const errorMessage = error instanceof Error ? error.message : "Unknown error getting location";
62
- throw { code: "LOCATION_ERROR", message: errorMessage };
150
+ this.logError("Error getting location:", error);
151
+
152
+ let errorCode: LocationErrorCode = "UNKNOWN_ERROR";
153
+ let errorMessage = "Unknown error getting location";
154
+
155
+ if (error instanceof LocationErrorImpl) {
156
+ errorCode = error.code;
157
+ errorMessage = error.message;
158
+ } else if (error instanceof Error) {
159
+ errorMessage = error.message;
160
+ }
161
+
162
+ throw new LocationErrorImpl(errorCode, errorMessage);
63
163
  }
64
164
  }
65
165
 
66
- /**
67
- * Reverse geocodes coordinates to an address.
68
- */
69
166
  async reverseGeocode(latitude: number, longitude: number) {
70
167
  try {
71
168
  const [address] = await Location.reverseGeocodeAsync({ latitude, longitude });
@@ -79,10 +176,61 @@ export class LocationService {
79
176
  formattedAddress: [address.city, address.country].filter(Boolean).join(", "),
80
177
  };
81
178
  } catch (error) {
82
- console.warn("[LocationService] Reverse geocode failed:", error);
179
+ this.logWarn("Reverse geocode failed:", error);
83
180
  return undefined;
84
181
  }
85
182
  }
183
+
184
+ async isLocationEnabled(): Promise<boolean> {
185
+ try {
186
+ this.log("Checking if location is enabled...");
187
+ const enabled = await Location.hasServicesEnabledAsync();
188
+ this.log("Location enabled:", enabled);
189
+ return enabled;
190
+ } catch (error) {
191
+ this.logError("Error checking location enabled:", error);
192
+ return false;
193
+ }
194
+ }
195
+
196
+ async getPermissionStatus(): Promise<Location.PermissionStatus> {
197
+ try {
198
+ this.log("Getting permission status...");
199
+ const status = await Location.getForegroundPermissionsAsync();
200
+ this.log("Permission status:", status.status);
201
+ return status.status;
202
+ } catch (error) {
203
+ this.logError("Error getting permission status:", error);
204
+ return "undetermined";
205
+ }
206
+ }
207
+
208
+ async getLastKnownPosition(): Promise<LocationData | null> {
209
+ try {
210
+ this.log("Getting last known position...");
211
+ const location = await Location.getLastKnownPositionAsync();
212
+
213
+ if (!location) {
214
+ this.log("No last known position available");
215
+ return null;
216
+ }
217
+
218
+ this.log("Last known position obtained", location);
219
+
220
+ return {
221
+ coords: {
222
+ latitude: location.coords.latitude,
223
+ longitude: location.coords.longitude,
224
+ },
225
+ timestamp: location.timestamp,
226
+ };
227
+ } catch (error) {
228
+ this.logError("Error getting last known position:", error);
229
+ return null;
230
+ }
231
+ }
86
232
  }
87
233
 
88
- export const locationService = new LocationService();
234
+ export function createLocationService(config?: LocationConfig): LocationService {
235
+ return new LocationService(config);
236
+ }
@@ -0,0 +1,116 @@
1
+ import * as Location from "expo-location";
2
+ import {
3
+ LocationData,
4
+ LocationError,
5
+ LocationCallback,
6
+ LocationErrorCallback,
7
+ LocationWatcherOptions,
8
+ LocationErrorImpl,
9
+ LocationErrorCode,
10
+ } from "../../types/location.types";
11
+
12
+ declare const __DEV__: boolean;
13
+
14
+ export class LocationWatcher {
15
+ private subscription: Location.LocationSubscription | null = null;
16
+ private options: LocationWatcherOptions;
17
+
18
+ constructor(options: LocationWatcherOptions = {}) {
19
+ this.options = options;
20
+ }
21
+
22
+ private log(message: string, ...args: unknown[]): void {
23
+ if (__DEV__) {
24
+ console.log(`[LocationWatcher] ${message}`, ...args);
25
+ }
26
+ }
27
+
28
+ private logError(message: string, error: unknown): void {
29
+ if (__DEV__) {
30
+ console.error(`[LocationWatcher] ${message}`, error);
31
+ }
32
+ }
33
+
34
+ async watchPosition(
35
+ onSuccess: LocationCallback,
36
+ onError?: LocationErrorCallback
37
+ ): Promise<string> {
38
+ try {
39
+ this.log("Requesting permissions...");
40
+ const { status } = await Location.requestForegroundPermissionsAsync();
41
+
42
+ if (status !== "granted") {
43
+ const error: LocationError = {
44
+ code: "PERMISSION_DENIED",
45
+ message: "Location permission not granted",
46
+ };
47
+ if (onError) {
48
+ onError(error);
49
+ }
50
+ throw new LocationErrorImpl("PERMISSION_DENIED", "Location permission not granted");
51
+ }
52
+
53
+ this.log("Starting location watch...");
54
+
55
+ this.subscription = await Location.watchPositionAsync(
56
+ {
57
+ accuracy: this.options.accuracy || Location.Accuracy.Balanced,
58
+ },
59
+ (location) => {
60
+ this.log("Location update received", location);
61
+
62
+ const locationData: LocationData = {
63
+ coords: {
64
+ latitude: location.coords.latitude,
65
+ longitude: location.coords.longitude,
66
+ },
67
+ timestamp: location.timestamp,
68
+ };
69
+
70
+ onSuccess(locationData);
71
+ }
72
+ );
73
+
74
+ return "watching";
75
+ } catch (error) {
76
+ this.logError("Error watching position:", error);
77
+
78
+ let errorCode: LocationErrorCode = "UNKNOWN_ERROR";
79
+ let errorMessage = "Unknown error watching location";
80
+
81
+ if (error instanceof LocationErrorImpl) {
82
+ errorCode = error.code;
83
+ errorMessage = error.message;
84
+ } else if (error instanceof Error) {
85
+ errorMessage = error.message;
86
+ }
87
+
88
+ const locationError: LocationError = {
89
+ code: errorCode,
90
+ message: errorMessage,
91
+ };
92
+
93
+ if (onError) {
94
+ onError(locationError);
95
+ }
96
+
97
+ throw new LocationErrorImpl(errorCode, errorMessage);
98
+ }
99
+ }
100
+
101
+ clearWatch(): void {
102
+ if (this.subscription) {
103
+ this.log("Clearing location watch");
104
+ this.subscription.remove();
105
+ this.subscription = null;
106
+ }
107
+ }
108
+
109
+ isWatching(): boolean {
110
+ return this.subscription !== null;
111
+ }
112
+ }
113
+
114
+ export function createLocationWatcher(options?: LocationWatcherOptions): LocationWatcher {
115
+ return new LocationWatcher(options);
116
+ }
@@ -0,0 +1,83 @@
1
+ import { Coordinates, DistanceUnit } from "../../types/location.types";
2
+
3
+ export class LocationUtils {
4
+ private static readonly EARTH_RADIUS_KM = 6371;
5
+ private static readonly EARTH_RADIUS_MILES = 3959;
6
+ private static readonly EARTH_RADIUS_METERS = 6371000;
7
+
8
+ static calculateDistance(
9
+ from: Coordinates,
10
+ to: Coordinates,
11
+ unit: DistanceUnit = "km"
12
+ ): number {
13
+ const lat1Rad = (from.latitude * Math.PI) / 180;
14
+ const lat2Rad = (to.latitude * Math.PI) / 180;
15
+ const deltaLatRad = ((to.latitude - from.latitude) * Math.PI) / 180;
16
+ const deltaLonRad = ((to.longitude - from.longitude) * Math.PI) / 180;
17
+
18
+ const a =
19
+ Math.sin(deltaLatRad / 2) * Math.sin(deltaLatRad / 2) +
20
+ Math.cos(lat1Rad) *
21
+ Math.cos(lat2Rad) *
22
+ Math.sin(deltaLonRad / 2) *
23
+ Math.sin(deltaLonRad / 2);
24
+
25
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
26
+
27
+ switch (unit) {
28
+ case "miles":
29
+ return this.EARTH_RADIUS_MILES * c;
30
+ case "meters":
31
+ return this.EARTH_RADIUS_METERS * c;
32
+ case "km":
33
+ default:
34
+ return this.EARTH_RADIUS_KM * c;
35
+ }
36
+ }
37
+
38
+ static isValidCoordinate(latitude: number, longitude: number): boolean {
39
+ return (
40
+ latitude >= -90 &&
41
+ latitude <= 90 &&
42
+ longitude >= -180 &&
43
+ longitude <= 180
44
+ );
45
+ }
46
+
47
+ static isValidAccuracy(accuracy: number | null | undefined, maxAccuracy = 100): boolean {
48
+ if (accuracy === null || accuracy === undefined) {
49
+ return false;
50
+ }
51
+ return accuracy > 0 && accuracy <= maxAccuracy;
52
+ }
53
+
54
+ static formatAccuracy(accuracy: number | null | undefined): string {
55
+ if (accuracy === null || accuracy === undefined) {
56
+ return "Unknown";
57
+ }
58
+
59
+ if (accuracy < 10) {
60
+ return "Excellent (±" + Math.round(accuracy) + "m)";
61
+ }
62
+ if (accuracy < 50) {
63
+ return "Good (±" + Math.round(accuracy) + "m)";
64
+ }
65
+ if (accuracy < 100) {
66
+ return "Fair (±" + Math.round(accuracy) + "m)";
67
+ }
68
+ return "Poor (±" + Math.round(accuracy) + "m)";
69
+ }
70
+
71
+ static coordinatesAreEqual(
72
+ coord1: Coordinates,
73
+ coord2: Coordinates,
74
+ precision = 6
75
+ ): boolean {
76
+ const lat1 = coord1.latitude.toFixed(precision);
77
+ const lat2 = coord2.latitude.toFixed(precision);
78
+ const lon1 = coord1.longitude.toFixed(precision);
79
+ const lon2 = coord2.longitude.toFixed(precision);
80
+
81
+ return lat1 === lat2 && lon1 === lon2;
82
+ }
83
+ }
@@ -1,6 +1,6 @@
1
- import { useState, useCallback } from "react";
2
- import { locationService } from "../../infrastructure/services/LocationService";
3
- import { LocationData, LocationError } from "../../domain/entities/Location";
1
+ import { useState, useCallback, useRef } from "react";
2
+ import { createLocationService } from "../../infrastructure/services/LocationService";
3
+ import { LocationData, LocationError, LocationConfig } from "../../types/location.types";
4
4
 
5
5
  export interface UseLocationResult {
6
6
  location: LocationData | null;
@@ -9,7 +9,8 @@ export interface UseLocationResult {
9
9
  getCurrentLocation: () => Promise<LocationData | null>;
10
10
  }
11
11
 
12
- export function useLocation(): UseLocationResult {
12
+ export function useLocation(config?: LocationConfig): UseLocationResult {
13
+ const serviceRef = useRef(createLocationService(config));
13
14
  const [location, setLocation] = useState<LocationData | null>(null);
14
15
  const [isLoading, setIsLoading] = useState(false);
15
16
  const [error, setError] = useState<LocationError | null>(null);
@@ -17,15 +18,24 @@ export function useLocation(): UseLocationResult {
17
18
  const getCurrentLocation = useCallback(async () => {
18
19
  setIsLoading(true);
19
20
  setError(null);
21
+
20
22
  try {
21
- const data = await locationService.getCurrentPosition(true);
23
+ const data = await serviceRef.current.getCurrentPosition();
22
24
  setLocation(data);
23
25
  return data;
24
- } catch (err: any) {
25
- const errorObj = {
26
- code: err.code || "UNKNOWN_ERROR",
27
- message: err.message || "An unknown error occurred",
26
+ } catch (err) {
27
+ let errorObj: LocationError = {
28
+ code: "UNKNOWN_ERROR",
29
+ message: "An unknown error occurred",
28
30
  };
31
+
32
+ if (err && typeof err === "object" && "code" in err && "message" in err) {
33
+ errorObj = {
34
+ code: typeof err.code === "string" ? err.code : "UNKNOWN_ERROR",
35
+ message: typeof err.message === "string" ? err.message : "An unknown error occurred",
36
+ };
37
+ }
38
+
29
39
  setError(errorObj);
30
40
  return null;
31
41
  } finally {
@@ -0,0 +1,75 @@
1
+ import { useEffect, useRef, useState, useCallback } from "react";
2
+ import { createLocationWatcher } from "../../infrastructure/services/LocationWatcher";
3
+ import { LocationData, LocationError, LocationWatcherOptions } from "../../types/location.types";
4
+
5
+ export interface UseLocationWatchResult {
6
+ location: LocationData | null;
7
+ error: LocationError | null;
8
+ isWatching: boolean;
9
+ startWatching: () => Promise<void>;
10
+ stopWatching: () => void;
11
+ }
12
+
13
+ export function useLocationWatch(options?: LocationWatcherOptions): UseLocationWatchResult {
14
+ const watcherRef = useRef<ReturnType<typeof createLocationWatcher> | null>(null);
15
+ const [location, setLocation] = useState<LocationData | null>(null);
16
+ const [error, setError] = useState<LocationError | null>(null);
17
+ const [isWatching, setIsWatching] = useState(false);
18
+
19
+ const stopWatching = useCallback(() => {
20
+ if (watcherRef.current) {
21
+ watcherRef.current.clearWatch();
22
+ watcherRef.current = null;
23
+ setIsWatching(false);
24
+ }
25
+ }, []);
26
+
27
+ const startWatching = useCallback(async () => {
28
+ stopWatching();
29
+
30
+ const watcher = createLocationWatcher(options);
31
+ watcherRef.current = watcher;
32
+
33
+ try {
34
+ await watcher.watchPosition(
35
+ (data) => {
36
+ setLocation(data);
37
+ setError(null);
38
+ },
39
+ (err) => {
40
+ setError(err);
41
+ }
42
+ );
43
+ setIsWatching(true);
44
+ } catch (err) {
45
+ let errorObj: LocationError = {
46
+ code: "UNKNOWN_ERROR",
47
+ message: "An unknown error occurred",
48
+ };
49
+
50
+ if (err && typeof err === "object" && "code" in err && "message" in err) {
51
+ errorObj = {
52
+ code: typeof err.code === "string" ? err.code : "UNKNOWN_ERROR",
53
+ message: typeof err.message === "string" ? err.message : "An unknown error occurred",
54
+ };
55
+ }
56
+
57
+ setError(errorObj);
58
+ setIsWatching(false);
59
+ }
60
+ }, [options, stopWatching]);
61
+
62
+ useEffect(() => {
63
+ return () => {
64
+ stopWatching();
65
+ };
66
+ }, [stopWatching]);
67
+
68
+ return {
69
+ location,
70
+ error,
71
+ isWatching,
72
+ startWatching,
73
+ stopWatching,
74
+ };
75
+ }
@@ -0,0 +1,78 @@
1
+ import * as Location from "expo-location";
2
+
3
+ export interface Coordinates {
4
+ latitude: number;
5
+ longitude: number;
6
+ }
7
+
8
+ export interface LocationAddress {
9
+ city?: string | null;
10
+ region?: string | null;
11
+ country?: string | null;
12
+ street?: string | null;
13
+ formattedAddress?: string | null;
14
+ }
15
+
16
+ export interface LocationData {
17
+ coords: Coordinates;
18
+ timestamp: number;
19
+ address?: LocationAddress;
20
+ }
21
+
22
+ export interface LocationError {
23
+ code: string;
24
+ message: string;
25
+ }
26
+
27
+ export interface CachedLocationData {
28
+ location: LocationData;
29
+ timestamp: number;
30
+ }
31
+
32
+ export type DistanceUnit = "km" | "miles" | "meters";
33
+
34
+ export type LocationErrorCode =
35
+ | "PERMISSION_DENIED"
36
+ | "LOCATION_UNAVAILABLE"
37
+ | "TIMEOUT"
38
+ | "CACHE_ERROR"
39
+ | "UNKNOWN_ERROR";
40
+
41
+ export interface LocationConfig {
42
+ accuracy?: Location.Accuracy;
43
+ timeout?: number;
44
+ enableCache?: boolean;
45
+ cacheKey?: string;
46
+ cacheDuration?: number;
47
+ withAddress?: boolean;
48
+ distanceFilter?: number;
49
+ }
50
+
51
+ export const DEFAULT_LOCATION_CONFIG: LocationConfig = {
52
+ accuracy: Location.Accuracy.Balanced,
53
+ timeout: 10000,
54
+ enableCache: true,
55
+ cacheKey: "default",
56
+ cacheDuration: 300000,
57
+ withAddress: true,
58
+ distanceFilter: 10,
59
+ };
60
+
61
+ export type LocationCallback = (location: LocationData) => void;
62
+ export type LocationErrorCallback = (error: LocationError) => void;
63
+
64
+ export interface LocationWatcherOptions {
65
+ accuracy?: Location.Accuracy;
66
+ distanceFilter?: number;
67
+ timeout?: number;
68
+ }
69
+
70
+ export class LocationErrorImpl extends Error implements LocationError {
71
+ code: LocationErrorCode;
72
+
73
+ constructor(code: LocationErrorCode, message: string) {
74
+ super(message);
75
+ this.name = "LocationError";
76
+ this.code = code;
77
+ }
78
+ }