@magmacomputing/tempo-plugin-geo 1.3.0 → 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/CHANGELOG.md +14 -0
- package/README.md +26 -70
- package/dist/index.d.ts +8 -27
- package/dist/index.global.min.js +1 -1
- package/dist/index.js +289 -536
- package/dist/install.global.min.js +1 -1
- package/dist/install.js +289 -536
- package/package.json +4 -1
package/dist/index.js
CHANGED
|
@@ -274,7 +274,7 @@ function isNumeric(str) {
|
|
|
274
274
|
return false;
|
|
275
275
|
}
|
|
276
276
|
}
|
|
277
|
-
var isType, isPrimitive, isReference, isIterable, isString, isText, isNumber, RE_BIGINT_LITERAL, isInteger, isArray, isArrayLike, isObject, isDate, isRegExp, isSymbol, isSymbolFor, isSafeKey, isNullish, isUndefined, isDefined, isFunction, isCallable, isMap, isSet, isError, isLocale, isEmpty;
|
|
277
|
+
var isType, isPrimitive, isReference, isIterable, isString, isText, isNumber, RE_BIGINT_LITERAL, isInteger, isBoolean, isArray, isArrayLike, isObject, isDate, isRegExp, isSymbol, isSymbolFor, isSafeKey, isNullish, isUndefined, isDefined, isFunction, isCallable, isMap, isSet, isError, isLocale, isEmpty;
|
|
278
278
|
var init_assertion_library = __esm({
|
|
279
279
|
"../../library/dist/common/primitives/assertion.library.js"() {
|
|
280
280
|
"use strict";
|
|
@@ -289,6 +289,7 @@ var init_assertion_library = __esm({
|
|
|
289
289
|
isNumber = (obj) => Number.isFinite(obj);
|
|
290
290
|
RE_BIGINT_LITERAL = /^[+-]?[0-9]+n$/;
|
|
291
291
|
isInteger = (obj) => typeof obj === "bigint";
|
|
292
|
+
isBoolean = (obj) => typeof obj === "boolean";
|
|
292
293
|
isArray = (obj) => Array.isArray(obj);
|
|
293
294
|
isArrayLike = (obj) => protoType(obj) === "Object" && "length" in obj && Object.keys(obj).every((key) => key === "length" || isNumber(Number(key)));
|
|
294
295
|
isObject = (obj) => isType(obj, "Object");
|
|
@@ -2774,8 +2775,8 @@ __export(sdk_exports, {
|
|
|
2774
2775
|
__reExport(sdk_exports, sdk_star);
|
|
2775
2776
|
import * as sdk_star from "@magmacomputing/tempo/plugin/sdk";
|
|
2776
2777
|
import { definePlugin as originalPlugin, defineTerm as originalTerm } from "@magmacomputing/tempo/plugin/sdk";
|
|
2777
|
-
var definePlugin = (config) => originalPlugin({ ...config, version: "1.
|
|
2778
|
-
var defineTerm = (config) => originalTerm({ ...config, version: "1.
|
|
2778
|
+
var definePlugin = (config) => originalPlugin({ ...config, version: "1.4.0" });
|
|
2779
|
+
var defineTerm = (config) => originalTerm({ ...config, version: "1.4.0" });
|
|
2779
2780
|
|
|
2780
2781
|
// ../../library/dist/common/runtime/mapper.library.js
|
|
2781
2782
|
init_utility_library();
|
|
@@ -2794,9 +2795,13 @@ function evaluate(...values) {
|
|
|
2794
2795
|
}
|
|
2795
2796
|
|
|
2796
2797
|
// ../../library/dist/common/runtime/mapper.library.js
|
|
2797
|
-
|
|
2798
|
+
init_cache_class();
|
|
2798
2799
|
var MAP_KEY2 = "_magma_geo_";
|
|
2799
2800
|
var DEFAULT_GEO_TTL = 24 * 60 * 60 * 1e3;
|
|
2801
|
+
var DEFAULT_REVERSE_GEO_ENDPOINT = "https://api.bigdatacloud.net/data/reverse-geocode-client";
|
|
2802
|
+
var DEFAULT_REVERSE_GEO_TIMEOUT = 3e3;
|
|
2803
|
+
var DEFAULT_REVERSE_GEO_MAX_BYTES = 64 * 1024;
|
|
2804
|
+
var DEFAULT_SPATIAL_CACHE_SIZE = 1e3;
|
|
2800
2805
|
var GEO_PROPERTIES = [
|
|
2801
2806
|
"latitude",
|
|
2802
2807
|
"lat",
|
|
@@ -2811,13 +2816,33 @@ var GEO_PROPERTIES = [
|
|
|
2811
2816
|
"timezone",
|
|
2812
2817
|
"tz"
|
|
2813
2818
|
];
|
|
2814
|
-
var
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2819
|
+
var parseCoordNumber = (val) => {
|
|
2820
|
+
if (!isDefined(val) || isBoolean(val))
|
|
2821
|
+
return NaN;
|
|
2822
|
+
if (isString(val)) {
|
|
2823
|
+
const trimmed = val.trim();
|
|
2824
|
+
return trimmed.length > 0 ? Number(trimmed) : NaN;
|
|
2825
|
+
}
|
|
2826
|
+
return isNumber(val) ? val : NaN;
|
|
2827
|
+
};
|
|
2828
|
+
var normalizeLat = (lat, round = true) => {
|
|
2829
|
+
const n = parseCoordNumber(lat);
|
|
2830
|
+
if (!isNumber(n) || n < -90 || n > 90)
|
|
2831
|
+
return void 0;
|
|
2832
|
+
return round ? Math.round(n * 1e3) / 1e3 : n;
|
|
2833
|
+
};
|
|
2834
|
+
var normalizeLng = (lng, round = true) => {
|
|
2835
|
+
const n = parseCoordNumber(lng);
|
|
2836
|
+
if (!isNumber(n) || n < -180 || n > 180)
|
|
2837
|
+
return void 0;
|
|
2838
|
+
return round ? Math.round(n * 1e3) / 1e3 : n;
|
|
2839
|
+
};
|
|
2840
|
+
var normalizeCoords = (lat, lng, round = true) => {
|
|
2841
|
+
const nLat = normalizeLat(lat, round);
|
|
2842
|
+
const nLng = normalizeLng(lng, round);
|
|
2843
|
+
return isDefined(nLat) && isDefined(nLng) ? { lat: nLat, lng: nLng } : void 0;
|
|
2820
2844
|
};
|
|
2845
|
+
var normalizeElevation = (elevation) => isNumber(elevation) ? Math.round(elevation * 1e3) / 1e3 : void 0;
|
|
2821
2846
|
var resolveSphere = (sphere, lat) => {
|
|
2822
2847
|
if (sphere === "north" || sphere === "south" || sphere === "equator")
|
|
2823
2848
|
return sphere;
|
|
@@ -2825,35 +2850,47 @@ var resolveSphere = (sphere, lat) => {
|
|
|
2825
2850
|
return lat > 1e-3 ? "north" : lat < -1e-3 ? "south" : "equator";
|
|
2826
2851
|
return void 0;
|
|
2827
2852
|
};
|
|
2828
|
-
var
|
|
2853
|
+
var parseCoordinatePair = (input, normalize = true) => {
|
|
2829
2854
|
if (isString(input) && input.includes(",")) {
|
|
2830
|
-
const
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2855
|
+
const parts = input.split(",").map((s) => s.trim());
|
|
2856
|
+
return parts.length >= 2 ? normalizeCoords(parts[0], parts[1], normalize) : void 0;
|
|
2857
|
+
}
|
|
2858
|
+
return Array.isArray(input) && input.length >= 2 ? normalizeCoords(input[0], input[1], normalize) : void 0;
|
|
2859
|
+
};
|
|
2860
|
+
var assembleGeoConfig = (coords, meta) => {
|
|
2861
|
+
const lat = "lat" in coords ? coords.lat : coords.latitude;
|
|
2862
|
+
const lng = "lng" in coords ? coords.lng : coords.longitude;
|
|
2863
|
+
const nLat = normalizeLat(lat);
|
|
2864
|
+
const nLng = normalizeLng(lng);
|
|
2865
|
+
const sphere = resolveSphere(meta?.sphere, nLat ?? lat);
|
|
2866
|
+
const elevation = normalizeElevation(meta?.elevation);
|
|
2867
|
+
return {
|
|
2868
|
+
latitude: nLat ?? lat,
|
|
2869
|
+
longitude: nLng ?? lng,
|
|
2870
|
+
...sphere ? { sphere } : {},
|
|
2871
|
+
...isString(meta?.city) && !isEmpty(meta.city) ? { city: meta.city.trim() } : {},
|
|
2872
|
+
...isString(meta?.country) && !isEmpty(meta.country) ? { country: meta.country.trim() } : {},
|
|
2873
|
+
...elevation !== void 0 ? { elevation } : {},
|
|
2874
|
+
...isString(meta?.timezone) && !isEmpty(meta.timezone) ? { timezone: meta.timezone.trim() } : {}
|
|
2875
|
+
};
|
|
2876
|
+
};
|
|
2877
|
+
var extractCustomProperties = (source, excludedKeys = GEO_PROPERTIES) => {
|
|
2878
|
+
const custom = {};
|
|
2879
|
+
if (isReference(source)) {
|
|
2880
|
+
for (const key of Object.keys(source)) {
|
|
2881
|
+
if (isSafeKey(key) && !excludedKeys.includes(key)) {
|
|
2882
|
+
custom[key] = source[key];
|
|
2840
2883
|
}
|
|
2841
2884
|
}
|
|
2842
|
-
return void 0;
|
|
2843
2885
|
}
|
|
2886
|
+
return custom;
|
|
2887
|
+
};
|
|
2888
|
+
var coerceGeo = (input) => {
|
|
2889
|
+
const pair = parseCoordinatePair(input);
|
|
2890
|
+
if (pair)
|
|
2891
|
+
return assembleGeoConfig(pair);
|
|
2844
2892
|
if (isPrimitive(input))
|
|
2845
2893
|
return void 0;
|
|
2846
|
-
if (Array.isArray(input) && input.length >= 2) {
|
|
2847
|
-
const coords = normalizeCoords(input[0], input[1]);
|
|
2848
|
-
if (coords) {
|
|
2849
|
-
const result2 = { latitude: coords.lat, longitude: coords.lng };
|
|
2850
|
-
const sphere2 = resolveSphere(void 0, coords.lat);
|
|
2851
|
-
if (sphere2)
|
|
2852
|
-
result2.sphere = sphere2;
|
|
2853
|
-
return result2;
|
|
2854
|
-
}
|
|
2855
|
-
return void 0;
|
|
2856
|
-
}
|
|
2857
2894
|
const geo = input.geo ?? input;
|
|
2858
2895
|
const cfg = input.config?.geo ?? input.config;
|
|
2859
2896
|
const lat = evaluate(geo?.latitude, geo?.lat, input.latitude, input.lat, cfg?.latitude, cfg?.lat);
|
|
@@ -2870,8 +2907,9 @@ var coerceGeo = (input) => {
|
|
|
2870
2907
|
result.latitude = nLat;
|
|
2871
2908
|
if (nLng !== void 0)
|
|
2872
2909
|
result.longitude = nLng;
|
|
2873
|
-
|
|
2874
|
-
|
|
2910
|
+
const nElevation = normalizeElevation(elevation);
|
|
2911
|
+
if (nElevation !== void 0)
|
|
2912
|
+
result.elevation = nElevation;
|
|
2875
2913
|
const resolvedSphere = resolveSphere(sphere, result.latitude);
|
|
2876
2914
|
if (resolvedSphere)
|
|
2877
2915
|
result.sphere = resolvedSphere;
|
|
@@ -2882,12 +2920,8 @@ var coerceGeo = (input) => {
|
|
|
2882
2920
|
if (isString(timezone))
|
|
2883
2921
|
result.timezone = timezone;
|
|
2884
2922
|
const explicitGeo = isReference(input.geo) ? input.geo : isReference(input.config?.geo) ? input.config.geo : void 0;
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
if (isSafeKey(key) && !GEO_PROPERTIES.includes(key))
|
|
2888
|
-
result[key] = explicitGeo[key];
|
|
2889
|
-
}
|
|
2890
|
-
}
|
|
2923
|
+
const customKeys = extractCustomProperties(explicitGeo);
|
|
2924
|
+
Object.assign(result, customKeys);
|
|
2891
2925
|
return Object.keys(result).length > 0 ? result : void 0;
|
|
2892
2926
|
};
|
|
2893
2927
|
var resolveCacheKey = (keyOrOpts) => {
|
|
@@ -2924,35 +2958,23 @@ var getStashedGeo = (keyOrOpts) => {
|
|
|
2924
2958
|
return void 0;
|
|
2925
2959
|
}
|
|
2926
2960
|
}
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
if (coords) {
|
|
2931
|
-
return {
|
|
2932
|
-
latitude: coords.lat,
|
|
2933
|
-
longitude: coords.lng,
|
|
2934
|
-
sphere: resolveSphere(void 0, coords.lat)
|
|
2935
|
-
};
|
|
2936
|
-
}
|
|
2937
|
-
}
|
|
2961
|
+
const pair = parseCoordinatePair(parsed);
|
|
2962
|
+
if (pair)
|
|
2963
|
+
return assembleGeoConfig(pair);
|
|
2938
2964
|
if (isObject(parsed)) {
|
|
2939
2965
|
const rawCoords = parsed.geolocation?.coords ?? parsed.coords ?? parsed;
|
|
2940
2966
|
const lat = rawCoords?.latitude ?? rawCoords?.lat;
|
|
2941
2967
|
const lng = rawCoords?.longitude ?? rawCoords?.lng ?? rawCoords?.lon ?? rawCoords?.long;
|
|
2942
2968
|
const coords = normalizeCoords(lat, lng);
|
|
2943
2969
|
if (coords) {
|
|
2944
|
-
const result = { latitude: coords.lat, longitude: coords.lng };
|
|
2945
2970
|
const elevation = parsed.elevation ?? rawCoords.elevation;
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
if (isString(parsed.timezone))
|
|
2954
|
-
result.timezone = parsed.timezone;
|
|
2955
|
-
return result;
|
|
2971
|
+
return assembleGeoConfig(coords, {
|
|
2972
|
+
elevation,
|
|
2973
|
+
sphere: parsed.sphere,
|
|
2974
|
+
country: parsed.country,
|
|
2975
|
+
city: parsed.city,
|
|
2976
|
+
timezone: parsed.timezone
|
|
2977
|
+
});
|
|
2956
2978
|
}
|
|
2957
2979
|
}
|
|
2958
2980
|
} catch {
|
|
@@ -3043,15 +3065,7 @@ var geoLookup = async (opts = {}) => {
|
|
|
3043
3065
|
res.latitude = coords.lat;
|
|
3044
3066
|
res.longitude = coords.lng;
|
|
3045
3067
|
res.sphere = sphere;
|
|
3046
|
-
const stashPayload =
|
|
3047
|
-
latitude: coords.lat,
|
|
3048
|
-
longitude: coords.lng,
|
|
3049
|
-
sphere,
|
|
3050
|
-
...isString(res.city) ? { city: res.city } : {},
|
|
3051
|
-
...isString(res.country) ? { country: res.country } : {},
|
|
3052
|
-
...isNumber(res.elevation) ? { elevation: Math.round(res.elevation * 1e3) / 1e3 } : {},
|
|
3053
|
-
...isString(res.timezone) ? { timezone: res.timezone } : {}
|
|
3054
|
-
};
|
|
3068
|
+
const stashPayload = assembleGeoConfig(coords, res);
|
|
3055
3069
|
try {
|
|
3056
3070
|
const ttl = isNumber(opts.ttl) ? opts.ttl : DEFAULT_GEO_TTL;
|
|
3057
3071
|
stashGeo(stashPayload, ttl, opts);
|
|
@@ -3060,29 +3074,183 @@ var geoLookup = async (opts = {}) => {
|
|
|
3060
3074
|
}
|
|
3061
3075
|
return res;
|
|
3062
3076
|
};
|
|
3077
|
+
var requestModulePromise2 = null;
|
|
3078
|
+
var getRequestModule2 = () => {
|
|
3079
|
+
if (!requestModulePromise2)
|
|
3080
|
+
requestModulePromise2 = Promise.resolve().then(() => (init_request_library(), request_library_exports));
|
|
3081
|
+
return requestModulePromise2;
|
|
3082
|
+
};
|
|
3083
|
+
var reverseGeoCache = new BoundedCache(DEFAULT_SPATIAL_CACHE_SIZE, DEFAULT_GEO_TTL);
|
|
3084
|
+
var isValidGeoEndpoint = (urlStr) => {
|
|
3085
|
+
try {
|
|
3086
|
+
const parsed = new URL(urlStr);
|
|
3087
|
+
return parsed.protocol === "https:" || parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
|
|
3088
|
+
} catch {
|
|
3089
|
+
return false;
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
var getSpatialCacheKey = (lat, lng, sourceOrOpts) => {
|
|
3093
|
+
const bucket = `${lat.toFixed(2)},${lng.toFixed(2)}`;
|
|
3094
|
+
if (isString(sourceOrOpts) && !isEmpty(sourceOrOpts)) {
|
|
3095
|
+
return `${bucket}:${sourceOrOpts.trim()}`;
|
|
3096
|
+
}
|
|
3097
|
+
if (isObject(sourceOrOpts)) {
|
|
3098
|
+
const hasExplicitProvider = Object.hasOwn(sourceOrOpts, "provider");
|
|
3099
|
+
const provider = hasExplicitProvider ? sourceOrOpts.provider : activeGeoProvider;
|
|
3100
|
+
const providerName = provider && isString(provider.name) && !isEmpty(provider.name) ? provider.name.trim() : void 0;
|
|
3101
|
+
const rawEndpoint = isString(sourceOrOpts.reverseEndpoint ?? sourceOrOpts.reverseGeoEndpoint) && !isEmpty(sourceOrOpts.reverseEndpoint ?? sourceOrOpts.reverseGeoEndpoint) ? (sourceOrOpts.reverseEndpoint ?? sourceOrOpts.reverseGeoEndpoint).trim() : void 0;
|
|
3102
|
+
const endpoint = rawEndpoint && isValidGeoEndpoint(rawEndpoint) ? rawEndpoint : void 0;
|
|
3103
|
+
if (providerName && endpoint)
|
|
3104
|
+
return `${bucket}:${providerName}:${endpoint}`;
|
|
3105
|
+
if (providerName)
|
|
3106
|
+
return `${bucket}:${providerName}`;
|
|
3107
|
+
if (endpoint)
|
|
3108
|
+
return `${bucket}:${endpoint}`;
|
|
3109
|
+
} else if (activeGeoProvider && isString(activeGeoProvider.name) && !isEmpty(activeGeoProvider.name)) {
|
|
3110
|
+
return `${bucket}:${activeGeoProvider.name.trim()}`;
|
|
3111
|
+
}
|
|
3112
|
+
return bucket;
|
|
3113
|
+
};
|
|
3063
3114
|
async function reverseGeocode(coords, opts) {
|
|
3064
|
-
const
|
|
3115
|
+
const coerced = coerceGeo(coords);
|
|
3116
|
+
if (!coerced || !isNumber(coerced.latitude) || !isNumber(coerced.longitude))
|
|
3117
|
+
return null;
|
|
3118
|
+
const lat = coerced.latitude;
|
|
3119
|
+
const lng = coerced.longitude;
|
|
3120
|
+
const key = getSpatialCacheKey(lat, lng, opts);
|
|
3121
|
+
const useCache = opts?.refresh !== true;
|
|
3122
|
+
if (useCache) {
|
|
3123
|
+
const cached = reverseGeoCache.get(key);
|
|
3124
|
+
if (cached) {
|
|
3125
|
+
return {
|
|
3126
|
+
...cached,
|
|
3127
|
+
latitude: lat,
|
|
3128
|
+
longitude: lng,
|
|
3129
|
+
sphere: resolveSphere(cached.sphere, lat),
|
|
3130
|
+
elevation: isNumber(cached.elevation) ? cached.elevation : coerced.elevation,
|
|
3131
|
+
timezone: isString(cached.timezone) ? cached.timezone : coerced.timezone
|
|
3132
|
+
};
|
|
3133
|
+
}
|
|
3134
|
+
}
|
|
3135
|
+
const hasExplicitProvider = isObject(opts) && Object.hasOwn(opts, "provider");
|
|
3136
|
+
const provider = hasExplicitProvider ? opts.provider : activeGeoProvider;
|
|
3065
3137
|
if (provider && isFunction(provider.reverseGeocode)) {
|
|
3066
|
-
|
|
3138
|
+
try {
|
|
3139
|
+
const res = await provider.reverseGeocode(coerced, opts);
|
|
3140
|
+
if (res && isObject(res)) {
|
|
3141
|
+
const result = assembleGeoConfig({ lat, lng }, {
|
|
3142
|
+
sphere: res.sphere,
|
|
3143
|
+
city: res.city,
|
|
3144
|
+
country: res.country,
|
|
3145
|
+
elevation: isNumber(res.elevation) ? res.elevation : coerced.elevation,
|
|
3146
|
+
timezone: isString(res.timezone) ? res.timezone : coerced.timezone
|
|
3147
|
+
});
|
|
3148
|
+
const cachePayload = assembleGeoConfig({ lat, lng }, {
|
|
3149
|
+
sphere: res.sphere,
|
|
3150
|
+
city: res.city,
|
|
3151
|
+
country: res.country,
|
|
3152
|
+
timezone: res.timezone
|
|
3153
|
+
});
|
|
3154
|
+
reverseGeoCache.set(key, cachePayload);
|
|
3155
|
+
return result;
|
|
3156
|
+
}
|
|
3157
|
+
if (opts?.fallback === false)
|
|
3158
|
+
return null;
|
|
3159
|
+
} catch (err) {
|
|
3160
|
+
if (opts?.fallback === false)
|
|
3161
|
+
throw err;
|
|
3162
|
+
}
|
|
3163
|
+
} else if (opts?.fallback === false && (provider || hasExplicitProvider)) {
|
|
3164
|
+
return null;
|
|
3165
|
+
}
|
|
3166
|
+
const rawReverseEndpoint = opts?.reverseEndpoint ?? opts?.reverseGeoEndpoint;
|
|
3167
|
+
if (isText(rawReverseEndpoint)) {
|
|
3168
|
+
const rawEndpoint = rawReverseEndpoint.trim();
|
|
3169
|
+
if (!isValidGeoEndpoint(rawEndpoint))
|
|
3170
|
+
return opts?.fallback === false ? null : coerced;
|
|
3171
|
+
}
|
|
3172
|
+
const customEndpoint = isText(rawReverseEndpoint) ? rawReverseEndpoint.trim() : void 0;
|
|
3173
|
+
const fallbackKey = getSpatialCacheKey(lat, lng, customEndpoint ?? "default");
|
|
3174
|
+
if (useCache) {
|
|
3175
|
+
const cachedFallback = reverseGeoCache.get(fallbackKey);
|
|
3176
|
+
if (cachedFallback) {
|
|
3177
|
+
return {
|
|
3178
|
+
...cachedFallback,
|
|
3179
|
+
latitude: lat,
|
|
3180
|
+
longitude: lng,
|
|
3181
|
+
sphere: resolveSphere(cachedFallback.sphere, lat),
|
|
3182
|
+
elevation: isNumber(cachedFallback.elevation) ? cachedFallback.elevation : coerced.elevation,
|
|
3183
|
+
timezone: isString(cachedFallback.timezone) ? cachedFallback.timezone : coerced.timezone
|
|
3184
|
+
};
|
|
3185
|
+
}
|
|
3186
|
+
}
|
|
3187
|
+
let endpoint;
|
|
3188
|
+
if (customEndpoint) {
|
|
3189
|
+
if (/\{(?:latitude|lat|longitude|lng|lon)\}/i.test(customEndpoint)) {
|
|
3190
|
+
endpoint = customEndpoint.replace(/\{latitude\}/gi, encodeURIComponent(lat)).replace(/\{lat\}/gi, encodeURIComponent(lat)).replace(/\{longitude\}/gi, encodeURIComponent(lng)).replace(/\{lng\}/gi, encodeURIComponent(lng)).replace(/\{lon\}/gi, encodeURIComponent(lng));
|
|
3191
|
+
} else {
|
|
3192
|
+
const sep = customEndpoint.includes("?") ? "&" : "?";
|
|
3193
|
+
endpoint = `${customEndpoint}${sep}latitude=${encodeURIComponent(lat)}&longitude=${encodeURIComponent(lng)}`;
|
|
3194
|
+
}
|
|
3195
|
+
} else {
|
|
3196
|
+
endpoint = `${DEFAULT_REVERSE_GEO_ENDPOINT}?latitude=${lat}&longitude=${lng}&localityLanguage=en`;
|
|
3067
3197
|
}
|
|
3068
|
-
|
|
3069
|
-
|
|
3198
|
+
try {
|
|
3199
|
+
const timeout = isNumber(opts?.timeout) && opts.timeout > 0 ? opts.timeout : DEFAULT_REVERSE_GEO_TIMEOUT;
|
|
3200
|
+
const maxBytes = isNumber(opts?.maxBytes) && opts.maxBytes > 0 ? opts.maxBytes : DEFAULT_REVERSE_GEO_MAX_BYTES;
|
|
3201
|
+
const { fetchRequest: fetchRequest2 } = await getRequestModule2();
|
|
3202
|
+
const data = await fetchRequest2(endpoint, {}, { timeout, maxBytes });
|
|
3203
|
+
if (isObject(data)) {
|
|
3204
|
+
const city = isText(data.city) ? data.city.trim() : isText(data.locality) ? data.locality.trim() : isText(data.principalSubdivision) ? data.principalSubdivision.trim() : void 0;
|
|
3205
|
+
const country = isText(data.countryCode) ? data.countryCode.trim() : isText(data.countryName) ? data.countryName.trim() : void 0;
|
|
3206
|
+
const result = assembleGeoConfig({ lat, lng }, {
|
|
3207
|
+
city,
|
|
3208
|
+
country,
|
|
3209
|
+
elevation: coerced.elevation,
|
|
3210
|
+
timezone: coerced.timezone
|
|
3211
|
+
});
|
|
3212
|
+
if (isText(city) || isText(country)) {
|
|
3213
|
+
const cachePayload = assembleGeoConfig({ lat, lng }, {
|
|
3214
|
+
city,
|
|
3215
|
+
country
|
|
3216
|
+
});
|
|
3217
|
+
reverseGeoCache.set(fallbackKey, cachePayload);
|
|
3218
|
+
}
|
|
3219
|
+
return result;
|
|
3220
|
+
}
|
|
3221
|
+
} catch {
|
|
3222
|
+
}
|
|
3223
|
+
return coerced;
|
|
3070
3224
|
}
|
|
3071
3225
|
async function forwardGeocode(query, opts) {
|
|
3072
3226
|
const provider = opts?.provider ?? activeGeoProvider;
|
|
3073
|
-
|
|
3074
|
-
return provider.forwardGeocode(query, opts);
|
|
3075
|
-
}
|
|
3076
|
-
return null;
|
|
3227
|
+
return provider && isFunction(provider.forwardGeocode) ? provider.forwardGeocode(query, opts) : null;
|
|
3077
3228
|
}
|
|
3078
3229
|
var resolveGeoCoordinates = async (input, opts = {}) => {
|
|
3079
3230
|
const coerced = coerceGeo(input);
|
|
3080
|
-
if (coerced && isNumber(coerced.latitude) && isNumber(coerced.longitude))
|
|
3231
|
+
if (coerced && isNumber(coerced.latitude) && isNumber(coerced.longitude)) {
|
|
3232
|
+
const shouldReverse = opts.reverse === true || opts.autoReverse === true;
|
|
3233
|
+
if (shouldReverse && (!coerced.city || !coerced.country)) {
|
|
3234
|
+
const reversed = await reverseGeocode(coerced, opts);
|
|
3235
|
+
if (reversed) {
|
|
3236
|
+
return {
|
|
3237
|
+
...reversed,
|
|
3238
|
+
...coerced,
|
|
3239
|
+
city: isText(coerced.city) ? coerced.city : reversed.city,
|
|
3240
|
+
country: isText(coerced.country) ? coerced.country : reversed.country,
|
|
3241
|
+
lat: coerced.latitude,
|
|
3242
|
+
lng: coerced.longitude,
|
|
3243
|
+
latitude: coerced.latitude,
|
|
3244
|
+
longitude: coerced.longitude
|
|
3245
|
+
};
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3081
3248
|
return {
|
|
3082
3249
|
...coerced,
|
|
3083
3250
|
lat: coerced.latitude,
|
|
3084
3251
|
lng: coerced.longitude
|
|
3085
3252
|
};
|
|
3253
|
+
}
|
|
3086
3254
|
const stashed = opts.refresh === true ? void 0 : getStashedGeo(opts);
|
|
3087
3255
|
if (stashed && isNumber(stashed.latitude) && isNumber(stashed.longitude))
|
|
3088
3256
|
return {
|
|
@@ -3105,426 +3273,31 @@ var resolveGeoCoordinates = async (input, opts = {}) => {
|
|
|
3105
3273
|
}
|
|
3106
3274
|
return null;
|
|
3107
3275
|
};
|
|
3108
|
-
var extractRawCoords = (input) => {
|
|
3109
|
-
if (isNullish(input))
|
|
3110
|
-
return void 0;
|
|
3111
|
-
if (isString(input) && input.includes(",")) {
|
|
3112
|
-
const segments = input.split(",").map((s) => s.trim());
|
|
3113
|
-
if (segments.length >= 2 && segments[0] !== "" && segments[1] !== "") {
|
|
3114
|
-
const lat = Number(segments[0]);
|
|
3115
|
-
const lng = Number(segments[1]);
|
|
3116
|
-
if (isNumber(lat) && isNumber(lng) && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180) {
|
|
3117
|
-
return { lat, lng };
|
|
3118
|
-
}
|
|
3119
|
-
}
|
|
3120
|
-
return void 0;
|
|
3121
|
-
}
|
|
3122
|
-
if (Array.isArray(input) && input.length >= 2) {
|
|
3123
|
-
const rawLat = input[0];
|
|
3124
|
-
const rawLng = input[1];
|
|
3125
|
-
if (rawLat !== null && rawLng !== null && rawLat !== "" && rawLng !== "" && typeof rawLat !== "boolean" && typeof rawLng !== "boolean") {
|
|
3126
|
-
const lat = typeof rawLat === "string" && rawLat.trim() === "" ? NaN : Number(rawLat);
|
|
3127
|
-
const lng = typeof rawLng === "string" && rawLng.trim() === "" ? NaN : Number(rawLng);
|
|
3128
|
-
if (isNumber(lat) && isNumber(lng) && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180) {
|
|
3129
|
-
return { lat, lng };
|
|
3130
|
-
}
|
|
3131
|
-
}
|
|
3132
|
-
return void 0;
|
|
3133
|
-
}
|
|
3134
|
-
if (isReference(input)) {
|
|
3135
|
-
const geo = input.geo ?? input.config?.geo ?? input;
|
|
3136
|
-
const cfg = input.config?.geo ?? input.config;
|
|
3137
|
-
const rawLat = evaluate(geo?.latitude, geo?.lat, input.latitude, input.lat, cfg?.latitude, cfg?.lat);
|
|
3138
|
-
const rawLng = evaluate(geo?.longitude, geo?.lng, geo?.lon, geo?.long, input.longitude, input.lng, input.lon, input.long, cfg?.longitude, cfg?.lng, cfg?.lon, cfg?.long);
|
|
3139
|
-
if (rawLat !== null && rawLng !== null && rawLat !== "" && rawLng !== "" && typeof rawLat !== "boolean" && typeof rawLng !== "boolean") {
|
|
3140
|
-
const lat = typeof rawLat === "string" && rawLat.trim() === "" ? NaN : Number(rawLat);
|
|
3141
|
-
const lng = typeof rawLng === "string" && rawLng.trim() === "" ? NaN : Number(rawLng);
|
|
3142
|
-
if (isNumber(lat) && isNumber(lng) && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180) {
|
|
3143
|
-
return { lat, lng };
|
|
3144
|
-
}
|
|
3145
|
-
}
|
|
3146
|
-
}
|
|
3147
|
-
return void 0;
|
|
3148
|
-
};
|
|
3149
|
-
var toRadianCoordinates = (from, to) => {
|
|
3150
|
-
const c1 = coerceGeo(from);
|
|
3151
|
-
const c2 = coerceGeo(to);
|
|
3152
|
-
if (!c1 || !c2 || !isNumber(c1.latitude) || !isNumber(c1.longitude) || !isNumber(c2.latitude) || !isNumber(c2.longitude))
|
|
3153
|
-
return void 0;
|
|
3154
|
-
const toRad = Math.PI / 180;
|
|
3155
|
-
const lat1 = c1.latitude * toRad;
|
|
3156
|
-
const lng1 = c1.longitude * toRad;
|
|
3157
|
-
const lat2 = c2.latitude * toRad;
|
|
3158
|
-
const lng2 = c2.longitude * toRad;
|
|
3159
|
-
return {
|
|
3160
|
-
lat1,
|
|
3161
|
-
lat2,
|
|
3162
|
-
lng1,
|
|
3163
|
-
lng2,
|
|
3164
|
-
dLat: lat2 - lat1,
|
|
3165
|
-
dLng: lng2 - lng1
|
|
3166
|
-
};
|
|
3167
|
-
};
|
|
3168
|
-
function haversineDistance(from, to, unit = "km") {
|
|
3169
|
-
const coords = toRadianCoordinates(from, to);
|
|
3170
|
-
if (!coords)
|
|
3171
|
-
return NaN;
|
|
3172
|
-
const { lat1, lat2, dLat, dLng } = coords;
|
|
3173
|
-
const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) ** 2;
|
|
3174
|
-
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
3175
|
-
const radius = unit === "miles" ? 3958.7613 : unit === "m" ? 63710088e-1 : 6371.0088;
|
|
3176
|
-
const dist = radius * c;
|
|
3177
|
-
return unit === "m" ? Math.round(dist) : Math.round(dist * 1e3) / 1e3;
|
|
3178
|
-
}
|
|
3179
|
-
var resolveCivilTimezoneOffset = (tz, epochMs) => {
|
|
3180
|
-
try {
|
|
3181
|
-
if (isDefined(globalThis.Temporal) && isFunction(globalThis.Temporal.Instant?.fromEpochMilliseconds)) {
|
|
3182
|
-
const zdt = Temporal.Instant.fromEpochMilliseconds(epochMs).toZonedDateTimeISO(tz);
|
|
3183
|
-
return zdt.offsetNanoseconds / 6e10;
|
|
3184
|
-
}
|
|
3185
|
-
const parts = new Intl.DateTimeFormat("en-US", {
|
|
3186
|
-
timeZone: tz,
|
|
3187
|
-
timeZoneName: "longOffset",
|
|
3188
|
-
year: "numeric"
|
|
3189
|
-
}).formatToParts(new Date(epochMs));
|
|
3190
|
-
const tzPart = parts.find((p) => p.type === "timeZoneName")?.value;
|
|
3191
|
-
if (tzPart) {
|
|
3192
|
-
if (tzPart === "GMT" || tzPart === "UTC")
|
|
3193
|
-
return 0;
|
|
3194
|
-
const match = tzPart.match(/GMT([+-])(\d{2}):(\d{2})/);
|
|
3195
|
-
if (match) {
|
|
3196
|
-
const sign = match[1] === "-" ? -1 : 1;
|
|
3197
|
-
return sign * (parseInt(match[2], 10) * 60 + parseInt(match[3], 10));
|
|
3198
|
-
}
|
|
3199
|
-
}
|
|
3200
|
-
} catch {
|
|
3201
|
-
}
|
|
3202
|
-
return void 0;
|
|
3203
|
-
};
|
|
3204
|
-
function solarOffset(coords, options) {
|
|
3205
|
-
const geo = coerceGeo(coords);
|
|
3206
|
-
if (!geo || !isNumber(geo.latitude) || !isNumber(geo.longitude)) {
|
|
3207
|
-
return NaN;
|
|
3208
|
-
}
|
|
3209
|
-
const lng = geo.longitude;
|
|
3210
|
-
const tz = options?.timeZone ?? (isReference(coords) ? coords.timezone ?? coords.tz : void 0) ?? geo.timezone;
|
|
3211
|
-
const dateVal = options?.date ?? (isReference(coords) ? extractEpochMs(coords) : void 0);
|
|
3212
|
-
const epochMs = isDefined(dateVal) ? extractEpochMs(dateVal) : Date.now();
|
|
3213
|
-
if (!isNumber(epochMs))
|
|
3214
|
-
return NaN;
|
|
3215
|
-
const offsetMinutes = isText(tz) ? resolveCivilTimezoneOffset(tz, epochMs) : void 0;
|
|
3216
|
-
const refMeridian = offsetMinutes !== void 0 ? offsetMinutes / 60 * 15 : Math.round(lng / 15) * 15;
|
|
3217
|
-
const deltaLng = lng - refMeridian;
|
|
3218
|
-
let offsetMin = deltaLng * 4;
|
|
3219
|
-
if (options?.apparent) {
|
|
3220
|
-
const d = new Date(epochMs);
|
|
3221
|
-
const startOfYear = Date.UTC(d.getUTCFullYear(), 0, 1);
|
|
3222
|
-
const dayOfYear = Math.floor((epochMs - startOfYear) / 864e5) + 1;
|
|
3223
|
-
const gamma = 2 * Math.PI / 365 * (dayOfYear - 1);
|
|
3224
|
-
const eqTime = 229.18 * (75e-6 + 1868e-6 * Math.cos(gamma) - 0.032077 * Math.sin(gamma) - 0.014615 * Math.cos(2 * gamma) - 0.040849 * Math.sin(2 * gamma));
|
|
3225
|
-
offsetMin += eqTime;
|
|
3226
|
-
}
|
|
3227
|
-
const unit = options?.unit ?? "mi";
|
|
3228
|
-
let res;
|
|
3229
|
-
if (unit === "ss" || unit === "seconds") {
|
|
3230
|
-
res = offsetMin * 60;
|
|
3231
|
-
} else if (unit === "hh" || unit === "hours") {
|
|
3232
|
-
res = offsetMin / 60;
|
|
3233
|
-
} else {
|
|
3234
|
-
res = offsetMin;
|
|
3235
|
-
}
|
|
3236
|
-
const precision = options?.precision ?? 2;
|
|
3237
|
-
const factor = Math.pow(10, precision);
|
|
3238
|
-
return Math.round(res * factor) / factor;
|
|
3239
|
-
}
|
|
3240
|
-
function extractEpochMs(input) {
|
|
3241
|
-
if (isNullish(input))
|
|
3242
|
-
return void 0;
|
|
3243
|
-
if (isNumber(input))
|
|
3244
|
-
return input;
|
|
3245
|
-
if (isDate(input))
|
|
3246
|
-
return input.getTime();
|
|
3247
|
-
if (isReference(input)) {
|
|
3248
|
-
if (isNumber(input.epoch?.ms))
|
|
3249
|
-
return input.epoch.ms;
|
|
3250
|
-
if (isNumber(input.epochMilliseconds))
|
|
3251
|
-
return input.epochMilliseconds;
|
|
3252
|
-
if (isNumber(input.timestamp))
|
|
3253
|
-
return input.timestamp;
|
|
3254
|
-
if (isDate(input.date))
|
|
3255
|
-
return input.date.getTime();
|
|
3256
|
-
if (isFunction(input.toInstant)) {
|
|
3257
|
-
try {
|
|
3258
|
-
return input.toInstant().epochMilliseconds;
|
|
3259
|
-
} catch {
|
|
3260
|
-
}
|
|
3261
|
-
}
|
|
3262
|
-
if (isFunction(input.getTime))
|
|
3263
|
-
try {
|
|
3264
|
-
return input.getTime();
|
|
3265
|
-
} catch {
|
|
3266
|
-
}
|
|
3267
|
-
}
|
|
3268
|
-
if (isString(input)) {
|
|
3269
|
-
const parsed = Date.parse(input);
|
|
3270
|
-
if (isNumber(parsed))
|
|
3271
|
-
return parsed;
|
|
3272
|
-
}
|
|
3273
|
-
return void 0;
|
|
3274
|
-
}
|
|
3275
|
-
function calculateBearing(from, to, options) {
|
|
3276
|
-
const coords = toRadianCoordinates(from, to);
|
|
3277
|
-
if (!coords)
|
|
3278
|
-
return NaN;
|
|
3279
|
-
const { lat1, lat2, dLng } = coords;
|
|
3280
|
-
const y = Math.sin(dLng) * Math.cos(lat2);
|
|
3281
|
-
const x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLng);
|
|
3282
|
-
const bearing = (Math.atan2(y, x) * 180 / Math.PI + 360) % 360;
|
|
3283
|
-
const precision = options?.precision ?? 1;
|
|
3284
|
-
const factor = Math.pow(10, precision);
|
|
3285
|
-
return Math.round(bearing * factor) / factor;
|
|
3286
|
-
}
|
|
3287
|
-
function calculateMidpoint(from, to) {
|
|
3288
|
-
const coords = toRadianCoordinates(from, to);
|
|
3289
|
-
if (!coords)
|
|
3290
|
-
return void 0;
|
|
3291
|
-
const { lat1, lat2, lng1, dLng } = coords;
|
|
3292
|
-
const Bx = Math.cos(lat2) * Math.cos(dLng);
|
|
3293
|
-
const By = Math.cos(lat2) * Math.sin(dLng);
|
|
3294
|
-
const latMidRad = Math.atan2(Math.sin(lat1) + Math.sin(lat2), Math.sqrt((Math.cos(lat1) + Bx) ** 2 + By ** 2));
|
|
3295
|
-
const lngMidRad = lng1 + Math.atan2(By, Math.cos(lat1) + Bx);
|
|
3296
|
-
const midLat = Math.round(latMidRad * 180 / Math.PI * 1e3) / 1e3;
|
|
3297
|
-
const midLng = Math.round(((lngMidRad * 180 / Math.PI + 540) % 360 - 180) * 1e3) / 1e3;
|
|
3298
|
-
const sphere = midLat > 1e-3 ? "north" : midLat < -1e-3 ? "south" : "equator";
|
|
3299
|
-
return {
|
|
3300
|
-
latitude: midLat,
|
|
3301
|
-
longitude: midLng,
|
|
3302
|
-
sphere
|
|
3303
|
-
};
|
|
3304
|
-
}
|
|
3305
|
-
function calculateVelocity(from, to, options) {
|
|
3306
|
-
const opts = isString(options) ? { unit: options } : options ?? {};
|
|
3307
|
-
const unit = opts.unit ?? "km";
|
|
3308
|
-
const timeUnit = opts.timeUnit ?? "hh";
|
|
3309
|
-
const dist = haversineDistance(from, to, unit);
|
|
3310
|
-
if (isNaN(dist))
|
|
3311
|
-
return NaN;
|
|
3312
|
-
const t1 = extractEpochMs(from);
|
|
3313
|
-
const t2 = extractEpochMs(to);
|
|
3314
|
-
if (!isNumber(t1) || !isNumber(t2))
|
|
3315
|
-
return NaN;
|
|
3316
|
-
const deltaMs = Math.abs(t2 - t1);
|
|
3317
|
-
if (deltaMs === 0) {
|
|
3318
|
-
return dist === 0 ? 0 : Infinity;
|
|
3319
|
-
}
|
|
3320
|
-
let deltaUnits;
|
|
3321
|
-
if (timeUnit === "ss" || timeUnit === "s" || timeUnit === "seconds" || timeUnit === "second") {
|
|
3322
|
-
deltaUnits = deltaMs / 1e3;
|
|
3323
|
-
} else if (timeUnit === "mi" || timeUnit === "m" || timeUnit === "minutes" || timeUnit === "minute") {
|
|
3324
|
-
deltaUnits = deltaMs / 6e4;
|
|
3325
|
-
} else {
|
|
3326
|
-
deltaUnits = deltaMs / 36e5;
|
|
3327
|
-
}
|
|
3328
|
-
const velocity = dist / deltaUnits;
|
|
3329
|
-
const precision = opts.precision ?? 2;
|
|
3330
|
-
const factor = Math.pow(10, precision);
|
|
3331
|
-
return Math.round(velocity * factor) / factor;
|
|
3332
|
-
}
|
|
3333
|
-
function isImpossibleTravel(from, to, options) {
|
|
3334
|
-
const unit = options?.unit ?? "km";
|
|
3335
|
-
const defaultMax = unit === "miles" ? 560 : unit === "m" ? 250 : 900;
|
|
3336
|
-
const threshold = options?.maxSpeed ?? options?.maxCommercialSpeedKmH ?? defaultMax;
|
|
3337
|
-
const velocity = calculateVelocity(from, to, { unit, timeUnit: unit === "m" ? "ss" : "hh" });
|
|
3338
|
-
return velocity > threshold;
|
|
3339
|
-
}
|
|
3340
|
-
function isWithin(from, to, maxDistance, unit = "km") {
|
|
3341
|
-
if (!isNumber(maxDistance) || maxDistance < 0)
|
|
3342
|
-
return false;
|
|
3343
|
-
const c1 = extractRawCoords(from);
|
|
3344
|
-
const c2 = extractRawCoords(to);
|
|
3345
|
-
if (!c1 || !c2 || !isNumber(c1.lat) || !isNumber(c1.lng) || !isNumber(c2.lat) || !isNumber(c2.lng))
|
|
3346
|
-
return false;
|
|
3347
|
-
const toRad = Math.PI / 180;
|
|
3348
|
-
const lat1 = c1.lat * toRad;
|
|
3349
|
-
const lng1 = c1.lng * toRad;
|
|
3350
|
-
const lat2 = c2.lat * toRad;
|
|
3351
|
-
const lng2 = c2.lng * toRad;
|
|
3352
|
-
const dLat = lat2 - lat1;
|
|
3353
|
-
const dLng = lng2 - lng1;
|
|
3354
|
-
const a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
|
|
3355
|
-
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
3356
|
-
const radius = unit === "miles" ? 3958.7613 : unit === "m" ? 63710088e-1 : 6371.0088;
|
|
3357
|
-
const dist = radius * c;
|
|
3358
|
-
return dist <= maxDistance;
|
|
3359
|
-
}
|
|
3360
|
-
function inBoundingBox(coords, bbox) {
|
|
3361
|
-
const geo = extractRawCoords(coords);
|
|
3362
|
-
if (!geo || !isNumber(geo.lat) || !isNumber(geo.lng))
|
|
3363
|
-
return false;
|
|
3364
|
-
if (isNullish(bbox))
|
|
3365
|
-
return false;
|
|
3366
|
-
let minLat;
|
|
3367
|
-
let maxLat;
|
|
3368
|
-
let minLng;
|
|
3369
|
-
let maxLng;
|
|
3370
|
-
if (Array.isArray(bbox) && bbox.length >= 4) {
|
|
3371
|
-
minLat = bbox[0];
|
|
3372
|
-
minLng = bbox[1];
|
|
3373
|
-
maxLat = bbox[2];
|
|
3374
|
-
maxLng = bbox[3];
|
|
3375
|
-
} else if (isReference(bbox)) {
|
|
3376
|
-
const b = bbox;
|
|
3377
|
-
minLat = b.minLat ?? b.minLatitude;
|
|
3378
|
-
maxLat = b.maxLat ?? b.maxLatitude;
|
|
3379
|
-
minLng = b.minLng ?? b.minLongitude;
|
|
3380
|
-
maxLng = b.maxLng ?? b.maxLongitude;
|
|
3381
|
-
}
|
|
3382
|
-
if (!isNumber(minLat) || !isNumber(maxLat) || !isNumber(minLng) || !isNumber(maxLng))
|
|
3383
|
-
return false;
|
|
3384
|
-
const lat = geo.lat;
|
|
3385
|
-
const lng = geo.lng;
|
|
3386
|
-
if (lat < minLat || lat > maxLat)
|
|
3387
|
-
return false;
|
|
3388
|
-
return minLng <= maxLng ? lng >= minLng && lng <= maxLng : lng >= minLng || lng <= maxLng;
|
|
3389
|
-
}
|
|
3390
|
-
var COMMON_COUNTRY_NAMES = {
|
|
3391
|
-
australia: "AU",
|
|
3392
|
-
"united states": "US",
|
|
3393
|
-
"united kingdom": "GB",
|
|
3394
|
-
"great britain": "GB",
|
|
3395
|
-
france: "FR",
|
|
3396
|
-
germany: "DE",
|
|
3397
|
-
italy: "IT",
|
|
3398
|
-
spain: "ES",
|
|
3399
|
-
japan: "JP",
|
|
3400
|
-
china: "CN",
|
|
3401
|
-
canada: "CA",
|
|
3402
|
-
brazil: "BR",
|
|
3403
|
-
egypt: "EG",
|
|
3404
|
-
"saudi arabia": "SA",
|
|
3405
|
-
russia: "RU",
|
|
3406
|
-
india: "IN",
|
|
3407
|
-
mexico: "MX",
|
|
3408
|
-
"new zealand": "NZ",
|
|
3409
|
-
netherlands: "NL",
|
|
3410
|
-
switzerland: "CH",
|
|
3411
|
-
austria: "AT",
|
|
3412
|
-
belgium: "BE",
|
|
3413
|
-
sweden: "SE",
|
|
3414
|
-
norway: "NO",
|
|
3415
|
-
denmark: "DK",
|
|
3416
|
-
finland: "FI",
|
|
3417
|
-
poland: "PL",
|
|
3418
|
-
turkey: "TR",
|
|
3419
|
-
greece: "GR",
|
|
3420
|
-
israel: "IL",
|
|
3421
|
-
thailand: "TH",
|
|
3422
|
-
vietnam: "VN",
|
|
3423
|
-
indonesia: "ID",
|
|
3424
|
-
malaysia: "MY",
|
|
3425
|
-
philippines: "PH",
|
|
3426
|
-
"south africa": "ZA",
|
|
3427
|
-
"south korea": "KR",
|
|
3428
|
-
korea: "KR",
|
|
3429
|
-
ireland: "IE",
|
|
3430
|
-
portugal: "PT",
|
|
3431
|
-
argentina: "AR"
|
|
3432
|
-
};
|
|
3433
|
-
var COUNTRY_PRIMARY_LOCALES = {
|
|
3434
|
-
AU: "en-AU",
|
|
3435
|
-
US: "en-US",
|
|
3436
|
-
GB: "en-GB",
|
|
3437
|
-
CA: "en-CA",
|
|
3438
|
-
NZ: "en-NZ",
|
|
3439
|
-
IE: "en-IE",
|
|
3440
|
-
SA: "ar-SA",
|
|
3441
|
-
AE: "ar-AE",
|
|
3442
|
-
EG: "ar-EG",
|
|
3443
|
-
JP: "ja-JP",
|
|
3444
|
-
CN: "zh-CN",
|
|
3445
|
-
TW: "zh-TW",
|
|
3446
|
-
HK: "zh-HK",
|
|
3447
|
-
KR: "ko-KR",
|
|
3448
|
-
FR: "fr-FR",
|
|
3449
|
-
DE: "de-DE",
|
|
3450
|
-
IT: "it-IT",
|
|
3451
|
-
ES: "es-ES",
|
|
3452
|
-
MX: "es-MX",
|
|
3453
|
-
AR: "es-AR",
|
|
3454
|
-
BR: "pt-BR",
|
|
3455
|
-
PT: "pt-PT",
|
|
3456
|
-
RU: "ru-RU",
|
|
3457
|
-
IN: "hi-IN",
|
|
3458
|
-
NL: "nl-NL",
|
|
3459
|
-
SE: "sv-SE",
|
|
3460
|
-
NO: "nb-NO",
|
|
3461
|
-
DK: "da-DK",
|
|
3462
|
-
FI: "fi-FI",
|
|
3463
|
-
PL: "pl-PL",
|
|
3464
|
-
TR: "tr-TR",
|
|
3465
|
-
GR: "el-GR",
|
|
3466
|
-
IL: "he-IL",
|
|
3467
|
-
TH: "th-TH",
|
|
3468
|
-
VN: "vi-VN",
|
|
3469
|
-
ID: "id-ID",
|
|
3470
|
-
MY: "ms-MY",
|
|
3471
|
-
PH: "fil-PH",
|
|
3472
|
-
ZA: "en-ZA",
|
|
3473
|
-
CH: "de-CH",
|
|
3474
|
-
AT: "de-AT",
|
|
3475
|
-
BE: "nl-BE"
|
|
3476
|
-
};
|
|
3477
|
-
function resolveCulturalLocale(currentLocale, countryCode, mode = true) {
|
|
3478
|
-
if (mode === false || mode === "none" || mode === "off")
|
|
3479
|
-
return void 0;
|
|
3480
|
-
const toCode = (val) => {
|
|
3481
|
-
const trimmed = val.trim();
|
|
3482
|
-
if (trimmed.length === 2)
|
|
3483
|
-
return trimmed.toUpperCase();
|
|
3484
|
-
return COMMON_COUNTRY_NAMES[trimmed.toLowerCase()];
|
|
3485
|
-
};
|
|
3486
|
-
let country;
|
|
3487
|
-
if (Array.isArray(countryCode)) {
|
|
3488
|
-
for (const c of countryCode) {
|
|
3489
|
-
if (isString(c)) {
|
|
3490
|
-
const mapped = toCode(c);
|
|
3491
|
-
if (mapped) {
|
|
3492
|
-
country = mapped;
|
|
3493
|
-
break;
|
|
3494
|
-
}
|
|
3495
|
-
}
|
|
3496
|
-
}
|
|
3497
|
-
} else if (isString(countryCode)) {
|
|
3498
|
-
country = toCode(countryCode);
|
|
3499
|
-
}
|
|
3500
|
-
if (isString(mode) && mode !== "regional" && mode !== "region" && mode !== "native" && mode !== "full") {
|
|
3501
|
-
const loc2 = getLC(mode);
|
|
3502
|
-
return loc2?.baseName ?? cleanLocaleTag(mode);
|
|
3503
|
-
}
|
|
3504
|
-
if (!country)
|
|
3505
|
-
return void 0;
|
|
3506
|
-
if (mode === "native" || mode === "full") {
|
|
3507
|
-
const nativeTag = COUNTRY_PRIMARY_LOCALES[country] ?? `en-${country}`;
|
|
3508
|
-
const loc2 = getLC(nativeTag);
|
|
3509
|
-
return loc2?.baseName ?? nativeTag;
|
|
3510
|
-
}
|
|
3511
|
-
let baseLang = "en";
|
|
3512
|
-
let script;
|
|
3513
|
-
if (isString(currentLocale) && currentLocale.length > 0) {
|
|
3514
|
-
const loc2 = getLC(currentLocale);
|
|
3515
|
-
baseLang = loc2?.language ?? cleanLocaleTag(currentLocale)?.split("-")[0] ?? "en";
|
|
3516
|
-
if (loc2?.script)
|
|
3517
|
-
script = loc2.script;
|
|
3518
|
-
}
|
|
3519
|
-
const targetTag = script ? `${baseLang}-${script}-${country}` : `${baseLang}-${country}`;
|
|
3520
|
-
const loc = getLC(targetTag);
|
|
3521
|
-
return loc?.baseName ?? targetTag;
|
|
3522
|
-
}
|
|
3523
3276
|
|
|
3524
3277
|
// src/index.ts
|
|
3525
3278
|
init_mapper_library2();
|
|
3526
3279
|
init_mapper_library();
|
|
3527
|
-
|
|
3280
|
+
init_assertion_library();
|
|
3281
|
+
import {
|
|
3282
|
+
resolveCulturalLocale
|
|
3283
|
+
} from "@magmacomputing/tempo-fns";
|
|
3284
|
+
var NON_GEO_CONTROL_KEYS = [
|
|
3285
|
+
"setTimezone",
|
|
3286
|
+
"setLocale",
|
|
3287
|
+
"refresh",
|
|
3288
|
+
"ttl",
|
|
3289
|
+
"endpoint",
|
|
3290
|
+
"timeout",
|
|
3291
|
+
"maxBytes",
|
|
3292
|
+
"highAccuracy",
|
|
3293
|
+
"catch",
|
|
3294
|
+
"debug",
|
|
3295
|
+
"geo",
|
|
3296
|
+
"provider",
|
|
3297
|
+
"fallback",
|
|
3298
|
+
"reverse",
|
|
3299
|
+
"autoReverse"
|
|
3300
|
+
];
|
|
3528
3301
|
var GeoPlugin = definePlugin({
|
|
3529
3302
|
name: "geo",
|
|
3530
3303
|
install(TempoClass, options) {
|
|
@@ -3535,10 +3308,10 @@ var GeoPlugin = definePlugin({
|
|
|
3535
3308
|
const classOpts = installedClass.config?.pluginOptions?.geo;
|
|
3536
3309
|
const instanceOpts = instance?.config?.pluginOptions?.geo;
|
|
3537
3310
|
return {
|
|
3538
|
-
...
|
|
3539
|
-
...
|
|
3540
|
-
...
|
|
3541
|
-
...
|
|
3311
|
+
...isObject(options) ? options : {},
|
|
3312
|
+
...isObject(classOpts) ? classOpts : {},
|
|
3313
|
+
...isObject(instanceOpts) ? instanceOpts : {},
|
|
3314
|
+
...isObject(callSiteOpts) ? callSiteOpts : {}
|
|
3542
3315
|
};
|
|
3543
3316
|
};
|
|
3544
3317
|
if (!Object.hasOwn(installedClass, "geo")) {
|
|
@@ -3546,14 +3319,6 @@ var GeoPlugin = definePlugin({
|
|
|
3546
3319
|
lookup: (opts) => geoLookup(getEffectiveOptions(opts)),
|
|
3547
3320
|
resolve: (target, opts) => resolveGeoCoordinates(target, getEffectiveOptions(opts, target)),
|
|
3548
3321
|
coerce: coerceGeo,
|
|
3549
|
-
distance: haversineDistance,
|
|
3550
|
-
bearing: calculateBearing,
|
|
3551
|
-
midpoint: calculateMidpoint,
|
|
3552
|
-
velocity: calculateVelocity,
|
|
3553
|
-
isImpossibleTravel,
|
|
3554
|
-
isWithin,
|
|
3555
|
-
inBoundingBox,
|
|
3556
|
-
solarOffset,
|
|
3557
3322
|
stash: stashGeo,
|
|
3558
3323
|
clear: clearStashedGeo,
|
|
3559
3324
|
get: getStashedGeo,
|
|
@@ -3580,38 +3345,39 @@ var GeoPlugin = definePlugin({
|
|
|
3580
3345
|
const setLocale = effectiveOpts?.setLocale ?? true;
|
|
3581
3346
|
const coords = await resolveGeoCoordinates(this, effectiveOpts);
|
|
3582
3347
|
if (coords) {
|
|
3583
|
-
const existingGeo =
|
|
3348
|
+
const existingGeo = isObject(this.config.geo) ? this.config.geo : {};
|
|
3584
3349
|
const customKeys = {};
|
|
3585
3350
|
for (const key of Object.keys(existingGeo)) {
|
|
3586
|
-
if (
|
|
3351
|
+
if (isSafeKey(key) && !GEO_PROPERTIES.includes(key))
|
|
3587
3352
|
customKeys[key] = existingGeo[key];
|
|
3588
3353
|
}
|
|
3589
3354
|
const callSiteGeo = coerceGeo(opts) ?? {};
|
|
3590
|
-
if (
|
|
3355
|
+
if (isObject(opts)) {
|
|
3591
3356
|
for (const key of Object.keys(opts)) {
|
|
3592
|
-
if (
|
|
3357
|
+
if (isSafeKey(key) && !NON_GEO_CONTROL_KEYS.includes(key)) {
|
|
3593
3358
|
if (!GEO_PROPERTIES.includes(key))
|
|
3594
3359
|
customKeys[key] = opts[key];
|
|
3595
3360
|
}
|
|
3596
3361
|
}
|
|
3597
3362
|
}
|
|
3598
|
-
const preservedElevation =
|
|
3363
|
+
const preservedElevation = isNumber(coords?.elevation) ? coords.elevation : isNumber(existingGeo.elevation) ? existingGeo.elevation : void 0;
|
|
3599
3364
|
const mergedGeo = {
|
|
3600
3365
|
...customKeys,
|
|
3601
3366
|
...coords,
|
|
3602
|
-
...
|
|
3367
|
+
...isNumber(preservedElevation) ? { elevation: preservedElevation } : {},
|
|
3603
3368
|
...callSiteGeo
|
|
3604
3369
|
};
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
if (
|
|
3608
|
-
|
|
3609
|
-
|
|
3370
|
+
const lat = mergedGeo.latitude;
|
|
3371
|
+
const lng = mergedGeo.longitude;
|
|
3372
|
+
if (isNumber(lat)) mergedGeo.latitude = Math.round(lat * 1e3) / 1e3;
|
|
3373
|
+
if (isNumber(lng)) mergedGeo.longitude = Math.round(lng * 1e3) / 1e3;
|
|
3374
|
+
if (!mergedGeo.sphere && isNumber(lat))
|
|
3375
|
+
mergedGeo.sphere = lat > 1e-3 ? "north" : lat < -1e-3 ? "south" : "equator";
|
|
3610
3376
|
let instance = this;
|
|
3611
3377
|
const targetTz = mergedGeo.timezone;
|
|
3612
|
-
if (setTimezone &&
|
|
3378
|
+
if (setTimezone && isString(targetTz) && !isEmpty(targetTz))
|
|
3613
3379
|
instance = this.set({ timeZone: targetTz });
|
|
3614
|
-
const targetLocale = mergedGeo.country ||
|
|
3380
|
+
const targetLocale = mergedGeo.country || isString(setLocale) ? resolveCulturalLocale(this.locale ?? this.config.locale, mergedGeo.country, setLocale) : void 0;
|
|
3615
3381
|
return new TempoClass(instance, {
|
|
3616
3382
|
...instance.config,
|
|
3617
3383
|
...targetLocale ? { locale: targetLocale } : {},
|
|
@@ -3624,12 +3390,6 @@ var GeoPlugin = definePlugin({
|
|
|
3624
3390
|
TempoClass.prototype.geoLookup = async function(opts) {
|
|
3625
3391
|
return resolveGeoCoordinates(this, getEffectiveOptions(opts, this));
|
|
3626
3392
|
};
|
|
3627
|
-
TempoClass.prototype.geoDistance = function(other, unit) {
|
|
3628
|
-
return haversineDistance(this, other, unit);
|
|
3629
|
-
};
|
|
3630
|
-
TempoClass.prototype.geoSolarOffset = function(options2) {
|
|
3631
|
-
return solarOffset(this, options2);
|
|
3632
|
-
};
|
|
3633
3393
|
}
|
|
3634
3394
|
});
|
|
3635
3395
|
var geoPlugin = GeoPlugin;
|
|
@@ -3637,9 +3397,7 @@ var index_default = GeoPlugin;
|
|
|
3637
3397
|
export {
|
|
3638
3398
|
GEO_PROPERTIES,
|
|
3639
3399
|
GeoPlugin,
|
|
3640
|
-
|
|
3641
|
-
calculateMidpoint,
|
|
3642
|
-
calculateVelocity,
|
|
3400
|
+
NON_GEO_CONTROL_KEYS,
|
|
3643
3401
|
clearStashedGeo,
|
|
3644
3402
|
coerceGeo,
|
|
3645
3403
|
index_default as default,
|
|
@@ -3649,10 +3407,6 @@ export {
|
|
|
3649
3407
|
geoPlugin,
|
|
3650
3408
|
getGeoProvider,
|
|
3651
3409
|
getStashedGeo,
|
|
3652
|
-
haversineDistance,
|
|
3653
|
-
inBoundingBox,
|
|
3654
|
-
isImpossibleTravel,
|
|
3655
|
-
isWithin,
|
|
3656
3410
|
resolveCulturalLocale,
|
|
3657
3411
|
resolveGeoCoordinates,
|
|
3658
3412
|
reverseGeocode,
|
|
@@ -3660,6 +3414,5 @@ export {
|
|
|
3660
3414
|
serverGeoLocation,
|
|
3661
3415
|
serverMapHemisphere,
|
|
3662
3416
|
setGeoProvider,
|
|
3663
|
-
solarOffset,
|
|
3664
3417
|
stashGeo
|
|
3665
3418
|
};
|