@magmacomputing/tempo-plugin-geo 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -257,7 +257,7 @@ var init_type_library = __esm({
257
257
  });
258
258
 
259
259
  // ../../library/dist/common/primitives/assertion.library.js
260
- var isType, isPrimitive, isReference, isString, isNumber, isInteger, isArray, isObject, isDate, isSymbol, isSymbolFor, isSafeKey, isNullish, isUndefined, isDefined, isFunction, isMap, isSet, isError, isEmpty;
260
+ var isType, isPrimitive, isReference, isString, isText, isNumber, isInteger, isArray, isObject, isDate, isSymbol, isSymbolFor, isSafeKey, isNullish, isUndefined, isDefined, isFunction, isMap, isSet, isError, isEmpty;
261
261
  var init_assertion_library = __esm({
262
262
  "../../library/dist/common/primitives/assertion.library.js"() {
263
263
  "use strict";
@@ -267,6 +267,7 @@ var init_assertion_library = __esm({
267
267
  isPrimitive = (obj) => isType(obj, "String", "Number", "BigInt", "Boolean", "Symbol", "Undefined", "Void", "Null", "Empty");
268
268
  isReference = (obj) => !isPrimitive(obj);
269
269
  isString = (obj) => isType(obj, "String");
270
+ isText = (obj) => isString(obj) && obj.trim().length > 0;
270
271
  isNumber = (obj) => Number.isFinite(obj);
271
272
  isInteger = (obj) => isType(obj, "BigInt");
272
273
  isArray = (obj) => isType(obj, "Array");
@@ -340,37 +341,6 @@ var init_utility_library = __esm({
340
341
  }
341
342
  });
342
343
 
343
- // ../../library/dist/common/primitives/object.library.js
344
- function looseIndex(arg) {
345
- if (isDefined(arg))
346
- return isFunction(arg) ? arg() : arg;
347
- return (obj) => isFunction(obj) ? obj() : obj;
348
- }
349
- var asObject;
350
- var init_object_library = __esm({
351
- "../../library/dist/common/primitives/object.library.js"() {
352
- "use strict";
353
- init_primitive_library();
354
- init_assertion_library();
355
- init_type_library();
356
- asObject = (obj) => {
357
- if (isNullish(obj) || !isObject(obj))
358
- return obj;
359
- const temp = isArray(obj) ? [] : {};
360
- ownKeys(obj).forEach((key) => {
361
- if (!isSafeKey(key))
362
- return;
363
- temp[key] = asObject(obj[key]);
364
- });
365
- return temp;
366
- };
367
- looseIndex.stringSymbol = looseIndex();
368
- looseIndex.symbolRegExp = looseIndex();
369
- looseIndex.symbolString = looseIndex();
370
- looseIndex.stringString = looseIndex();
371
- }
372
- });
373
-
374
344
  // ../../library/dist/common/runtime/reflection.library.js
375
345
  function allObject(json) {
376
346
  return Object.fromEntries(ownEntries(json, true));
@@ -852,8 +822,590 @@ var init_serialize_library = __esm({
852
822
  "%7C": "|",
853
823
  "%7D": "}"
854
824
  };
855
- RE_SAFE_URI_CODES = new RegExp(Object.keys(SAFE_URI_MAP).join("|"), "gi");
856
- symKey = /^@(@)?\(([^\)]*)\)$/;
825
+ RE_SAFE_URI_CODES = new RegExp(Object.keys(SAFE_URI_MAP).join("|"), "gi");
826
+ symKey = /^@(@)?\(([^\)]*)\)$/;
827
+ }
828
+ });
829
+
830
+ // ../../../node_modules/tslib/tslib.es6.mjs
831
+ function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
832
+ function accept(f) {
833
+ if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected");
834
+ return f;
835
+ }
836
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
837
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
838
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
839
+ var _, done = false;
840
+ for (var i = decorators.length - 1; i >= 0; i--) {
841
+ var context3 = {};
842
+ for (var p in contextIn) context3[p] = p === "access" ? {} : contextIn[p];
843
+ for (var p in contextIn.access) context3.access[p] = contextIn.access[p];
844
+ context3.addInitializer = function(f) {
845
+ if (done) throw new TypeError("Cannot add initializers after decoration has completed");
846
+ extraInitializers.push(accept(f || null));
847
+ };
848
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context3);
849
+ if (kind === "accessor") {
850
+ if (result === void 0) continue;
851
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
852
+ if (_ = accept(result.get)) descriptor.get = _;
853
+ if (_ = accept(result.set)) descriptor.set = _;
854
+ if (_ = accept(result.init)) initializers.unshift(_);
855
+ } else if (_ = accept(result)) {
856
+ if (kind === "field") initializers.unshift(_);
857
+ else descriptor[key] = _;
858
+ }
859
+ }
860
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
861
+ done = true;
862
+ }
863
+ function __runInitializers(thisArg, initializers, value2) {
864
+ var useValue = arguments.length > 2;
865
+ for (var i = 0; i < initializers.length; i++) {
866
+ value2 = useValue ? initializers[i].call(thisArg, value2) : initializers[i].call(thisArg);
867
+ }
868
+ return useValue ? value2 : void 0;
869
+ }
870
+ var init_tslib_es6 = __esm({
871
+ "../../../node_modules/tslib/tslib.es6.mjs"() {
872
+ "use strict";
873
+ }
874
+ });
875
+
876
+ // ../../library/dist/common/runtime/decorator.library.js
877
+ function getClassName(value2, contextName) {
878
+ return getSafeTag(value2) ?? (isUndefined(contextName) ? value2.name || void 0 : String(contextName));
879
+ }
880
+ function Serializable(value2, { kind, name, addInitializer }) {
881
+ const finalName = getClassName(value2, name);
882
+ if (finalName)
883
+ registerType(value2, finalName);
884
+ switch (kind) {
885
+ case "class":
886
+ if (finalName)
887
+ addInitializer(() => registerSerializable(finalName, value2));
888
+ return value2;
889
+ default:
890
+ throw new Error(`@Serializable decorating unknown 'kind': ${kind} (${name})`);
891
+ }
892
+ }
893
+ function StringTag(tagOrValue, context3) {
894
+ const applyTag = (value2, customTag, contextName) => {
895
+ const proto = value2.prototype;
896
+ const tagName = customTag ?? getClassName(value2, contextName);
897
+ if (tagName) {
898
+ if (proto && !Object.hasOwn(proto, Symbol.toStringTag)) {
899
+ Object.defineProperty(proto, Symbol.toStringTag, {
900
+ value: tagName,
901
+ configurable: true,
902
+ writable: false,
903
+ enumerable: false
904
+ });
905
+ }
906
+ if (!value2.name || value2.name !== tagName) {
907
+ try {
908
+ Object.defineProperty(value2, "name", {
909
+ value: tagName,
910
+ configurable: true,
911
+ writable: false,
912
+ enumerable: false
913
+ });
914
+ } catch {
915
+ }
916
+ }
917
+ }
918
+ return value2;
919
+ };
920
+ if (typeof tagOrValue === "function" && context3?.kind === "class")
921
+ return applyTag(tagOrValue, void 0, context3.name);
922
+ return (value2, ctx) => {
923
+ return applyTag(value2, isString(tagOrValue) ? tagOrValue : void 0, ctx?.name);
924
+ };
925
+ }
926
+ var init_decorator_library = __esm({
927
+ "../../library/dist/common/runtime/decorator.library.js"() {
928
+ "use strict";
929
+ init_symbol_library();
930
+ init_proxy_library();
931
+ init_assertion_library();
932
+ init_serialize_library();
933
+ init_type_library();
934
+ }
935
+ });
936
+
937
+ // ../../library/dist/common/runtime/cache.class.js
938
+ var BoundedCache;
939
+ var init_cache_class = __esm({
940
+ "../../library/dist/common/runtime/cache.class.js"() {
941
+ "use strict";
942
+ init_tslib_es6();
943
+ init_assertion_library();
944
+ init_decorator_library();
945
+ BoundedCache = (() => {
946
+ let _classDecorators = [StringTag("BoundedCache")];
947
+ let _classDescriptor;
948
+ let _classExtraInitializers = [];
949
+ let _classThis;
950
+ let _classSuper = Map;
951
+ var BoundedCache2 = class extends _classSuper {
952
+ static {
953
+ _classThis = this;
954
+ }
955
+ static {
956
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
957
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
958
+ BoundedCache2 = _classThis = _classDescriptor.value;
959
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
960
+ __runInitializers(_classThis, _classExtraInitializers);
961
+ }
962
+ #expires = /* @__PURE__ */ new Map();
963
+ #staticKeys = /* @__PURE__ */ new Set();
964
+ #ttls = /* @__PURE__ */ new Map();
965
+ maxSize;
966
+ ttl;
967
+ /**
968
+ * Creates a bounded cache with configurable capacity and entry lifetime.
969
+ *
970
+ * @param maxSize - Maximum number of non-static entries retained
971
+ * @param ttl - Default time-to-live for entries in milliseconds
972
+ */
973
+ constructor(maxSize = 1e3, ttl = 24 * 60 * 60 * 1e3) {
974
+ super();
975
+ this.maxSize = maxSize;
976
+ this.ttl = ttl;
977
+ }
978
+ /**
979
+ * Returns true to identify this instance as a BoundedCache.
980
+ */
981
+ get isBoundedCache() {
982
+ return true;
983
+ }
984
+ /**
985
+ * Determines whether a cache entry has passed its expiration deadline.
986
+ *
987
+ * @param key - Cache key to inspect
988
+ * @returns True when the entry has expired, otherwise false
989
+ */
990
+ #isExpired(key) {
991
+ const deadline = this.#expires.get(key);
992
+ if (deadline === void 0)
993
+ return false;
994
+ return Date.now() > deadline;
995
+ }
996
+ /**
997
+ * Purges TTL-expired entries.
998
+ */
999
+ evictExpired() {
1000
+ if (this.#expires.size === 0)
1001
+ return;
1002
+ const now = Date.now();
1003
+ for (const [key, deadline] of this.#expires.entries()) {
1004
+ if (now > deadline) {
1005
+ this.delete(key);
1006
+ }
1007
+ }
1008
+ }
1009
+ /**
1010
+ * Register an immortal static key (e.g. business glossary term).
1011
+ * Static keys bypass TTL expiration and LRU capacity eviction.
1012
+ */
1013
+ setStatic(key, value2) {
1014
+ if (super.has(key))
1015
+ super.delete(key);
1016
+ super.set(key, value2);
1017
+ this.#staticKeys.add(key);
1018
+ this.#expires.delete(key);
1019
+ this.#ttls.delete(key);
1020
+ return this;
1021
+ }
1022
+ /**
1023
+ * Check if a key is a static key.
1024
+ */
1025
+ isStatic(key) {
1026
+ return this.#staticKeys.has(key);
1027
+ }
1028
+ /**
1029
+ * Retrieves a value from the cache by key. Evaluates TTL expiration via `#expires`
1030
+ * specifically for the requested key, and updates LRU ordering by deleting and re-inserting
1031
+ * the key in the underlying Map. Leaves the expiration deadline unchanged.
1032
+ *
1033
+ * @param key - The cache key to retrieve
1034
+ * @returns The cached value, or undefined if not found or expired
1035
+ */
1036
+ get(key) {
1037
+ if (this.#isExpired(key)) {
1038
+ this.delete(key);
1039
+ return void 0;
1040
+ }
1041
+ if (!super.has(key))
1042
+ return void 0;
1043
+ const val = super.get(key);
1044
+ super.delete(key);
1045
+ super.set(key, val);
1046
+ return val;
1047
+ }
1048
+ /**
1049
+ * Checks if a key exists in the cache and is not expired.
1050
+ * Automatically evicts expired entries on access.
1051
+ *
1052
+ * @param key - The cache key to check
1053
+ * @returns True if the key exists and is not expired, false otherwise
1054
+ */
1055
+ has(key) {
1056
+ if (this.#isExpired(key)) {
1057
+ this.delete(key);
1058
+ return false;
1059
+ }
1060
+ return super.has(key);
1061
+ }
1062
+ /**
1063
+ * Returns the number of entries in the cache after evicting expired entries.
1064
+ */
1065
+ get size() {
1066
+ this.evictExpired();
1067
+ return super.size;
1068
+ }
1069
+ /**
1070
+ * Executes a callback for each cache entry after evicting expired entries.
1071
+ *
1072
+ * @param callbackfn - Function to execute for each entry
1073
+ * @param thisArg - Optional value to use as `this` when executing the callback
1074
+ */
1075
+ forEach(callbackfn, thisArg) {
1076
+ this.evictExpired();
1077
+ super.forEach(callbackfn, thisArg);
1078
+ }
1079
+ /**
1080
+ * Sets a key-value pair in the cache, enforcing LRU eviction.
1081
+ * If finite-TTL is configured, entries retain their original absolute expiration deadline
1082
+ * unless an explicit `ttl` override is passed.
1083
+ * If the cache exceeds maxSize, the oldest non-static entry is removed.
1084
+ *
1085
+ * @param key - The cache key to set
1086
+ * @param value - The value to store
1087
+ * @param ttl - Optional custom time-to-live in milliseconds for this specific entry
1088
+ * @returns This cache instance for chaining
1089
+ */
1090
+ set(key, value2, ttl) {
1091
+ this.evictExpired();
1092
+ const existingDeadline = this.#expires.get(key);
1093
+ if (super.has(key))
1094
+ super.delete(key);
1095
+ super.set(key, value2);
1096
+ this.#staticKeys.delete(key);
1097
+ if (isDefined(ttl)) {
1098
+ if (ttl !== Infinity) {
1099
+ this.#expires.set(key, Date.now() + ttl);
1100
+ this.#ttls.set(key, ttl);
1101
+ } else {
1102
+ this.#expires.delete(key);
1103
+ this.#ttls.delete(key);
1104
+ }
1105
+ } else if (existingDeadline !== void 0) {
1106
+ this.#expires.set(key, existingDeadline);
1107
+ } else if (this.ttl !== Infinity) {
1108
+ this.#expires.set(key, Date.now() + this.ttl);
1109
+ this.#ttls.delete(key);
1110
+ } else {
1111
+ this.#expires.delete(key);
1112
+ this.#ttls.delete(key);
1113
+ }
1114
+ while (this.size - this.#staticKeys.size > this.maxSize) {
1115
+ let evicted = false;
1116
+ const keysIter = super.keys();
1117
+ let res = keysIter.next();
1118
+ while (!res.done) {
1119
+ const k = res.value;
1120
+ if (!this.#staticKeys.has(k)) {
1121
+ this.delete(k);
1122
+ evicted = true;
1123
+ break;
1124
+ }
1125
+ res = keysIter.next();
1126
+ }
1127
+ if (!evicted)
1128
+ break;
1129
+ }
1130
+ return this;
1131
+ }
1132
+ /**
1133
+ * Deletes a key from the cache, removing its expiration and static key markers.
1134
+ *
1135
+ * @param key - The cache key to delete
1136
+ * @returns True if the key was deleted, false if it did not exist
1137
+ */
1138
+ delete(key) {
1139
+ this.#staticKeys.delete(key);
1140
+ this.#expires.delete(key);
1141
+ this.#ttls.delete(key);
1142
+ return super.delete(key);
1143
+ }
1144
+ /**
1145
+ * Deletes all cache entries whose keys start with the specified prefix.
1146
+ * The prefix comparison is case-insensitive.
1147
+ *
1148
+ * @param prefix - The prefix string to match against cache keys
1149
+ * @returns The number of entries deleted
1150
+ */
1151
+ deletePrefix(prefix) {
1152
+ const normalizedPrefix = String(prefix).trim().toLowerCase();
1153
+ if (isEmpty(normalizedPrefix))
1154
+ return 0;
1155
+ const toDelete = [];
1156
+ for (const key of super.keys()) {
1157
+ if (isString(key) && key.toLowerCase().startsWith(normalizedPrefix))
1158
+ toDelete.push(key);
1159
+ }
1160
+ for (const k of toDelete)
1161
+ this.delete(k);
1162
+ return toDelete.length;
1163
+ }
1164
+ /**
1165
+ * Purges cache entries.
1166
+ * If `count` is specified, evicts up to `count` oldest non-static entries.
1167
+ * If omitted, clears all entries, including static entries.
1168
+ *
1169
+ * @param count - Optional number of entries to evict. If omitted, clears all entries.
1170
+ */
1171
+ clear(count) {
1172
+ if (count === void 0) {
1173
+ this.#staticKeys.clear();
1174
+ this.#expires.clear();
1175
+ this.#ttls.clear();
1176
+ super.clear();
1177
+ return;
1178
+ }
1179
+ let evicted = 0;
1180
+ for (const key of super.keys()) {
1181
+ if (evicted >= count)
1182
+ break;
1183
+ if (!this.#staticKeys.has(key)) {
1184
+ this.delete(key);
1185
+ evicted++;
1186
+ }
1187
+ }
1188
+ }
1189
+ /**
1190
+ * Returns an iterator of cache keys after evicting expired entries.
1191
+ *
1192
+ * @returns Iterator of cache keys
1193
+ */
1194
+ keys() {
1195
+ this.evictExpired();
1196
+ return super.keys();
1197
+ }
1198
+ /**
1199
+ * Returns an iterator of cache values after evicting expired entries.
1200
+ *
1201
+ * @returns Iterator of cache values
1202
+ */
1203
+ values() {
1204
+ this.evictExpired();
1205
+ return super.values();
1206
+ }
1207
+ /**
1208
+ * Returns an iterator of cache entries after evicting expired entries.
1209
+ *
1210
+ * @returns Iterator of [key, value] pairs
1211
+ */
1212
+ entries() {
1213
+ this.evictExpired();
1214
+ return super.entries();
1215
+ }
1216
+ /**
1217
+ * Returns an iterator of cache entries after evicting expired entries, making the cache iterable.
1218
+ *
1219
+ * @returns Iterator of [key, value] pairs
1220
+ */
1221
+ [Symbol.iterator]() {
1222
+ this.evictExpired();
1223
+ return super[Symbol.iterator]();
1224
+ }
1225
+ /**
1226
+ * Returns a plain key-value object of all active non-expired cache entries.
1227
+ * Filters out non-string keys to prevent lossy key conversions or collisions (e.g. numeric 1 vs string "1").
1228
+ */
1229
+ toJSON() {
1230
+ this.evictExpired();
1231
+ const stringEntries = [];
1232
+ for (const [k, v] of super.entries()) {
1233
+ if (typeof k === "string")
1234
+ stringEntries.push([k, v]);
1235
+ }
1236
+ return Object.fromEntries(stringEntries);
1237
+ }
1238
+ /**
1239
+ * Creates a BoundedCache from an iterable of key-value pairs.
1240
+ *
1241
+ * @param entries - Iterable of [key, value] pairs to populate the cache
1242
+ * @param maxSize - Maximum number of entries (default: 1000)
1243
+ * @param ttl - Time-to-live in milliseconds (default: 24 hours)
1244
+ * @returns A new BoundedCache instance
1245
+ */
1246
+ static fromEntries(entries, maxSize = 1e3, ttl = 24 * 60 * 60 * 1e3) {
1247
+ const cache = new BoundedCache2(maxSize, ttl);
1248
+ for (const [k, v] of entries) {
1249
+ cache.set(k, v);
1250
+ }
1251
+ return cache;
1252
+ }
1253
+ };
1254
+ return BoundedCache2 = _classThis;
1255
+ })();
1256
+ }
1257
+ });
1258
+
1259
+ // ../../library/dist/common/runtime/storage.library.js
1260
+ function getStorage(key, dflt) {
1261
+ let store;
1262
+ if (isUndefined(key))
1263
+ return dflt ?? {};
1264
+ switch (context.type) {
1265
+ case CONTEXT.Browser:
1266
+ store = storage.getItem(key);
1267
+ break;
1268
+ case CONTEXT.NodeJS:
1269
+ store = nodeStorage.has(key) ? nodeStorage.get(key) : getEnvVar(key);
1270
+ break;
1271
+ case CONTEXT.Deno:
1272
+ store = context.global.Deno.env.get(key);
1273
+ break;
1274
+ case CONTEXT.GoogleAppsScript:
1275
+ store = context.global.PropertiesService?.getUserProperties().getProperty(key);
1276
+ break;
1277
+ case CONTEXT.WebWorker:
1278
+ case CONTEXT.Unknown:
1279
+ store = void 0;
1280
+ break;
1281
+ default:
1282
+ throw new Error(`Cannot determine Javascript context: ${context.type}`);
1283
+ }
1284
+ return isString(store) ? objectify(store) : dflt;
1285
+ }
1286
+ function setStorage(key, val, options) {
1287
+ const stash = isDefined(val) ? stringify(val) : void 0;
1288
+ const set = isDefined(stash);
1289
+ switch (context.type) {
1290
+ case CONTEXT.Browser:
1291
+ try {
1292
+ set ? storage.setItem(key, stash) : storage.removeItem(key);
1293
+ } catch (e) {
1294
+ console.warn(`[Storage] Failed to ${set ? "setItem" : "removeItem"} for key '${key}':`, e);
1295
+ }
1296
+ break;
1297
+ case CONTEXT.NodeJS:
1298
+ if (!set) {
1299
+ nodeStorage.set(key, void 0, options?.ttl);
1300
+ } else if (options?.static) {
1301
+ nodeStorage.setStatic(key, stash);
1302
+ } else {
1303
+ nodeStorage.set(key, stash, options?.ttl);
1304
+ }
1305
+ break;
1306
+ case CONTEXT.Deno:
1307
+ set ? context.global.Deno.env.set(key, stash) : context.global.Deno.env.delete(key);
1308
+ break;
1309
+ case CONTEXT.GoogleAppsScript:
1310
+ set ? context.global.PropertiesService?.getUserProperties().setProperty(key, stash) : context.global.PropertiesService?.getUserProperties().deleteProperty(key);
1311
+ break;
1312
+ case CONTEXT.WebWorker:
1313
+ case CONTEXT.Unknown:
1314
+ break;
1315
+ default:
1316
+ throw new Error(`Cannot determine Javascript context: ${context.type}`);
1317
+ }
1318
+ }
1319
+ var context, createMemoryStorage, memoryStores, getMemoryStorage, getSafeStorage, storage, nodeStorage, getEnvVar;
1320
+ var init_storage_library = __esm({
1321
+ "../../library/dist/common/runtime/storage.library.js"() {
1322
+ "use strict";
1323
+ init_serialize_library();
1324
+ init_utility_library();
1325
+ init_assertion_library();
1326
+ init_cache_class();
1327
+ context = getContext();
1328
+ createMemoryStorage = (maxSize = 1e3, ttl = Infinity) => {
1329
+ const map = new BoundedCache(maxSize, ttl);
1330
+ return {
1331
+ get length() {
1332
+ return map.size;
1333
+ },
1334
+ clear: () => map.clear(),
1335
+ getItem: (key) => map.get(key) ?? null,
1336
+ key: (index) => Array.from(map.keys())[index] ?? null,
1337
+ removeItem: (key) => {
1338
+ map.delete(key);
1339
+ },
1340
+ setItem: (key, value2) => {
1341
+ map.set(key, String(value2));
1342
+ }
1343
+ };
1344
+ };
1345
+ memoryStores = /* @__PURE__ */ new Map();
1346
+ getMemoryStorage = (name) => {
1347
+ let store = memoryStores.get(name);
1348
+ if (!store) {
1349
+ store = createMemoryStorage();
1350
+ memoryStores.set(name, store);
1351
+ }
1352
+ return store;
1353
+ };
1354
+ getSafeStorage = (name = "localStorage") => {
1355
+ try {
1356
+ const target = globalThis?.[name];
1357
+ if (target && typeof target.getItem === "function" && typeof target.setItem === "function" && typeof target.removeItem === "function" && typeof target.clear === "function" && typeof target.key === "function" && typeof target.length === "number")
1358
+ return target;
1359
+ } catch {
1360
+ }
1361
+ return getMemoryStorage(name);
1362
+ };
1363
+ storage = context.type === CONTEXT.Browser ? getSafeStorage() : createMemoryStorage();
1364
+ nodeStorage = new BoundedCache(1e3, Infinity);
1365
+ getEnvVar = (key) => {
1366
+ try {
1367
+ const proc = Reflect.get(context.global, "process");
1368
+ if (!proc || typeof proc !== "object")
1369
+ return void 0;
1370
+ const env = Reflect.get(proc, "env");
1371
+ if (!env || typeof env !== "object")
1372
+ return void 0;
1373
+ return Reflect.get(env, key);
1374
+ } catch {
1375
+ return void 0;
1376
+ }
1377
+ };
1378
+ }
1379
+ });
1380
+
1381
+ // ../../library/dist/common/primitives/object.library.js
1382
+ function looseIndex(arg) {
1383
+ if (isDefined(arg))
1384
+ return isFunction(arg) ? arg() : arg;
1385
+ return (obj) => isFunction(obj) ? obj() : obj;
1386
+ }
1387
+ var asObject;
1388
+ var init_object_library = __esm({
1389
+ "../../library/dist/common/primitives/object.library.js"() {
1390
+ "use strict";
1391
+ init_primitive_library();
1392
+ init_assertion_library();
1393
+ init_type_library();
1394
+ asObject = (obj) => {
1395
+ if (isNullish(obj) || !isObject(obj))
1396
+ return obj;
1397
+ const temp = isArray(obj) ? [] : {};
1398
+ ownKeys(obj).forEach((key) => {
1399
+ if (!isSafeKey(key))
1400
+ return;
1401
+ temp[key] = asObject(obj[key]);
1402
+ });
1403
+ return temp;
1404
+ };
1405
+ looseIndex.stringSymbol = looseIndex();
1406
+ looseIndex.symbolRegExp = looseIndex();
1407
+ looseIndex.symbolString = looseIndex();
1408
+ looseIndex.stringString = looseIndex();
857
1409
  }
858
1410
  });
859
1411
 
@@ -993,113 +1545,6 @@ var init_international_library = __esm({
993
1545
  }
994
1546
  });
995
1547
 
996
- // ../../../node_modules/tslib/tslib.es6.mjs
997
- function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
998
- function accept(f) {
999
- if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected");
1000
- return f;
1001
- }
1002
- var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
1003
- var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
1004
- var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
1005
- var _, done = false;
1006
- for (var i = decorators.length - 1; i >= 0; i--) {
1007
- var context3 = {};
1008
- for (var p in contextIn) context3[p] = p === "access" ? {} : contextIn[p];
1009
- for (var p in contextIn.access) context3.access[p] = contextIn.access[p];
1010
- context3.addInitializer = function(f) {
1011
- if (done) throw new TypeError("Cannot add initializers after decoration has completed");
1012
- extraInitializers.push(accept(f || null));
1013
- };
1014
- var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context3);
1015
- if (kind === "accessor") {
1016
- if (result === void 0) continue;
1017
- if (result === null || typeof result !== "object") throw new TypeError("Object expected");
1018
- if (_ = accept(result.get)) descriptor.get = _;
1019
- if (_ = accept(result.set)) descriptor.set = _;
1020
- if (_ = accept(result.init)) initializers.unshift(_);
1021
- } else if (_ = accept(result)) {
1022
- if (kind === "field") initializers.unshift(_);
1023
- else descriptor[key] = _;
1024
- }
1025
- }
1026
- if (target) Object.defineProperty(target, contextIn.name, descriptor);
1027
- done = true;
1028
- }
1029
- function __runInitializers(thisArg, initializers, value2) {
1030
- var useValue = arguments.length > 2;
1031
- for (var i = 0; i < initializers.length; i++) {
1032
- value2 = useValue ? initializers[i].call(thisArg, value2) : initializers[i].call(thisArg);
1033
- }
1034
- return useValue ? value2 : void 0;
1035
- }
1036
- var init_tslib_es6 = __esm({
1037
- "../../../node_modules/tslib/tslib.es6.mjs"() {
1038
- "use strict";
1039
- }
1040
- });
1041
-
1042
- // ../../library/dist/common/runtime/decorator.library.js
1043
- function getClassName(value2, contextName) {
1044
- return getSafeTag(value2) ?? (isUndefined(contextName) ? value2.name || void 0 : String(contextName));
1045
- }
1046
- function Serializable(value2, { kind, name, addInitializer }) {
1047
- const finalName = getClassName(value2, name);
1048
- if (finalName)
1049
- registerType(value2, finalName);
1050
- switch (kind) {
1051
- case "class":
1052
- if (finalName)
1053
- addInitializer(() => registerSerializable(finalName, value2));
1054
- return value2;
1055
- default:
1056
- throw new Error(`@Serializable decorating unknown 'kind': ${kind} (${name})`);
1057
- }
1058
- }
1059
- function StringTag(tagOrValue, context3) {
1060
- const applyTag = (value2, customTag, contextName) => {
1061
- const proto = value2.prototype;
1062
- const tagName = customTag ?? getClassName(value2, contextName);
1063
- if (tagName) {
1064
- if (proto && !Object.hasOwn(proto, Symbol.toStringTag)) {
1065
- Object.defineProperty(proto, Symbol.toStringTag, {
1066
- value: tagName,
1067
- configurable: true,
1068
- writable: false,
1069
- enumerable: false
1070
- });
1071
- }
1072
- if (!value2.name || value2.name !== tagName) {
1073
- try {
1074
- Object.defineProperty(value2, "name", {
1075
- value: tagName,
1076
- configurable: true,
1077
- writable: false,
1078
- enumerable: false
1079
- });
1080
- } catch {
1081
- }
1082
- }
1083
- }
1084
- return value2;
1085
- };
1086
- if (typeof tagOrValue === "function" && context3?.kind === "class")
1087
- return applyTag(tagOrValue, void 0, context3.name);
1088
- return (value2, ctx) => {
1089
- return applyTag(value2, isString(tagOrValue) ? tagOrValue : void 0, ctx?.name);
1090
- };
1091
- }
1092
- var init_decorator_library = __esm({
1093
- "../../library/dist/common/runtime/decorator.library.js"() {
1094
- "use strict";
1095
- init_symbol_library();
1096
- init_proxy_library();
1097
- init_assertion_library();
1098
- init_serialize_library();
1099
- init_type_library();
1100
- }
1101
- });
1102
-
1103
1548
  // ../../library/dist/common/runtime/enumerate.library.js
1104
1549
  function value(val) {
1105
1550
  return { enumerable: false, configurable: false, writable: false, value: val };
@@ -1329,54 +1774,6 @@ var init_logger_class = __esm({
1329
1774
  }
1330
1775
  });
1331
1776
 
1332
- // ../../library/dist/common/runtime/storage.library.js
1333
- var context, createMemoryStorage, memoryStores, getMemoryStorage, getSafeStorage, storage;
1334
- var init_storage_library = __esm({
1335
- "../../library/dist/common/runtime/storage.library.js"() {
1336
- "use strict";
1337
- init_serialize_library();
1338
- init_utility_library();
1339
- init_assertion_library();
1340
- context = getContext();
1341
- createMemoryStorage = () => {
1342
- const map = /* @__PURE__ */ new Map();
1343
- return {
1344
- get length() {
1345
- return map.size;
1346
- },
1347
- clear: () => map.clear(),
1348
- getItem: (key) => map.get(key) ?? null,
1349
- key: (index) => Array.from(map.keys())[index] ?? null,
1350
- removeItem: (key) => {
1351
- map.delete(key);
1352
- },
1353
- setItem: (key, value2) => {
1354
- map.set(key, String(value2));
1355
- }
1356
- };
1357
- };
1358
- memoryStores = /* @__PURE__ */ new Map();
1359
- getMemoryStorage = (name) => {
1360
- let store = memoryStores.get(name);
1361
- if (!store) {
1362
- store = createMemoryStorage();
1363
- memoryStores.set(name, store);
1364
- }
1365
- return store;
1366
- };
1367
- getSafeStorage = (name = "localStorage") => {
1368
- try {
1369
- const target = globalThis?.[name];
1370
- if (target && typeof target.getItem === "function" && typeof target.setItem === "function" && typeof target.removeItem === "function" && typeof target.clear === "function" && typeof target.key === "function" && typeof target.length === "number")
1371
- return target;
1372
- } catch {
1373
- }
1374
- return getMemoryStorage(name);
1375
- };
1376
- storage = context.type === CONTEXT.Browser ? getSafeStorage() : createMemoryStorage();
1377
- }
1378
- });
1379
-
1380
1777
  // ../../library/dist/browser/webstore.class.js
1381
1778
  var webstore_class_exports = {};
1382
1779
  __export(webstore_class_exports, {
@@ -1622,7 +2019,7 @@ var init_mapper_library = __esm({
1622
2019
  defaults = { catch: true, debug: 0 };
1623
2020
  context2 = getContext();
1624
2021
  mapStore = {};
1625
- MAP_KEY = "_map_";
2022
+ MAP_KEY = "_magma_browser_map_";
1626
2023
  log = new Logger("[Mapper]");
1627
2024
  storePromise = null;
1628
2025
  getStore = () => {
@@ -1685,7 +2082,7 @@ var init_mapper_library = __esm({
1685
2082
  const fulfil = opts.catch ? resolve : reject;
1686
2083
  geoCoords(coords).then((loc) => {
1687
2084
  switch (true) {
1688
- case !(typeof window !== "undefined" && "google" in window && "maps" in window["google"]):
2085
+ case (context2.type !== CONTEXT.Browser || !window["google"]?.maps):
1689
2086
  throw new Error("Google Maps API not configured");
1690
2087
  case isNullish(loc):
1691
2088
  throw new Error("Cannot determine Coordinates");
@@ -1929,7 +2326,7 @@ __export(mapper_library_exports2, {
1929
2326
  serverGeoLocation: () => serverGeoLocation,
1930
2327
  serverMapHemisphere: () => serverMapHemisphere
1931
2328
  });
1932
- var log2, defaults2, requestModulePromise, getRequestModule, serverGeoLocation, serverGeoCoords, serverMapHemisphere;
2329
+ var log2, DEFAULT_GEO_ENDPOINT, defaults2, requestModulePromise, getRequestModule, serverGeoLocation, serverGeoCoords, serverMapHemisphere;
1933
2330
  var init_mapper_library2 = __esm({
1934
2331
  "../../library/dist/server/mapper.library.js"() {
1935
2332
  "use strict";
@@ -1937,8 +2334,9 @@ var init_mapper_library2 = __esm({
1937
2334
  init_international_library();
1938
2335
  init_logger_class();
1939
2336
  log2 = new Logger("[ServerMapper]");
2337
+ DEFAULT_GEO_ENDPOINT = "https://ipwho.is";
1940
2338
  defaults2 = {
1941
- endpoint: "https://ipwho.is/",
2339
+ endpoint: `${DEFAULT_GEO_ENDPOINT}/`,
1942
2340
  timeout: 3e3,
1943
2341
  catch: true,
1944
2342
  debug: 0
@@ -1953,7 +2351,18 @@ var init_mapper_library2 = __esm({
1953
2351
  const options = { ...defaults2, ...opts };
1954
2352
  const fulfil = options.catch !== false;
1955
2353
  try {
1956
- const endpoint = options.endpoint || defaults2.endpoint;
2354
+ let endpoint = options.endpoint || defaults2.endpoint;
2355
+ if (isString(options.ip)) {
2356
+ const cleanIp = encodeURIComponent(options.ip.trim());
2357
+ const normalized = endpoint.endsWith("/") ? endpoint.slice(0, -1) : endpoint;
2358
+ if (normalized === DEFAULT_GEO_ENDPOINT) {
2359
+ endpoint = `${DEFAULT_GEO_ENDPOINT}/${cleanIp}`;
2360
+ } else if (endpoint.includes("{ip}")) {
2361
+ endpoint = endpoint.replace("{ip}", cleanIp);
2362
+ } else if (cleanIp !== "") {
2363
+ throw new Error(`Custom endpoint must include an '{ip}' placeholder to resolve a specific IP: ${endpoint}`);
2364
+ }
2365
+ }
1957
2366
  const timeout = options.timeout ?? defaults2.timeout;
1958
2367
  const { fetchRequest: fetchRequest2 } = await getRequestModule();
1959
2368
  const data = await fetchRequest2(endpoint, {}, { ...isNumber(timeout) ? { timeout } : {}, maxBytes: 64 * 1024 });
@@ -2019,124 +2428,440 @@ __export(sdk_exports, {
2019
2428
  __reExport(sdk_exports, sdk_star);
2020
2429
  import * as sdk_star from "@magmacomputing/tempo/plugin/sdk";
2021
2430
  import { definePlugin as originalPlugin, defineTerm as originalTerm } from "@magmacomputing/tempo/plugin/sdk";
2022
- var definePlugin = (config) => originalPlugin({ ...config, version: "0.1.0" });
2023
- var defineTerm = (config) => originalTerm({ ...config, version: "0.1.0" });
2431
+ var definePlugin = (config) => originalPlugin({ ...config, version: "1.0.0" });
2432
+ var defineTerm = (config) => originalTerm({ ...config, version: "1.0.0" });
2024
2433
 
2025
2434
  // ../../library/dist/common/runtime/mapper.library.js
2026
2435
  init_utility_library();
2027
2436
  init_assertion_library();
2437
+ init_storage_library();
2438
+
2439
+ // ../../library/dist/common/runtime/evaluation.library.js
2440
+ init_assertion_library();
2441
+ function evaluate(...values) {
2442
+ for (const val of values) {
2443
+ const resolved = isFunction(val) ? val() : val;
2444
+ if (resolved !== void 0)
2445
+ return resolved;
2446
+ }
2447
+ return void 0;
2448
+ }
2449
+
2450
+ // ../../library/dist/common/runtime/mapper.library.js
2451
+ var MAP_KEY2 = "_magma_geo_";
2452
+ var DEFAULT_GEO_TTL = 24 * 60 * 60 * 1e3;
2453
+ var GEO_PROPERTIES = [
2454
+ "latitude",
2455
+ "lat",
2456
+ "longitude",
2457
+ "lng",
2458
+ "lon",
2459
+ "long",
2460
+ "elevation",
2461
+ "sphere",
2462
+ "country",
2463
+ "city",
2464
+ "timezone",
2465
+ "tz"
2466
+ ];
2467
+ var normalizeLat = (lat) => isNumber(lat) && lat >= -90 && lat <= 90 ? Math.round(lat * 1e3) / 1e3 : void 0;
2468
+ var normalizeLng = (lng) => isNumber(lng) && lng >= -180 && lng <= 180 ? Math.round(lng * 1e3) / 1e3 : void 0;
2469
+ var normalizeCoords = (lat, lng) => {
2470
+ const nLat = normalizeLat(lat);
2471
+ const nLng = normalizeLng(lng);
2472
+ return nLat !== void 0 && nLng !== void 0 ? { lat: nLat, lng: nLng } : void 0;
2473
+ };
2474
+ var resolveSphere = (sphere, lat) => {
2475
+ if (sphere === "north" || sphere === "south" || sphere === "equator")
2476
+ return sphere;
2477
+ if (isNumber(lat))
2478
+ return lat > 1e-3 ? "north" : lat < -1e-3 ? "south" : "equator";
2479
+ return void 0;
2480
+ };
2028
2481
  var coerceGeo = (input) => {
2029
- if (isNullish(input) || typeof input !== "object")
2482
+ if (isString(input) && input.includes(",")) {
2483
+ const segments = input.split(",").map((s) => s.trim());
2484
+ const parts = segments.map((s) => s === "" ? NaN : Number(s));
2485
+ if (parts.length >= 2 && !isNaN(parts[0]) && !isNaN(parts[1])) {
2486
+ const coords = normalizeCoords(parts[0], parts[1]);
2487
+ if (coords) {
2488
+ const result2 = { latitude: coords.lat, longitude: coords.lng };
2489
+ const sphere2 = resolveSphere(void 0, coords.lat);
2490
+ if (sphere2)
2491
+ result2.sphere = sphere2;
2492
+ return result2;
2493
+ }
2494
+ }
2495
+ return void 0;
2496
+ }
2497
+ if (isPrimitive(input))
2498
+ return void 0;
2499
+ if (Array.isArray(input) && input.length >= 2) {
2500
+ const coords = normalizeCoords(input[0], input[1]);
2501
+ if (coords) {
2502
+ const result2 = { latitude: coords.lat, longitude: coords.lng };
2503
+ const sphere2 = resolveSphere(void 0, coords.lat);
2504
+ if (sphere2)
2505
+ result2.sphere = sphere2;
2506
+ return result2;
2507
+ }
2030
2508
  return void 0;
2031
- const geoObj = input.geo ?? input;
2032
- const cfgGeo = input.config?.geo ?? input.config;
2033
- const lat = geoObj?.latitude ?? geoObj?.lat ?? input.latitude ?? input.lat ?? cfgGeo?.latitude ?? cfgGeo?.lat;
2034
- const lng = geoObj?.longitude ?? geoObj?.lng ?? geoObj?.lon ?? geoObj?.long ?? input.longitude ?? input.lng ?? input.lon ?? input.long ?? cfgGeo?.longitude ?? cfgGeo?.lng ?? cfgGeo?.lon ?? cfgGeo?.long;
2035
- const elevation = geoObj?.elevation ?? input.elevation ?? cfgGeo?.elevation;
2036
- const sphere = geoObj?.sphere ?? input.sphere ?? cfgGeo?.sphere;
2037
- const country = geoObj?.country ?? input.country ?? cfgGeo?.country;
2038
- const city = geoObj?.city ?? input.city ?? cfgGeo?.city;
2509
+ }
2510
+ const geo = input.geo ?? input;
2511
+ const cfg = input.config?.geo ?? input.config;
2512
+ const lat = evaluate(geo?.latitude, geo?.lat, input.latitude, input.lat, cfg?.latitude, cfg?.lat);
2513
+ const lng = 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);
2514
+ const elevation = evaluate(geo?.elevation, input.elevation, cfg?.elevation);
2515
+ const sphere = evaluate(geo?.sphere, input.sphere, cfg?.sphere);
2516
+ const country = evaluate(geo?.country, input.country, cfg?.country);
2517
+ const city = evaluate(geo?.city, input.city, cfg?.city);
2518
+ const timezone = evaluate(geo?.timezone, geo?.tz, input.timezone, input.tz, cfg?.timezone, cfg?.tz);
2039
2519
  const result = {};
2040
- if (isNumber(lat))
2041
- result.latitude = lat;
2042
- if (isNumber(lng))
2043
- result.longitude = lng;
2520
+ const nLat = normalizeLat(lat);
2521
+ const nLng = normalizeLng(lng);
2522
+ if (nLat !== void 0)
2523
+ result.latitude = nLat;
2524
+ if (nLng !== void 0)
2525
+ result.longitude = nLng;
2044
2526
  if (isNumber(elevation))
2045
- result.elevation = elevation;
2046
- if (sphere === "north" || sphere === "south")
2047
- result.sphere = sphere;
2527
+ result.elevation = Math.round(elevation * 1e3) / 1e3;
2528
+ const resolvedSphere = resolveSphere(sphere, result.latitude);
2529
+ if (resolvedSphere)
2530
+ result.sphere = resolvedSphere;
2048
2531
  if (isString(country))
2049
2532
  result.country = country;
2050
2533
  if (isString(city))
2051
2534
  result.city = city;
2052
- if (geoObj && typeof geoObj === "object") {
2053
- for (const key of Object.keys(geoObj)) {
2054
- if (isSafeKey(key) && !["latitude", "lat", "longitude", "lng", "lon", "long", "elevation", "sphere", "country", "city"].includes(key))
2055
- result[key] = geoObj[key];
2535
+ if (isString(timezone))
2536
+ result.timezone = timezone;
2537
+ const explicitGeo = isReference(input.geo) ? input.geo : isReference(input.config?.geo) ? input.config.geo : void 0;
2538
+ if (isReference(explicitGeo)) {
2539
+ for (const key of Object.keys(explicitGeo)) {
2540
+ if (isSafeKey(key) && !GEO_PROPERTIES.includes(key))
2541
+ result[key] = explicitGeo[key];
2056
2542
  }
2057
2543
  }
2058
2544
  return Object.keys(result).length > 0 ? result : void 0;
2059
2545
  };
2060
- var getStashedGeo = () => {
2061
- const { type } = getContext();
2062
- if (type === CONTEXT.Browser || type === CONTEXT.WebWorker) {
2063
- try {
2064
- if (typeof localStorage !== "undefined") {
2065
- const raw = localStorage.getItem("_map_");
2066
- if (raw) {
2067
- const parsed = JSON.parse(raw);
2068
- const coords = parsed?.geolocation?.coords;
2069
- if (isNumber(coords?.latitude) && isNumber(coords?.longitude)) {
2070
- return { latitude: coords.latitude, longitude: coords.longitude };
2071
- }
2072
- }
2546
+ var resolveCacheKey = (keyOrOpts) => {
2547
+ if (isString(keyOrOpts) && !isEmpty(keyOrOpts)) {
2548
+ const trimmed = keyOrOpts.trim();
2549
+ return trimmed.startsWith(MAP_KEY2) ? trimmed : `${MAP_KEY2}:${trimmed}`;
2550
+ }
2551
+ if (keyOrOpts && isObject(keyOrOpts)) {
2552
+ const k = keyOrOpts.key ?? keyOrOpts.ip ?? keyOrOpts.query;
2553
+ if (isString(k) && !isEmpty(k))
2554
+ return `${MAP_KEY2}:${k.trim()}`;
2555
+ }
2556
+ return MAP_KEY2;
2557
+ };
2558
+ var getStashedGeo = (keyOrOpts) => {
2559
+ const cacheKey = resolveCacheKey(keyOrOpts);
2560
+ try {
2561
+ const raw = getStorage(cacheKey) ?? (typeof localStorage !== "undefined" ? localStorage.getItem(cacheKey) : void 0);
2562
+ if (!raw)
2563
+ return void 0;
2564
+ const parsed = isString(raw) && (raw.startsWith("{") || raw.startsWith("[")) ? JSON.parse(raw) : raw;
2565
+ if (isObject(parsed)) {
2566
+ if (isNumber(parsed._expires) && Date.now() > parsed._expires) {
2567
+ clearStashedGeo(keyOrOpts);
2568
+ return void 0;
2569
+ }
2570
+ }
2571
+ if (isString(parsed) && parsed.includes(",")) {
2572
+ const parts = parsed.split(",").map((s) => parseFloat(s.trim()));
2573
+ const coords = normalizeCoords(parts[0], parts[1]);
2574
+ if (coords) {
2575
+ return {
2576
+ latitude: coords.lat,
2577
+ longitude: coords.lng,
2578
+ sphere: resolveSphere(void 0, coords.lat)
2579
+ };
2580
+ }
2581
+ }
2582
+ if (isObject(parsed)) {
2583
+ const rawCoords = parsed.geolocation?.coords ?? parsed.coords ?? parsed;
2584
+ const lat = rawCoords?.latitude ?? rawCoords?.lat;
2585
+ const lng = rawCoords?.longitude ?? rawCoords?.lng ?? rawCoords?.lon ?? rawCoords?.long;
2586
+ const coords = normalizeCoords(lat, lng);
2587
+ if (coords) {
2588
+ const result = { latitude: coords.lat, longitude: coords.lng };
2589
+ const elevation = parsed.elevation ?? rawCoords.elevation;
2590
+ if (isNumber(elevation))
2591
+ result.elevation = Math.round(elevation * 1e3) / 1e3;
2592
+ result.sphere = resolveSphere(parsed.sphere, coords.lat);
2593
+ if (isString(parsed.country))
2594
+ result.country = parsed.country;
2595
+ if (isString(parsed.city))
2596
+ result.city = parsed.city;
2597
+ if (isString(parsed.timezone))
2598
+ result.timezone = parsed.timezone;
2599
+ return result;
2073
2600
  }
2074
- } catch {
2075
2601
  }
2602
+ } catch {
2076
2603
  }
2077
2604
  return void 0;
2078
2605
  };
2606
+ var stashGeo = (coords, ttl = DEFAULT_GEO_TTL, keyOrOpts) => {
2607
+ const cacheKey = resolveCacheKey(keyOrOpts);
2608
+ const payload = isNumber(ttl) && ttl > 0 ? { ...coords, _expires: Date.now() + ttl } : coords;
2609
+ setStorage(cacheKey, payload, { ttl });
2610
+ };
2611
+ var clearStashedGeo = (keyOrOpts) => {
2612
+ const cacheKey = resolveCacheKey(keyOrOpts);
2613
+ setStorage(cacheKey, void 0);
2614
+ };
2079
2615
  var geoLookup = async (opts = {}) => {
2616
+ const useCache = opts.refresh !== true;
2617
+ if (useCache) {
2618
+ const stashed = getStashedGeo(opts);
2619
+ if (stashed && isNumber(stashed.latitude) && isNumber(stashed.longitude)) {
2620
+ const { latitude, longitude, ...rest } = stashed;
2621
+ return {
2622
+ ...rest,
2623
+ status: "cached",
2624
+ lat: latitude,
2625
+ lng: longitude,
2626
+ latitude,
2627
+ longitude
2628
+ };
2629
+ }
2630
+ }
2080
2631
  const { type } = getContext();
2632
+ let res;
2081
2633
  switch (type) {
2082
2634
  case CONTEXT.Browser: {
2083
2635
  const { geoLocation: geoLocation2 } = await Promise.resolve().then(() => (init_mapper_library(), mapper_library_exports));
2084
- const res = await geoLocation2(opts);
2085
- if (res.error)
2086
- return { error: res.error };
2087
- const lat = res.coords?.latitude;
2088
- const lng = res.coords?.longitude;
2089
- return { lat, lng, latitude: lat, longitude: lng, ...res };
2090
- }
2091
- case CONTEXT.WebWorker: {
2092
- const stashed = getStashedGeo();
2093
- if (stashed && isNumber(stashed.latitude) && isNumber(stashed.longitude))
2094
- return { lat: stashed.latitude, lng: stashed.longitude, latitude: stashed.latitude, longitude: stashed.longitude };
2095
- const { serverGeoLocation: serverGeoLocation2 } = await Promise.resolve().then(() => (init_mapper_library2(), mapper_library_exports2));
2096
- return serverGeoLocation2(opts);
2636
+ const browserRes = await geoLocation2(opts);
2637
+ if (browserRes.error)
2638
+ return { error: browserRes.error };
2639
+ const lat = browserRes.coords?.latitude;
2640
+ const lng = browserRes.coords?.longitude;
2641
+ res = { ...browserRes, lat, lng, latitude: lat, longitude: lng };
2642
+ break;
2097
2643
  }
2644
+ case CONTEXT.WebWorker:
2098
2645
  case CONTEXT.NodeJS:
2099
2646
  case CONTEXT.Deno:
2100
2647
  default: {
2101
2648
  const { serverGeoLocation: serverGeoLocation2 } = await Promise.resolve().then(() => (init_mapper_library2(), mapper_library_exports2));
2102
- return serverGeoLocation2(opts);
2649
+ res = await serverGeoLocation2(opts);
2650
+ break;
2651
+ }
2652
+ }
2653
+ const rawLat = res.latitude ?? res.lat;
2654
+ const rawLng = res.longitude ?? res.lng;
2655
+ const coords = normalizeCoords(rawLat, rawLng);
2656
+ if (isNullish(res.error) && coords) {
2657
+ const sphere = resolveSphere(res.sphere, coords.lat);
2658
+ res.lat = coords.lat;
2659
+ res.lng = coords.lng;
2660
+ res.latitude = coords.lat;
2661
+ res.longitude = coords.lng;
2662
+ res.sphere = sphere;
2663
+ const stashPayload = {
2664
+ latitude: coords.lat,
2665
+ longitude: coords.lng,
2666
+ sphere,
2667
+ ...isString(res.city) ? { city: res.city } : {},
2668
+ ...isString(res.country) ? { country: res.country } : {},
2669
+ ...isNumber(res.elevation) ? { elevation: Math.round(res.elevation * 1e3) / 1e3 } : {},
2670
+ ...isString(res.timezone) ? { timezone: res.timezone } : {}
2671
+ };
2672
+ try {
2673
+ const ttl = isNumber(opts.ttl) ? opts.ttl : DEFAULT_GEO_TTL;
2674
+ stashGeo(stashPayload, ttl, opts);
2675
+ } catch {
2103
2676
  }
2104
2677
  }
2678
+ return res;
2105
2679
  };
2106
2680
  var resolveGeoCoordinates = async (input, opts = {}) => {
2107
2681
  const coerced = coerceGeo(input);
2108
2682
  if (coerced && isNumber(coerced.latitude) && isNumber(coerced.longitude))
2109
- return { lat: coerced.latitude, lng: coerced.longitude };
2110
- const stashed = getStashedGeo();
2683
+ return {
2684
+ ...coerced,
2685
+ lat: coerced.latitude,
2686
+ lng: coerced.longitude
2687
+ };
2688
+ const stashed = opts.refresh === true ? void 0 : getStashedGeo(opts);
2111
2689
  if (stashed && isNumber(stashed.latitude) && isNumber(stashed.longitude))
2112
- return { lat: stashed.latitude, lng: stashed.longitude };
2690
+ return {
2691
+ ...stashed,
2692
+ lat: stashed.latitude,
2693
+ lng: stashed.longitude
2694
+ };
2113
2695
  const lookup = await geoLookup(opts);
2114
- if (isNullish(lookup.error) && isNumber(lookup.lat) && isNumber(lookup.lng))
2115
- return { lat: lookup.lat, lng: lookup.lng };
2696
+ const coords = normalizeCoords(lookup.lat, lookup.lng);
2697
+ if (isNullish(lookup.error) && coords) {
2698
+ const sphere = resolveSphere(lookup.sphere, coords.lat);
2699
+ return {
2700
+ ...lookup,
2701
+ lat: coords.lat,
2702
+ lng: coords.lng,
2703
+ latitude: coords.lat,
2704
+ longitude: coords.lng,
2705
+ sphere
2706
+ };
2707
+ }
2116
2708
  return null;
2117
2709
  };
2710
+ function haversineDistance(from, to, unit = "km") {
2711
+ const c1 = coerceGeo(from);
2712
+ const c2 = coerceGeo(to);
2713
+ if (!c1 || !c2 || !isNumber(c1.latitude) || !isNumber(c1.longitude) || !isNumber(c2.latitude) || !isNumber(c2.longitude)) {
2714
+ return NaN;
2715
+ }
2716
+ const toRad = Math.PI / 180;
2717
+ const lat1 = c1.latitude * toRad;
2718
+ const lng1 = c1.longitude * toRad;
2719
+ const lat2 = c2.latitude * toRad;
2720
+ const lng2 = c2.longitude * toRad;
2721
+ const dLat = lat2 - lat1;
2722
+ const dLng = lng2 - lng1;
2723
+ const a = Math.sin(dLat / 2) ** 2 + Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) ** 2;
2724
+ const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
2725
+ let radius;
2726
+ if (unit === "miles") {
2727
+ radius = 3958.7613;
2728
+ } else if (unit === "m") {
2729
+ radius = 63710088e-1;
2730
+ } else {
2731
+ radius = 6371.0088;
2732
+ }
2733
+ const dist = radius * c;
2734
+ return unit === "m" ? Math.round(dist) : Math.round(dist * 1e3) / 1e3;
2735
+ }
2736
+ var resolveCivilTimezoneOffset = (tz, epochMs) => {
2737
+ try {
2738
+ if (typeof Temporal !== "undefined" && typeof Temporal.Instant?.fromEpochMilliseconds === "function") {
2739
+ const zdt = Temporal.Instant.fromEpochMilliseconds(epochMs).toZonedDateTimeISO(tz);
2740
+ return zdt.offsetNanoseconds / 6e10;
2741
+ }
2742
+ const parts = new Intl.DateTimeFormat("en-US", {
2743
+ timeZone: tz,
2744
+ timeZoneName: "longOffset",
2745
+ year: "numeric"
2746
+ }).formatToParts(new Date(epochMs));
2747
+ const tzPart = parts.find((p) => p.type === "timeZoneName")?.value;
2748
+ if (tzPart) {
2749
+ if (tzPart === "GMT" || tzPart === "UTC")
2750
+ return 0;
2751
+ const match = tzPart.match(/GMT([+-])(\d{2}):(\d{2})/);
2752
+ if (match) {
2753
+ const sign = match[1] === "-" ? -1 : 1;
2754
+ return sign * (parseInt(match[2], 10) * 60 + parseInt(match[3], 10));
2755
+ }
2756
+ }
2757
+ } catch {
2758
+ }
2759
+ return void 0;
2760
+ };
2761
+ function solarOffset(coords, options) {
2762
+ const geo = coerceGeo(coords);
2763
+ if (!geo || !isNumber(geo.latitude) || !isNumber(geo.longitude) || isNaN(geo.latitude) || isNaN(geo.longitude)) {
2764
+ return NaN;
2765
+ }
2766
+ const lng = geo.longitude;
2767
+ const tz = options?.timeZone ?? (isReference(coords) ? coords.timezone ?? coords.tz : void 0) ?? geo.timezone;
2768
+ const dateVal = options?.date ?? (isReference(coords) && isNumber(coords.epoch?.ms) ? coords.epoch.ms : Date.now());
2769
+ const epochMs = typeof dateVal === "number" ? dateVal : isString(dateVal) ? Date.parse(dateVal) : isDate(dateVal) ? dateVal.getTime() : isReference(dateVal) && isNumber(dateVal?.epoch?.ms) ? dateVal.epoch.ms : Date.now();
2770
+ if (!Number.isFinite(epochMs))
2771
+ return NaN;
2772
+ const offsetMinutes = isText(tz) ? resolveCivilTimezoneOffset(tz, epochMs) : void 0;
2773
+ const refMeridian = offsetMinutes !== void 0 ? offsetMinutes / 60 * 15 : Math.round(lng / 15) * 15;
2774
+ const deltaLng = lng - refMeridian;
2775
+ let offsetMin = deltaLng * 4;
2776
+ if (options?.apparent) {
2777
+ const d = new Date(epochMs);
2778
+ const startOfYear = Date.UTC(d.getUTCFullYear(), 0, 1);
2779
+ const dayOfYear = Math.floor((epochMs - startOfYear) / 864e5) + 1;
2780
+ const gamma = 2 * Math.PI / 365 * (dayOfYear - 1);
2781
+ 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));
2782
+ offsetMin += eqTime;
2783
+ }
2784
+ const unit = options?.unit ?? "minutes";
2785
+ let res;
2786
+ if (unit === "seconds") {
2787
+ res = offsetMin * 60;
2788
+ } else if (unit === "hours") {
2789
+ res = offsetMin / 60;
2790
+ } else {
2791
+ res = offsetMin;
2792
+ }
2793
+ const precision = options?.precision ?? 2;
2794
+ const factor = Math.pow(10, precision);
2795
+ return Math.round(res * factor) / factor;
2796
+ }
2118
2797
 
2119
2798
  // src/index.ts
2120
2799
  init_mapper_library2();
2121
2800
  init_mapper_library();
2801
+ init_assertion_library();
2122
2802
  var GeoPlugin = definePlugin({
2123
2803
  name: "geo",
2124
2804
  install(TempoClass) {
2125
- TempoClass.geoLookup = geoLookup;
2126
- TempoClass.resolveGeoCoordinates = resolveGeoCoordinates;
2127
- TempoClass.serverGeoLocation = serverGeoLocation;
2128
- TempoClass.geoLocation = geoLocation;
2805
+ const geoNamespace = {
2806
+ lookup: geoLookup,
2807
+ resolve: resolveGeoCoordinates,
2808
+ coerce: coerceGeo,
2809
+ distance: haversineDistance,
2810
+ solarOffset,
2811
+ stash: stashGeo,
2812
+ clear: clearStashedGeo,
2813
+ get: getStashedGeo,
2814
+ server: serverGeoLocation,
2815
+ browser: geoLocation,
2816
+ get current() {
2817
+ return getStashedGeo() ?? TempoClass.config?.geo;
2818
+ }
2819
+ };
2820
+ Object.defineProperty(TempoClass, "geo", {
2821
+ value: (0, sdk_exports.deepFreeze)(geoNamespace),
2822
+ writable: false,
2823
+ configurable: false,
2824
+ enumerable: false
2825
+ });
2129
2826
  TempoClass.prototype.geoLocate = async function(opts) {
2827
+ const setTimezone = opts?.setTimezone !== false;
2130
2828
  const coords = await resolveGeoCoordinates(this, opts);
2131
2829
  if (coords) {
2132
2830
  const existingGeo = typeof this.config.geo === "object" && this.config.geo !== null ? this.config.geo : {};
2133
- return new TempoClass(this, {
2134
- ...this.config,
2135
- geo: {
2136
- ...existingGeo,
2137
- latitude: coords.lat,
2138
- longitude: coords.lng
2831
+ const customKeys = {};
2832
+ for (const key of Object.keys(existingGeo)) {
2833
+ if (isSafeKey(key) && !GEO_PROPERTIES.includes(key))
2834
+ customKeys[key] = existingGeo[key];
2835
+ }
2836
+ const callSiteGeo = coerceGeo(opts) ?? {};
2837
+ if (opts && typeof opts === "object") {
2838
+ for (const key of Object.keys(opts)) {
2839
+ if (isSafeKey(key) && !["setTimezone", "refresh", "ttl", "endpoint", "timeout", "catch", "debug", "geo"].includes(key)) {
2840
+ if (!GEO_PROPERTIES.includes(key))
2841
+ customKeys[key] = opts[key];
2842
+ }
2139
2843
  }
2844
+ }
2845
+ const preservedElevation = isNumber(coords?.elevation) ? coords.elevation : isNumber(existingGeo.elevation) ? existingGeo.elevation : void 0;
2846
+ const mergedGeo = {
2847
+ ...customKeys,
2848
+ ...coords,
2849
+ ...isNumber(preservedElevation) ? { elevation: preservedElevation } : {},
2850
+ ...callSiteGeo
2851
+ };
2852
+ if (isNumber(mergedGeo.latitude)) mergedGeo.latitude = Math.round(mergedGeo.latitude * 1e3) / 1e3;
2853
+ if (isNumber(mergedGeo.longitude)) mergedGeo.longitude = Math.round(mergedGeo.longitude * 1e3) / 1e3;
2854
+ if (!mergedGeo.sphere && isNumber(mergedGeo.latitude)) {
2855
+ mergedGeo.sphere = mergedGeo.latitude > 1e-3 ? "north" : mergedGeo.latitude < -1e-3 ? "south" : "equator";
2856
+ }
2857
+ let instance = this;
2858
+ const targetTz = mergedGeo.timezone;
2859
+ if (setTimezone && isString(targetTz) && !isEmpty(targetTz))
2860
+ instance = this.set({ timeZone: targetTz });
2861
+ return new TempoClass(instance, {
2862
+ ...instance.config,
2863
+ geo: (0, sdk_exports.deepFreeze)(mergedGeo),
2864
+ ...mergedGeo.sphere ? { sphere: mergedGeo.sphere } : {}
2140
2865
  });
2141
2866
  }
2142
2867
  return this;
@@ -2144,20 +2869,31 @@ var GeoPlugin = definePlugin({
2144
2869
  TempoClass.prototype.geoLookup = async function(opts) {
2145
2870
  return resolveGeoCoordinates(this, opts);
2146
2871
  };
2872
+ TempoClass.prototype.geoDistance = function(other, unit) {
2873
+ return haversineDistance(this, other, unit);
2874
+ };
2875
+ TempoClass.prototype.geoSolarOffset = function(options) {
2876
+ return solarOffset(this, options);
2877
+ };
2147
2878
  }
2148
2879
  });
2149
2880
  var geoPlugin = GeoPlugin;
2150
2881
  var index_default = GeoPlugin;
2151
2882
  export {
2883
+ GEO_PROPERTIES,
2152
2884
  GeoPlugin,
2885
+ clearStashedGeo,
2153
2886
  coerceGeo,
2154
2887
  index_default as default,
2155
2888
  geoLocation,
2156
2889
  geoLookup,
2157
2890
  geoPlugin,
2158
2891
  getStashedGeo,
2892
+ haversineDistance,
2159
2893
  resolveGeoCoordinates,
2160
2894
  serverGeoCoords,
2161
2895
  serverGeoLocation,
2162
- serverMapHemisphere
2896
+ serverMapHemisphere,
2897
+ solarOffset,
2898
+ stashGeo
2163
2899
  };