@putkoff/abstract-utilities 0.1.243 → 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.
Files changed (96) hide show
  1. package/dist/cjs/index.js +771 -355
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/esm/index.js +773 -341
  4. package/dist/esm/index.js.map +1 -1
  5. package/dist/index.d.ts +14 -40
  6. package/dist/types/functions/auth_utils/imports.d.ts +0 -0
  7. package/dist/types/functions/auth_utils/index.d.ts +0 -0
  8. package/dist/types/functions/auth_utils/src/index.d.ts +0 -0
  9. package/dist/types/functions/auth_utils/src/token_utils.d.ts +0 -1
  10. package/dist/types/functions/config_utils/imports.d.ts +0 -0
  11. package/dist/types/functions/config_utils/index.d.ts +0 -0
  12. package/dist/types/functions/config_utils/src/config_utils.d.ts +6 -2
  13. package/dist/types/functions/config_utils/src/index.d.ts +0 -0
  14. package/dist/types/functions/constants_utils/index.d.ts +0 -0
  15. package/dist/types/functions/constants_utils/src/constants.d.ts +0 -0
  16. package/dist/types/functions/constants_utils/src/index.d.ts +0 -0
  17. package/dist/types/functions/env_utils/imports.d.ts +0 -0
  18. package/dist/types/functions/env_utils/index.d.ts +0 -0
  19. package/dist/types/functions/env_utils/src/index.d.ts +0 -0
  20. package/dist/types/functions/env_utils/src/window_utils.d.ts +0 -0
  21. package/dist/types/functions/fetch_utils/imports.d.ts +0 -0
  22. package/dist/types/functions/fetch_utils/index.d.ts +0 -0
  23. package/dist/types/functions/fetch_utils/src/fetch_utils.d.ts +2 -2
  24. package/dist/types/functions/fetch_utils/src/index.d.ts +0 -0
  25. package/dist/types/functions/fetch_utils/src/url_utils.d.ts +0 -0
  26. package/dist/types/functions/fetch_utils/src/utils.d.ts +1 -2
  27. package/dist/types/functions/index.d.ts +1 -2
  28. package/dist/types/functions/math_utils/index.d.ts +0 -0
  29. package/dist/types/functions/math_utils/safe_math.d.ts +0 -0
  30. package/dist/types/functions/path_utils/imports.d.ts +0 -0
  31. package/dist/types/functions/path_utils/index.d.ts +0 -0
  32. package/dist/types/functions/path_utils/src/base_dirs.d.ts +0 -0
  33. package/dist/types/functions/path_utils/src/function_dirs.d.ts +0 -0
  34. package/dist/types/functions/path_utils/src/index.d.ts +0 -0
  35. package/dist/types/functions/path_utils/src/misc_dirs.d.ts +0 -0
  36. package/dist/types/functions/path_utils/src/path_utils.d.ts +0 -4
  37. package/dist/types/functions/path_utils/src/paths.d.ts +0 -0
  38. package/dist/types/functions/path_utils/src/src_dirs.d.ts +0 -0
  39. package/dist/types/functions/read_utils/imports.d.ts +0 -0
  40. package/dist/types/functions/read_utils/index.d.ts +0 -0
  41. package/dist/types/functions/read_utils/src/index.d.ts +0 -0
  42. package/dist/types/functions/read_utils/src/utils.d.ts +0 -0
  43. package/dist/types/functions/rndm_utils/imports.d.ts +0 -0
  44. package/dist/types/functions/rndm_utils/index.d.ts +0 -0
  45. package/dist/types/functions/rndm_utils/src/index.d.ts +0 -0
  46. package/dist/types/functions/rndm_utils/src/utils.d.ts +0 -1
  47. package/dist/types/functions/safe_utils/imports.d.ts +0 -0
  48. package/dist/types/functions/safe_utils/index.d.ts +0 -0
  49. package/dist/types/functions/safe_utils/src/index.d.ts +0 -0
  50. package/dist/types/functions/safe_utils/src/safe_document.d.ts +0 -0
  51. package/dist/types/functions/safe_utils/src/safe_globals.d.ts +0 -0
  52. package/dist/types/functions/safe_utils/src/safe_storage.d.ts +0 -0
  53. package/dist/types/functions/safe_utils/src/safe_window.d.ts +0 -0
  54. package/dist/types/functions/string_utils/index.d.ts +0 -0
  55. package/dist/types/functions/string_utils/src/index.d.ts +0 -0
  56. package/dist/types/functions/string_utils/src/string_utils.d.ts +0 -2
  57. package/dist/types/functions/type_utils/imports.d.ts +0 -0
  58. package/dist/types/functions/type_utils/index.d.ts +0 -0
  59. package/dist/types/functions/type_utils/src/clean_utils.d.ts +0 -0
  60. package/dist/types/functions/type_utils/src/ensure_utils.d.ts +0 -0
  61. package/dist/types/functions/type_utils/src/imports.d.ts +0 -0
  62. package/dist/types/functions/type_utils/src/index.d.ts +0 -0
  63. package/dist/types/functions/type_utils/src/json_utils.d.ts +0 -0
  64. package/dist/types/functions/type_utils/src/mime_utils.d.ts +0 -0
  65. package/dist/types/functions/type_utils/src/type_utils.d.ts +0 -0
  66. package/dist/types/functions/ui_utils/imports.d.ts +0 -0
  67. package/dist/types/functions/ui_utils/index.d.ts +0 -0
  68. package/dist/types/functions/ui_utils/src/button.d.ts +0 -0
  69. package/dist/types/functions/ui_utils/src/checkbox.d.ts +0 -0
  70. package/dist/types/functions/ui_utils/src/index.d.ts +0 -0
  71. package/dist/types/functions/ui_utils/src/input.d.ts +0 -0
  72. package/dist/types/functions/ui_utils/src/spinner.d.ts +0 -0
  73. package/dist/types/functions/variable_utils/imports.d.ts +0 -0
  74. package/dist/types/functions/variable_utils/index.d.ts +0 -0
  75. package/dist/types/functions/variable_utils/src/index.d.ts +0 -0
  76. package/dist/types/functions/variable_utils/src/variable_utils.d.ts +0 -0
  77. package/dist/types/index.d.ts +0 -0
  78. package/dist/types/types/index.d.ts +0 -0
  79. package/dist/types/types/src/ChangePassword.d.ts +0 -0
  80. package/dist/types/types/src/Files.d.ts +0 -0
  81. package/dist/types/types/src/index.d.ts +0 -0
  82. package/dist/types/types/src/login.d.ts +0 -0
  83. package/dist/types/types/src/logout.d.ts +0 -0
  84. package/dist/types/types/src/utils.d.ts +0 -0
  85. package/dist/types/utils/imports.d.ts +0 -0
  86. package/dist/types/utils/index.d.ts +0 -0
  87. package/dist/types/utils/src/Input.d.ts +0 -0
  88. package/dist/types/utils/src/config.d.ts +0 -0
  89. package/dist/types/utils/src/index.d.ts +0 -0
  90. package/package.json +89 -69
  91. package/dist/types/functions/path_utils/src/path_utils.browser.d.ts +0 -2
  92. package/dist/types/functions/path_utils/src/path_utils.node.d.ts +0 -2
  93. package/dist/types/functions/read_utils/src/read_utils.browser.d.ts +0 -1
  94. package/dist/types/functions/read_utils/src/utils.browser.d.ts +0 -3
  95. package/dist/types/functions/url_utils/index.d.ts +0 -1
  96. package/dist/types/functions/url_utils/uri_utils.d.ts +0 -19
package/dist/esm/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  export { useCallback, useEffect, useRef, useState } from 'react';
2
- import path$2 from 'path';
3
- import * as path$1 from 'path-browserify';
2
+ import path$1 from 'path';
4
3
  import * as fs from 'node:fs';
5
4
  import * as fsp from 'node:fs/promises';
6
5
  import * as path from 'node:path';
@@ -145,17 +144,6 @@ function isLoggedIn() {
145
144
  const tok = getToken();
146
145
  return !!tok && !isTokenExpired(tok !== null && tok !== void 0 ? tok : "");
147
146
  }
148
- function removeToken() {
149
- let is_logged = isLoggedIn();
150
- if (is_logged) {
151
- callStorage('removeItem', "token");
152
- }
153
- is_logged = isLoggedIn();
154
- if (is_logged) {
155
- return false;
156
- }
157
- return true;
158
- }
159
147
  /**
160
148
  * Add a Bearer Authorization header.
161
149
  * A shallow copy of headers is returned so callers can keep chaining.
@@ -172,7 +160,7 @@ function requireToken() {
172
160
  const tok = getToken();
173
161
  if (!tok || isTokenExpired(tok)) {
174
162
  console.warn("→ No token or expired token, redirecting to login…");
175
- removeToken();
163
+ localStorage.removeItem("token");
176
164
  window.location.href = '/';
177
165
  throw new Error("Redirecting to login…");
178
166
  }
@@ -190,13 +178,16 @@ function isTokenExpired(token) {
190
178
  }
191
179
  /** Convenience wrapper: return username from the JWT (or null). */
192
180
  function currentUsername() {
193
- const token = getToken();
194
- let uName = null;
195
- if (token) {
196
- const decodedJwt = decodeJwt(token) || {};
197
- uName = (decodedJwt === null || decodedJwt === void 0 ? void 0 : decodedJwt.username) || null;
181
+ const tok = getToken();
182
+ if (!tok)
183
+ return null;
184
+ try {
185
+ const { username } = decodeJwt(tok);
186
+ return username !== null && username !== void 0 ? username : null;
187
+ }
188
+ catch (_a) {
189
+ return null;
198
190
  }
199
- return uName;
200
191
  }
201
192
  function currentUsernames() {
202
193
  var _a;
@@ -340,37 +331,44 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
340
331
  */
341
332
  function readJsonFile(relativeOrAbsolutePath) {
342
333
  return __awaiter(this, void 0, void 0, function* () {
343
- if (typeof window === 'undefined') {
334
+ // 1) Try Node.js fs
335
+ if (typeof process !== 'undefined' &&
336
+ process.versions != null &&
337
+ process.versions.node) {
344
338
  try {
345
- const { readFile } = yield import('fs/promises');
346
- const { isAbsolute, resolve } = yield import('path');
347
- const filePath = isAbsolute(relativeOrAbsolutePath)
339
+ const fs = yield import('fs');
340
+ const path = yield import('path');
341
+ const filePath = path.isAbsolute(relativeOrAbsolutePath)
348
342
  ? relativeOrAbsolutePath
349
- : resolve(import.meta.url ? new URL('.', import.meta.url).pathname : '', relativeOrAbsolutePath);
350
- const text = yield readFile(filePath, 'utf8');
343
+ : path.resolve(process.cwd(), relativeOrAbsolutePath);
344
+ const text = yield fs.promises.readFile(filePath, 'utf8');
351
345
  return JSON.parse(text);
352
346
  }
353
347
  catch (_a) {
354
- return null;
348
+ // swallow and fall back to browser
355
349
  }
356
350
  }
357
- // Browser fallback
351
+ // 2) Try browser fetch
358
352
  const fetchFn = safeGlobalProp('fetch');
359
- if (typeof fetchFn !== 'function')
353
+ if (typeof fetchFn !== 'function') {
360
354
  return null;
355
+ }
356
+ // Resolve URL against document.baseURI if possible
361
357
  let url = relativeOrAbsolutePath;
362
358
  const baseURI = safeGlobalProp('document', 'baseURI');
363
359
  if (baseURI) {
364
360
  try {
365
361
  url = new URL(relativeOrAbsolutePath, baseURI).href;
366
362
  }
367
- catch (_b) { }
363
+ catch (_b) {
364
+ // keep url as-is
365
+ }
368
366
  }
369
367
  try {
370
368
  const res = yield fetchFn(url);
371
369
  if (!res.ok)
372
370
  return null;
373
- return yield res.json();
371
+ return (yield res.json());
374
372
  }
375
373
  catch (_c) {
376
374
  return null;
@@ -413,7 +411,6 @@ function getResult(obj) {
413
411
  }
414
412
  return current;
415
413
  }
416
- const get_result = getResult;
417
414
  // Determines HTTP method, defaults to GET or POST based on body
418
415
  function getMethod(method = null, body = null) {
419
416
  const validMethods = ['GET', 'POST', 'PUT', 'PATCH', 'PULL'];
@@ -502,7 +499,7 @@ function checkResponse(res) {
502
499
  }
503
500
 
504
501
  function fetchIt(endpoint_1) {
505
- return __awaiter(this, arguments, void 0, function* (endpoint, body = null, method = null, headers = null, blob = false, configUrl = false, withCredentials = true, returnJson = true, returnResult = true) {
502
+ return __awaiter(this, arguments, void 0, function* (endpoint, body = null, method = null, headers = null, blob = false, configUrl = false, withCredentials = true, returnJson = true, returnReult = true) {
506
503
  method = (method || "GET").toUpperCase();
507
504
  // 2) choose the URL
508
505
  let url = endpoint;
@@ -518,20 +515,18 @@ function fetchIt(endpoint_1) {
518
515
  ? JSON.stringify(body)
519
516
  : undefined,
520
517
  };
521
- let res = yield fetch(url, opts);
518
+ console.debug("➡️ secureFetchIt →", url, opts);
519
+ const res = yield fetch(url, opts);
522
520
  if (!res.ok) {
523
521
  const err = yield res.text();
524
522
  throw new Error(`HTTP ${res.status}: ${err}`);
525
523
  }
526
524
  if (blob)
527
525
  return res.blob();
528
- if (returnResult || returnJson) {
529
- let JsonRes = parseResult(res);
530
- if (returnResult) {
531
- JsonRes = getResult(JsonRes);
532
- }
533
- return JsonRes;
534
- }
526
+ if (returnReult)
527
+ return getResult(res.json());
528
+ if (returnJson)
529
+ return res.json();
535
530
  return res;
536
531
  });
537
532
  }
@@ -604,7 +599,7 @@ function get_full_path(partial_path, parent_dir = null) {
604
599
  if (typeof partial_path !== 'string') {
605
600
  throw new Error('partial_path must be a string');
606
601
  }
607
- if (path$2.isAbsolute(partial_path)) {
602
+ if (path$1.isAbsolute(partial_path)) {
608
603
  return partial_path;
609
604
  }
610
605
  return urlJoin(parent_dir, partial_path);
@@ -619,7 +614,7 @@ function path_to_url(filePath, all_paths) {
619
614
  }
620
615
  for (const key in all_paths) {
621
616
  const mapping = all_paths[key];
622
- const normalizedBase = path$2.normalize(mapping.path);
617
+ const normalizedBase = path$1.normalize(mapping.path);
623
618
  if (filePath.startsWith(normalizedBase)) {
624
619
  const relativePath = filePath.substring(normalizedBase.length);
625
620
  return urlJoin(mapping.url, relativePath.replace(/\\/g, '/'));
@@ -645,6 +640,637 @@ function url_to_path(urlStr, all_paths) {
645
640
  return null;
646
641
  }
647
642
 
643
+ function assertPath(path) {
644
+ if (typeof path !== 'string') {
645
+ throw new TypeError('Path must be a string. Received ' + JSON.stringify(path));
646
+ }
647
+ }
648
+
649
+ // Resolves . and .. elements in a path with directory names
650
+ function normalizeStringPosix(path, allowAboveRoot) {
651
+ var res = '';
652
+ var lastSegmentLength = 0;
653
+ var lastSlash = -1;
654
+ var dots = 0;
655
+ var code;
656
+ for (var i = 0; i <= path.length; ++i) {
657
+ if (i < path.length)
658
+ code = path.charCodeAt(i);
659
+ else if (code === 47 /*/*/)
660
+ break;
661
+ else
662
+ code = 47 /*/*/;
663
+ if (code === 47 /*/*/) {
664
+ if (lastSlash === i - 1 || dots === 1) ; else if (lastSlash !== i - 1 && dots === 2) {
665
+ if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) {
666
+ if (res.length > 2) {
667
+ var lastSlashIndex = res.lastIndexOf('/');
668
+ if (lastSlashIndex !== res.length - 1) {
669
+ if (lastSlashIndex === -1) {
670
+ res = '';
671
+ lastSegmentLength = 0;
672
+ } else {
673
+ res = res.slice(0, lastSlashIndex);
674
+ lastSegmentLength = res.length - 1 - res.lastIndexOf('/');
675
+ }
676
+ lastSlash = i;
677
+ dots = 0;
678
+ continue;
679
+ }
680
+ } else if (res.length === 2 || res.length === 1) {
681
+ res = '';
682
+ lastSegmentLength = 0;
683
+ lastSlash = i;
684
+ dots = 0;
685
+ continue;
686
+ }
687
+ }
688
+ if (allowAboveRoot) {
689
+ if (res.length > 0)
690
+ res += '/..';
691
+ else
692
+ res = '..';
693
+ lastSegmentLength = 2;
694
+ }
695
+ } else {
696
+ if (res.length > 0)
697
+ res += '/' + path.slice(lastSlash + 1, i);
698
+ else
699
+ res = path.slice(lastSlash + 1, i);
700
+ lastSegmentLength = i - lastSlash - 1;
701
+ }
702
+ lastSlash = i;
703
+ dots = 0;
704
+ } else if (code === 46 /*.*/ && dots !== -1) {
705
+ ++dots;
706
+ } else {
707
+ dots = -1;
708
+ }
709
+ }
710
+ return res;
711
+ }
712
+
713
+ function _format(sep, pathObject) {
714
+ var dir = pathObject.dir || pathObject.root;
715
+ var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || '');
716
+ if (!dir) {
717
+ return base;
718
+ }
719
+ if (dir === pathObject.root) {
720
+ return dir + base;
721
+ }
722
+ return dir + sep + base;
723
+ }
724
+
725
+ var posix = {
726
+ // path.resolve([from ...], to)
727
+ resolve: function resolve() {
728
+ var resolvedPath = '';
729
+ var resolvedAbsolute = false;
730
+ var cwd;
731
+
732
+ for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
733
+ var path;
734
+ if (i >= 0)
735
+ path = arguments[i];
736
+ else {
737
+ if (cwd === undefined)
738
+ cwd = process.cwd();
739
+ path = cwd;
740
+ }
741
+
742
+ assertPath(path);
743
+
744
+ // Skip empty entries
745
+ if (path.length === 0) {
746
+ continue;
747
+ }
748
+
749
+ resolvedPath = path + '/' + resolvedPath;
750
+ resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/;
751
+ }
752
+
753
+ // At this point the path should be resolved to a full absolute path, but
754
+ // handle relative paths to be safe (might happen when process.cwd() fails)
755
+
756
+ // Normalize the path
757
+ resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute);
758
+
759
+ if (resolvedAbsolute) {
760
+ if (resolvedPath.length > 0)
761
+ return '/' + resolvedPath;
762
+ else
763
+ return '/';
764
+ } else if (resolvedPath.length > 0) {
765
+ return resolvedPath;
766
+ } else {
767
+ return '.';
768
+ }
769
+ },
770
+
771
+ normalize: function normalize(path) {
772
+ assertPath(path);
773
+
774
+ if (path.length === 0) return '.';
775
+
776
+ var isAbsolute = path.charCodeAt(0) === 47 /*/*/;
777
+ var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/;
778
+
779
+ // Normalize the path
780
+ path = normalizeStringPosix(path, !isAbsolute);
781
+
782
+ if (path.length === 0 && !isAbsolute) path = '.';
783
+ if (path.length > 0 && trailingSeparator) path += '/';
784
+
785
+ if (isAbsolute) return '/' + path;
786
+ return path;
787
+ },
788
+
789
+ isAbsolute: function isAbsolute(path) {
790
+ assertPath(path);
791
+ return path.length > 0 && path.charCodeAt(0) === 47 /*/*/;
792
+ },
793
+
794
+ join: function join() {
795
+ if (arguments.length === 0)
796
+ return '.';
797
+ var joined;
798
+ for (var i = 0; i < arguments.length; ++i) {
799
+ var arg = arguments[i];
800
+ assertPath(arg);
801
+ if (arg.length > 0) {
802
+ if (joined === undefined)
803
+ joined = arg;
804
+ else
805
+ joined += '/' + arg;
806
+ }
807
+ }
808
+ if (joined === undefined)
809
+ return '.';
810
+ return posix.normalize(joined);
811
+ },
812
+
813
+ relative: function relative(from, to) {
814
+ assertPath(from);
815
+ assertPath(to);
816
+
817
+ if (from === to) return '';
818
+
819
+ from = posix.resolve(from);
820
+ to = posix.resolve(to);
821
+
822
+ if (from === to) return '';
823
+
824
+ // Trim any leading backslashes
825
+ var fromStart = 1;
826
+ for (; fromStart < from.length; ++fromStart) {
827
+ if (from.charCodeAt(fromStart) !== 47 /*/*/)
828
+ break;
829
+ }
830
+ var fromEnd = from.length;
831
+ var fromLen = fromEnd - fromStart;
832
+
833
+ // Trim any leading backslashes
834
+ var toStart = 1;
835
+ for (; toStart < to.length; ++toStart) {
836
+ if (to.charCodeAt(toStart) !== 47 /*/*/)
837
+ break;
838
+ }
839
+ var toEnd = to.length;
840
+ var toLen = toEnd - toStart;
841
+
842
+ // Compare paths to find the longest common path from root
843
+ var length = fromLen < toLen ? fromLen : toLen;
844
+ var lastCommonSep = -1;
845
+ var i = 0;
846
+ for (; i <= length; ++i) {
847
+ if (i === length) {
848
+ if (toLen > length) {
849
+ if (to.charCodeAt(toStart + i) === 47 /*/*/) {
850
+ // We get here if `from` is the exact base path for `to`.
851
+ // For example: from='/foo/bar'; to='/foo/bar/baz'
852
+ return to.slice(toStart + i + 1);
853
+ } else if (i === 0) {
854
+ // We get here if `from` is the root
855
+ // For example: from='/'; to='/foo'
856
+ return to.slice(toStart + i);
857
+ }
858
+ } else if (fromLen > length) {
859
+ if (from.charCodeAt(fromStart + i) === 47 /*/*/) {
860
+ // We get here if `to` is the exact base path for `from`.
861
+ // For example: from='/foo/bar/baz'; to='/foo/bar'
862
+ lastCommonSep = i;
863
+ } else if (i === 0) {
864
+ // We get here if `to` is the root.
865
+ // For example: from='/foo'; to='/'
866
+ lastCommonSep = 0;
867
+ }
868
+ }
869
+ break;
870
+ }
871
+ var fromCode = from.charCodeAt(fromStart + i);
872
+ var toCode = to.charCodeAt(toStart + i);
873
+ if (fromCode !== toCode)
874
+ break;
875
+ else if (fromCode === 47 /*/*/)
876
+ lastCommonSep = i;
877
+ }
878
+
879
+ var out = '';
880
+ // Generate the relative path based on the path difference between `to`
881
+ // and `from`
882
+ for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) {
883
+ if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) {
884
+ if (out.length === 0)
885
+ out += '..';
886
+ else
887
+ out += '/..';
888
+ }
889
+ }
890
+
891
+ // Lastly, append the rest of the destination (`to`) path that comes after
892
+ // the common path parts
893
+ if (out.length > 0)
894
+ return out + to.slice(toStart + lastCommonSep);
895
+ else {
896
+ toStart += lastCommonSep;
897
+ if (to.charCodeAt(toStart) === 47 /*/*/)
898
+ ++toStart;
899
+ return to.slice(toStart);
900
+ }
901
+ },
902
+
903
+ _makeLong: function _makeLong(path) {
904
+ return path;
905
+ },
906
+
907
+ dirname: function dirname(path) {
908
+ assertPath(path);
909
+ if (path.length === 0) return '.';
910
+ var code = path.charCodeAt(0);
911
+ var hasRoot = code === 47 /*/*/;
912
+ var end = -1;
913
+ var matchedSlash = true;
914
+ for (var i = path.length - 1; i >= 1; --i) {
915
+ code = path.charCodeAt(i);
916
+ if (code === 47 /*/*/) {
917
+ if (!matchedSlash) {
918
+ end = i;
919
+ break;
920
+ }
921
+ } else {
922
+ // We saw the first non-path separator
923
+ matchedSlash = false;
924
+ }
925
+ }
926
+
927
+ if (end === -1) return hasRoot ? '/' : '.';
928
+ if (hasRoot && end === 1) return '//';
929
+ return path.slice(0, end);
930
+ },
931
+
932
+ basename: function basename(path, ext) {
933
+ if (ext !== undefined && typeof ext !== 'string') throw new TypeError('"ext" argument must be a string');
934
+ assertPath(path);
935
+
936
+ var start = 0;
937
+ var end = -1;
938
+ var matchedSlash = true;
939
+ var i;
940
+
941
+ if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
942
+ if (ext.length === path.length && ext === path) return '';
943
+ var extIdx = ext.length - 1;
944
+ var firstNonSlashEnd = -1;
945
+ for (i = path.length - 1; i >= 0; --i) {
946
+ var code = path.charCodeAt(i);
947
+ if (code === 47 /*/*/) {
948
+ // If we reached a path separator that was not part of a set of path
949
+ // separators at the end of the string, stop now
950
+ if (!matchedSlash) {
951
+ start = i + 1;
952
+ break;
953
+ }
954
+ } else {
955
+ if (firstNonSlashEnd === -1) {
956
+ // We saw the first non-path separator, remember this index in case
957
+ // we need it if the extension ends up not matching
958
+ matchedSlash = false;
959
+ firstNonSlashEnd = i + 1;
960
+ }
961
+ if (extIdx >= 0) {
962
+ // Try to match the explicit extension
963
+ if (code === ext.charCodeAt(extIdx)) {
964
+ if (--extIdx === -1) {
965
+ // We matched the extension, so mark this as the end of our path
966
+ // component
967
+ end = i;
968
+ }
969
+ } else {
970
+ // Extension does not match, so our result is the entire path
971
+ // component
972
+ extIdx = -1;
973
+ end = firstNonSlashEnd;
974
+ }
975
+ }
976
+ }
977
+ }
978
+
979
+ if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length;
980
+ return path.slice(start, end);
981
+ } else {
982
+ for (i = path.length - 1; i >= 0; --i) {
983
+ if (path.charCodeAt(i) === 47 /*/*/) {
984
+ // If we reached a path separator that was not part of a set of path
985
+ // separators at the end of the string, stop now
986
+ if (!matchedSlash) {
987
+ start = i + 1;
988
+ break;
989
+ }
990
+ } else if (end === -1) {
991
+ // We saw the first non-path separator, mark this as the end of our
992
+ // path component
993
+ matchedSlash = false;
994
+ end = i + 1;
995
+ }
996
+ }
997
+
998
+ if (end === -1) return '';
999
+ return path.slice(start, end);
1000
+ }
1001
+ },
1002
+
1003
+ extname: function extname(path) {
1004
+ assertPath(path);
1005
+ var startDot = -1;
1006
+ var startPart = 0;
1007
+ var end = -1;
1008
+ var matchedSlash = true;
1009
+ // Track the state of characters (if any) we see before our first dot and
1010
+ // after any path separator we find
1011
+ var preDotState = 0;
1012
+ for (var i = path.length - 1; i >= 0; --i) {
1013
+ var code = path.charCodeAt(i);
1014
+ if (code === 47 /*/*/) {
1015
+ // If we reached a path separator that was not part of a set of path
1016
+ // separators at the end of the string, stop now
1017
+ if (!matchedSlash) {
1018
+ startPart = i + 1;
1019
+ break;
1020
+ }
1021
+ continue;
1022
+ }
1023
+ if (end === -1) {
1024
+ // We saw the first non-path separator, mark this as the end of our
1025
+ // extension
1026
+ matchedSlash = false;
1027
+ end = i + 1;
1028
+ }
1029
+ if (code === 46 /*.*/) {
1030
+ // If this is our first dot, mark it as the start of our extension
1031
+ if (startDot === -1)
1032
+ startDot = i;
1033
+ else if (preDotState !== 1)
1034
+ preDotState = 1;
1035
+ } else if (startDot !== -1) {
1036
+ // We saw a non-dot and non-path separator before our dot, so we should
1037
+ // have a good chance at having a non-empty extension
1038
+ preDotState = -1;
1039
+ }
1040
+ }
1041
+
1042
+ if (startDot === -1 || end === -1 ||
1043
+ // We saw a non-dot character immediately before the dot
1044
+ preDotState === 0 ||
1045
+ // The (right-most) trimmed path component is exactly '..'
1046
+ preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
1047
+ return '';
1048
+ }
1049
+ return path.slice(startDot, end);
1050
+ },
1051
+
1052
+ format: function format(pathObject) {
1053
+ if (pathObject === null || typeof pathObject !== 'object') {
1054
+ throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
1055
+ }
1056
+ return _format('/', pathObject);
1057
+ },
1058
+
1059
+ parse: function parse(path) {
1060
+ assertPath(path);
1061
+
1062
+ var ret = { root: '', dir: '', base: '', ext: '', name: '' };
1063
+ if (path.length === 0) return ret;
1064
+ var code = path.charCodeAt(0);
1065
+ var isAbsolute = code === 47 /*/*/;
1066
+ var start;
1067
+ if (isAbsolute) {
1068
+ ret.root = '/';
1069
+ start = 1;
1070
+ } else {
1071
+ start = 0;
1072
+ }
1073
+ var startDot = -1;
1074
+ var startPart = 0;
1075
+ var end = -1;
1076
+ var matchedSlash = true;
1077
+ var i = path.length - 1;
1078
+
1079
+ // Track the state of characters (if any) we see before our first dot and
1080
+ // after any path separator we find
1081
+ var preDotState = 0;
1082
+
1083
+ // Get non-dir info
1084
+ for (; i >= start; --i) {
1085
+ code = path.charCodeAt(i);
1086
+ if (code === 47 /*/*/) {
1087
+ // If we reached a path separator that was not part of a set of path
1088
+ // separators at the end of the string, stop now
1089
+ if (!matchedSlash) {
1090
+ startPart = i + 1;
1091
+ break;
1092
+ }
1093
+ continue;
1094
+ }
1095
+ if (end === -1) {
1096
+ // We saw the first non-path separator, mark this as the end of our
1097
+ // extension
1098
+ matchedSlash = false;
1099
+ end = i + 1;
1100
+ }
1101
+ if (code === 46 /*.*/) {
1102
+ // If this is our first dot, mark it as the start of our extension
1103
+ if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1;
1104
+ } else if (startDot !== -1) {
1105
+ // We saw a non-dot and non-path separator before our dot, so we should
1106
+ // have a good chance at having a non-empty extension
1107
+ preDotState = -1;
1108
+ }
1109
+ }
1110
+
1111
+ if (startDot === -1 || end === -1 ||
1112
+ // We saw a non-dot character immediately before the dot
1113
+ preDotState === 0 ||
1114
+ // The (right-most) trimmed path component is exactly '..'
1115
+ preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
1116
+ if (end !== -1) {
1117
+ if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end);
1118
+ }
1119
+ } else {
1120
+ if (startPart === 0 && isAbsolute) {
1121
+ ret.name = path.slice(1, startDot);
1122
+ ret.base = path.slice(1, end);
1123
+ } else {
1124
+ ret.name = path.slice(startPart, startDot);
1125
+ ret.base = path.slice(startPart, end);
1126
+ }
1127
+ ret.ext = path.slice(startDot, end);
1128
+ }
1129
+
1130
+ if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/';
1131
+
1132
+ return ret;
1133
+ },
1134
+
1135
+ sep: '/',
1136
+ delimiter: ':',
1137
+ win32: null,
1138
+ posix: null
1139
+ };
1140
+
1141
+ posix.posix = posix;
1142
+
1143
+ var pathBrowserify = posix;
1144
+
1145
+ function getSubstring(obj, maxLength = null, minLength = null) {
1146
+ const objLength = obj.length;
1147
+ const effectiveMaxLength = maxLength !== null && maxLength !== void 0 ? maxLength : objLength; // Use nullish coalescing for clarity
1148
+ const effectiveMinLength = minLength !== null && minLength !== void 0 ? minLength : 0;
1149
+ // Ensure bounds are valid
1150
+ const clampedMaxLength = Math.min(Math.max(effectiveMaxLength, 0), objLength);
1151
+ const clampedMinLength = Math.min(Math.max(effectiveMinLength, 0), objLength);
1152
+ // If minLength exceeds maxLength, return empty string or adjust logic as needed
1153
+ if (clampedMinLength >= clampedMaxLength) {
1154
+ return '';
1155
+ }
1156
+ return obj.substring(clampedMinLength, clampedMaxLength);
1157
+ }
1158
+ function truncateString(obj, maxLength = 20) {
1159
+ const objLength = obj.length;
1160
+ if (objLength > maxLength && maxLength) {
1161
+ obj = getSubstring(obj, maxLength) + '...';
1162
+ }
1163
+ return obj;
1164
+ }
1165
+ // string_utils/src/string_utils.ts
1166
+ function stripPrefixes(str, bases = []) {
1167
+ /* NEW: coerce whatever arrives into a string */
1168
+ str = String(str);
1169
+ const prefixes = (Array.isArray(bases) ? bases : [bases])
1170
+ .filter(Boolean)
1171
+ .sort((a, b) => b.length - a.length); // longest first
1172
+ let changed = true;
1173
+ while (changed) {
1174
+ changed = false;
1175
+ for (const prefix of prefixes) {
1176
+ if (str.startsWith(prefix)) {
1177
+ str = str.slice(prefix.length);
1178
+ changed = true;
1179
+ break; // restart from longest prefix
1180
+ }
1181
+ }
1182
+ }
1183
+ return str;
1184
+ }
1185
+ /**
1186
+ * Removes characters from the beginning of the string
1187
+ * if they are found in the list of characters.
1188
+ *
1189
+ * @param str - The input string.
1190
+ * @param listObjects - A string or an array of characters to remove.
1191
+ * @returns The modified string.
1192
+ */
1193
+ function eatInner(str, listObjects) {
1194
+ if (!Array.isArray(listObjects)) {
1195
+ listObjects = [listObjects];
1196
+ }
1197
+ // Ensure str is a string
1198
+ str = String(str);
1199
+ // Remove characters from the beginning while they are in listObjects
1200
+ while (str.length > 0 && listObjects.includes(str[0])) {
1201
+ str = str.slice(1);
1202
+ }
1203
+ return str;
1204
+ }
1205
+ /**
1206
+ * Removes characters from the end of the string
1207
+ * if they are found in the list of characters.
1208
+ *
1209
+ * @param str - The input string.
1210
+ * @param listObjects - A string or an array of characters to remove.
1211
+ * @returns The modified string.
1212
+ */
1213
+ function eatOuter(str, listObjects) {
1214
+ if (!Array.isArray(listObjects)) {
1215
+ listObjects = [listObjects];
1216
+ }
1217
+ // Ensure str is a string
1218
+ str = String(str);
1219
+ // Remove characters from the end while they are in listObjects
1220
+ while (str.length > 0 && listObjects.includes(str[str.length - 1])) {
1221
+ str = str.slice(0, -1);
1222
+ }
1223
+ return str;
1224
+ }
1225
+ /**
1226
+ * Removes characters from both the beginning and the end of the string
1227
+ * if they are found in the list of characters.
1228
+ *
1229
+ * @param str - The input string.
1230
+ * @param listObjects - A string or an array of characters to remove.
1231
+ * @returns The modified string.
1232
+ */
1233
+ function eatAll(str, listObjects) {
1234
+ return eatOuter(eatInner(str, listObjects), listObjects);
1235
+ }
1236
+ function eatEnd(obj, endings = ['/']) {
1237
+ let result = obj;
1238
+ let modified = true;
1239
+ while (modified) {
1240
+ modified = false;
1241
+ for (const ending of endings) {
1242
+ if (result.endsWith(ending)) {
1243
+ result = result.slice(0, -ending.length);
1244
+ modified = true;
1245
+ break;
1246
+ }
1247
+ }
1248
+ }
1249
+ return result;
1250
+ }
1251
+ function tryParse(obj) {
1252
+ try {
1253
+ obj = JSON.stringify(obj);
1254
+ }
1255
+ catch (err) {
1256
+ try {
1257
+ obj = JSON.parse(obj);
1258
+ }
1259
+ catch (err) {
1260
+ }
1261
+ }
1262
+ return obj;
1263
+ }
1264
+ function create_list_string(array_obj) {
1265
+ let string = '';
1266
+ for (const obj in array_obj) {
1267
+ const array_value = array_obj[obj];
1268
+ const parsed_value = tryParse(array_value);
1269
+ string += `${obj} == ${parsed_value}\n`;
1270
+ }
1271
+ return string;
1272
+ }
1273
+
648
1274
  function ensure_list(obj) {
649
1275
  const objArray = Array.isArray(obj) ? obj : [obj];
650
1276
  return objArray;
@@ -1085,159 +1711,6 @@ const confirm_type = confirmType;
1085
1711
  const is_media_type = isMediaType;
1086
1712
  const get_mime_type = getMimeType;
1087
1713
 
1088
- function getSubstring(obj, maxLength = null, minLength = null) {
1089
- const objLength = obj.length;
1090
- const effectiveMaxLength = maxLength !== null && maxLength !== void 0 ? maxLength : objLength; // Use nullish coalescing for clarity
1091
- const effectiveMinLength = minLength !== null && minLength !== void 0 ? minLength : 0;
1092
- // Ensure bounds are valid
1093
- const clampedMaxLength = Math.min(Math.max(effectiveMaxLength, 0), objLength);
1094
- const clampedMinLength = Math.min(Math.max(effectiveMinLength, 0), objLength);
1095
- // If minLength exceeds maxLength, return empty string or adjust logic as needed
1096
- if (clampedMinLength >= clampedMaxLength) {
1097
- return '';
1098
- }
1099
- return obj.substring(clampedMinLength, clampedMaxLength);
1100
- }
1101
- function truncateString(obj, maxLength = 20) {
1102
- const objLength = obj.length;
1103
- if (objLength > maxLength && maxLength) {
1104
- obj = getSubstring(obj, maxLength) + '...';
1105
- }
1106
- return obj;
1107
- }
1108
- function capitalize_str(string) {
1109
- string = assureString(string);
1110
- const string_len = string.length;
1111
- let init_char = string.toUpperCase();
1112
- if (string_len > 0) {
1113
- init_char = string[0].toUpperCase();
1114
- }
1115
- let rest_chars = '';
1116
- if (string_len > 1) {
1117
- rest_chars = string.slice(1).toLowerCase();
1118
- }
1119
- const fin_chars = `${init_char}${rest_chars}`;
1120
- return fin_chars;
1121
- }
1122
- function capitalize(string) {
1123
- let nu_string = '';
1124
- string = assureString(string);
1125
- let objs = string.replace('-', '_').split('_');
1126
- for (const obj of objs) {
1127
- let str_obj = capitalize_str(obj);
1128
- nu_string = `${nu_string} ${str_obj}`;
1129
- }
1130
- return eatAll(nu_string, [' ']);
1131
- }
1132
- // string_utils/src/string_utils.ts
1133
- function stripPrefixes(str, bases = []) {
1134
- /* NEW: coerce whatever arrives into a string */
1135
- str = String(str);
1136
- const prefixes = (Array.isArray(bases) ? bases : [bases])
1137
- .filter(Boolean)
1138
- .sort((a, b) => b.length - a.length); // longest first
1139
- let changed = true;
1140
- while (changed) {
1141
- changed = false;
1142
- for (const prefix of prefixes) {
1143
- if (str.startsWith(prefix)) {
1144
- str = str.slice(prefix.length);
1145
- changed = true;
1146
- break; // restart from longest prefix
1147
- }
1148
- }
1149
- }
1150
- return str;
1151
- }
1152
- /**
1153
- * Removes characters from the beginning of the string
1154
- * if they are found in the list of characters.
1155
- *
1156
- * @param str - The input string.
1157
- * @param listObjects - A string or an array of characters to remove.
1158
- * @returns The modified string.
1159
- */
1160
- function eatInner(str, listObjects) {
1161
- if (!Array.isArray(listObjects)) {
1162
- listObjects = [listObjects];
1163
- }
1164
- // Ensure str is a string
1165
- str = String(str);
1166
- // Remove characters from the beginning while they are in listObjects
1167
- while (str.length > 0 && listObjects.includes(str[0])) {
1168
- str = str.slice(1);
1169
- }
1170
- return str;
1171
- }
1172
- /**
1173
- * Removes characters from the end of the string
1174
- * if they are found in the list of characters.
1175
- *
1176
- * @param str - The input string.
1177
- * @param listObjects - A string or an array of characters to remove.
1178
- * @returns The modified string.
1179
- */
1180
- function eatOuter(str, listObjects) {
1181
- if (!Array.isArray(listObjects)) {
1182
- listObjects = [listObjects];
1183
- }
1184
- // Ensure str is a string
1185
- str = String(str);
1186
- // Remove characters from the end while they are in listObjects
1187
- while (str.length > 0 && listObjects.includes(str[str.length - 1])) {
1188
- str = str.slice(0, -1);
1189
- }
1190
- return str;
1191
- }
1192
- /**
1193
- * Removes characters from both the beginning and the end of the string
1194
- * if they are found in the list of characters.
1195
- *
1196
- * @param str - The input string.
1197
- * @param listObjects - A string or an array of characters to remove.
1198
- * @returns The modified string.
1199
- */
1200
- function eatAll(str, listObjects) {
1201
- return eatOuter(eatInner(str, listObjects), listObjects);
1202
- }
1203
- function eatEnd(obj, endings = ['/']) {
1204
- let result = obj;
1205
- let modified = true;
1206
- while (modified) {
1207
- modified = false;
1208
- for (const ending of endings) {
1209
- if (result.endsWith(ending)) {
1210
- result = result.slice(0, -ending.length);
1211
- modified = true;
1212
- break;
1213
- }
1214
- }
1215
- }
1216
- return result;
1217
- }
1218
- function tryParse(obj) {
1219
- try {
1220
- obj = JSON.stringify(obj);
1221
- }
1222
- catch (err) {
1223
- try {
1224
- obj = JSON.parse(obj);
1225
- }
1226
- catch (err) {
1227
- }
1228
- }
1229
- return obj;
1230
- }
1231
- function create_list_string(array_obj) {
1232
- let string = '';
1233
- for (const obj in array_obj) {
1234
- const array_value = array_obj[obj];
1235
- const parsed_value = tryParse(array_value);
1236
- string += `${obj} == ${parsed_value}\n`;
1237
- }
1238
- return string;
1239
- }
1240
-
1241
1714
  /**
1242
1715
  * In the browser we already have a WHATWG URL constructor on window.
1243
1716
  * Here we re-export it as “url” so other modules can import it.
@@ -1258,37 +1731,34 @@ function fileURLToPath(fileUrl) {
1258
1731
  }
1259
1732
  }
1260
1733
  function getAbsolutePath() {
1261
- if (typeof window !== 'undefined')
1262
- return '';
1263
1734
  return fileURLToPath(import.meta.url);
1264
1735
  }
1265
1736
 
1266
- // path_utils.browser.ts
1267
1737
  function get_dirname(filePath) {
1268
1738
  if (!filePath)
1269
1739
  return '';
1270
- return path$1.dirname(filePath);
1740
+ return pathBrowserify.dirname(filePath);
1271
1741
  }
1272
1742
  function get_basename(filePath) {
1273
1743
  if (!filePath)
1274
1744
  return '';
1275
- return path$1.basename(filePath);
1745
+ return pathBrowserify.basename(filePath);
1276
1746
  }
1277
1747
  function get_filename(file_path) {
1278
- const ext = path$1.extname(file_path);
1279
- return path$1.basename(file_path, ext);
1748
+ const ext = pathBrowserify.extname(file_path);
1749
+ return pathBrowserify.basename(file_path, ext);
1280
1750
  }
1281
1751
  function get_extname(filePath) {
1282
1752
  if (!filePath)
1283
1753
  return '';
1284
- return path$1.extname(filePath);
1754
+ return pathBrowserify.extname(filePath);
1285
1755
  }
1286
1756
  function get_splitext(filePath) {
1287
1757
  if (!filePath)
1288
1758
  return { filename: '', extname: '' };
1289
- const ext = path$1.extname(filePath);
1759
+ const ext = pathBrowserify.extname(filePath);
1290
1760
  // Get the basename without the extension
1291
- const filename = path$1.basename(filePath, ext);
1761
+ const filename = pathBrowserify.basename(filePath, ext);
1292
1762
  return { filename, ext };
1293
1763
  }
1294
1764
  /**
@@ -1319,23 +1789,6 @@ function make_path(...paths) {
1319
1789
  }
1320
1790
  return real_path;
1321
1791
  }
1322
- function makePath(...paths) {
1323
- var _a;
1324
- const pathArray = ensure_list(paths);
1325
- let real_path = '';
1326
- for (let i = 0; i < pathArray.length; i++) {
1327
- let seg = String((_a = pathArray[i]) !== null && _a !== void 0 ? _a : '');
1328
- if (i === 0) {
1329
- real_path = seg;
1330
- }
1331
- else {
1332
- seg = eatInner(seg, ['/']);
1333
- real_path = eatOuter(real_path, ['/']);
1334
- real_path = `${real_path}/${seg}`;
1335
- }
1336
- }
1337
- return real_path || '';
1338
- }
1339
1792
  function sanitizeFilename(filename) {
1340
1793
  return filename
1341
1794
  .toLowerCase()
@@ -1345,13 +1798,6 @@ function sanitizeFilename(filename) {
1345
1798
  .replace(/-+/g, '-') // Collapse multiple hyphens into one
1346
1799
  .replace(/^-|-$/, ''); // Remove leading/trailing hyphens
1347
1800
  }
1348
- function get_relative_path(directory, fullPath) {
1349
- return path$1.relative(directory, fullPath);
1350
- }
1351
- // Safer resolver that strips .. at the front only, but prefer server-side checks.
1352
- function get_safe_path(p) {
1353
- return path$1.normalize(p).replace(/^(\.\.[/\\])+/, '');
1354
- }
1355
1801
  function make_sanitized_path(...paths) {
1356
1802
  let real_path = '';
1357
1803
  for (let i = 0; i < paths.length; i++) {
@@ -1365,13 +1811,13 @@ function make_sanitized_path(...paths) {
1365
1811
  }
1366
1812
  return real_path || '';
1367
1813
  }
1368
- /** FIXED: your regexes were strings. This correctly joins without duplicate slashes. */
1369
1814
  function normalizeUrl(base, p) {
1370
1815
  if (!p)
1371
- return base.replace(/\/+$/g, '');
1372
- const cleanBase = base.replace(/\/+$/g, '');
1373
- const cleanPath = p.replace(/^\/+/g, '');
1374
- return `${cleanBase}/${cleanPath}`.replace(/([^:])\/{2,}/g, '$1/'); // keep protocol //
1816
+ return base;
1817
+ const cleanBase = base.replace(/\/+$/, ''); // regex literal
1818
+ const cleanPath = p.replace(/^\/+/, '');
1819
+ // collapse multiple “//” into one, but keep the “://” after protocol
1820
+ return `${cleanBase}/${cleanPath}`.replace(/([^:])\/{2,}/g, '$1/');
1375
1821
  }
1376
1822
 
1377
1823
  /**
@@ -1472,7 +1918,32 @@ function alertit(obj = null) {
1472
1918
  }
1473
1919
  alert(msg);
1474
1920
  }
1475
- const alertIt = alertit;
1921
+
1922
+ // take N args and coerce them all to numbers
1923
+ function safeNums(...args) {
1924
+ return args.map(ensure_number);
1925
+ }
1926
+ // divide the first value by each of the following
1927
+ function safeDivide(...args) {
1928
+ const [head, ...rest] = safeNums(...args);
1929
+ // if we don’t have a head or any divisor is zero, bail
1930
+ if (head === 0 || rest.some((d) => d === 0))
1931
+ return 0;
1932
+ return rest.reduce((acc, d) => acc / d, head);
1933
+ }
1934
+ // multiply all the values together
1935
+ function safeMultiply(...args) {
1936
+ const nums = safeNums(...args);
1937
+ // if any number is zero, result is zero
1938
+ if (nums.includes(0))
1939
+ return 0;
1940
+ return nums.reduce((acc, n) => acc * n, 1);
1941
+ }
1942
+ // round a value to two decimals by percent
1943
+ function roundPercentage(x) {
1944
+ const pct = safeMultiply(ensure_number(x), 100);
1945
+ return safeDivide(Math.round(pct), 100);
1946
+ }
1476
1947
 
1477
1948
  function Button(_a) {
1478
1949
  var { children, color = 'gray', variant = 'default', className = '' } = _a, rest = __rest(_a, ["children", "color", "variant", "className"]);
@@ -1510,17 +1981,74 @@ function Spinner() {
1510
1981
  }
1511
1982
 
1512
1983
  // src/functions/config_utils/src/config_utils.ts
1513
- /**
1514
- * Attempt to load config.json if present, otherwise return empty object.
1515
- */
1516
- function getConfigJson() {
1517
- return __awaiter(this, void 0, void 0, function* () {
1984
+ let _cachedConfig = null;
1985
+ function loadConfig() {
1986
+ return __awaiter(this, arguments, void 0, function* (filePath = null) {
1987
+ var _a;
1988
+ if (_cachedConfig) {
1989
+ return _cachedConfig;
1990
+ }
1991
+ // 1) figure out where config.json lives
1992
+ let configUrl;
1993
+ if (filePath) {
1994
+ configUrl = filePath;
1995
+ }
1996
+ else if (typeof import.meta !== 'undefined' && typeof import.meta.url === 'string') {
1997
+ // ES module: resolve relative to this file
1998
+ try {
1999
+ configUrl = new URL('./config.json', import.meta.url).href;
2000
+ }
2001
+ catch (_b) {
2002
+ configUrl = 'config.json';
2003
+ }
2004
+ }
2005
+ else {
2006
+ // browser fallback
2007
+ const baseURI = safeGlobalProp('document', 'baseURI');
2008
+ try {
2009
+ configUrl =
2010
+ typeof baseURI === 'string'
2011
+ ? new URL('config.json', baseURI).href
2012
+ : 'config.json';
2013
+ }
2014
+ catch (_c) {
2015
+ configUrl = 'config.json';
2016
+ }
2017
+ }
2018
+ // 2) if we have a fetch, try HTTP(S)
2019
+ const fetchFn = safeGlobalProp('fetch');
2020
+ if (typeof fetchFn === 'function') {
2021
+ try {
2022
+ const res = yield fetchFn(configUrl);
2023
+ if (res.ok) {
2024
+ const json = yield res.json();
2025
+ // cache & return
2026
+ _cachedConfig = (_a = json) !== null && _a !== void 0 ? _a : {};
2027
+ return _cachedConfig;
2028
+ }
2029
+ }
2030
+ catch (_d) {
2031
+ /* swallow */
2032
+ }
2033
+ }
2034
+ // 3) Node fallback: try reading from disk (requires your readJsonFile util)
1518
2035
  try {
1519
- return (yield readJsonFile('config.json')) || {};
2036
+ const disk = yield readJsonFile(configUrl);
2037
+ _cachedConfig = disk !== null && disk !== void 0 ? disk : {};
2038
+ return _cachedConfig;
1520
2039
  }
1521
- catch (_a) {
1522
- return {};
2040
+ catch (_e) {
2041
+ /* swallow */
1523
2042
  }
2043
+ // 4) if all else fails, return an empty config
2044
+ _cachedConfig = {};
2045
+ return _cachedConfig;
2046
+ });
2047
+ }
2048
+ function getConfig(key) {
2049
+ return __awaiter(this, void 0, void 0, function* () {
2050
+ const cfg = yield loadConfig();
2051
+ return key != null ? cfg[key] : cfg;
1524
2052
  });
1525
2053
  }
1526
2054
 
@@ -1558,101 +2086,5 @@ function get_keyword_string(keywords) {
1558
2086
  return allString;
1559
2087
  }
1560
2088
 
1561
- // take N args and coerce them all to numbers
1562
- function safeNums(...args) {
1563
- return args.map(ensure_number);
1564
- }
1565
- // divide the first value by each of the following
1566
- function safeDivide(...args) {
1567
- const [head, ...rest] = safeNums(...args);
1568
- // if we don’t have a head or any divisor is zero, bail
1569
- if (head === 0 || rest.some((d) => d === 0))
1570
- return 0;
1571
- return rest.reduce((acc, d) => acc / d, head);
1572
- }
1573
- // multiply all the values together
1574
- function safeMultiply(...args) {
1575
- const nums = safeNums(...args);
1576
- // if any number is zero, result is zero
1577
- if (nums.includes(0))
1578
- return 0;
1579
- return nums.reduce((acc, n) => acc * n, 1);
1580
- }
1581
- // round a value to two decimals by percent
1582
- function roundPercentage(x) {
1583
- const pct = safeMultiply(ensure_number(x), 100);
1584
- return safeDivide(Math.round(pct), 100);
1585
- }
1586
-
1587
- // urlTools.ts
1588
- // Minimal, safe encoders/decoders + helpers to build/parse URLs
1589
- /** Encode a single query value/key safely */
1590
- const encode = (v) => encodeURIComponent(String(v !== null && v !== void 0 ? v : ""));
1591
- /** Decode a single query value/key safely (never throws) */
1592
- const decodeSafe = (v) => {
1593
- if (v == null)
1594
- return "";
1595
- try {
1596
- return decodeURIComponent(v);
1597
- }
1598
- catch (_a) {
1599
- // handles bad % sequences or already-decoded strings
1600
- return v;
1601
- }
1602
- };
1603
- /** Decode strings that might be double-encoded (up to 2 passes) */
1604
- const decodeMaybeDouble = (v) => {
1605
- const once = decodeSafe(v);
1606
- const twice = decodeSafe(once);
1607
- return twice.length < once.length ? twice : once;
1608
- };
1609
- /** Convert + to spaces (legacy www-form behavior) then decode */
1610
- const decodeFormComponent = (v) => decodeSafe(v.replace(/\+/g, " "));
1611
- /** Build a URL with query params (skips null/undefined) */
1612
- const buildUrl = (base, params) => {
1613
- const u = new URL(base, typeof window !== "undefined" ? window.location.origin : "http://localhost");
1614
- if (params) {
1615
- for (const [k, val] of Object.entries(params)) {
1616
- if (val === null || val === undefined)
1617
- continue;
1618
- // arrays -> multiple entries
1619
- if (Array.isArray(val)) {
1620
- val.forEach(v => u.searchParams.append(k, String(v)));
1621
- }
1622
- else {
1623
- u.searchParams.set(k, String(val));
1624
- }
1625
- }
1626
- }
1627
- return u.toString();
1628
- };
1629
- /** Parse a query string into an object (first value wins; arrays if repeat=true) */
1630
- const parseQuery = (qs, opts) => {
1631
- var _a;
1632
- const { repeat = false, form = false } = opts || {};
1633
- const out = {};
1634
- const s = qs.startsWith("?") ? qs.slice(1) : qs;
1635
- if (!s)
1636
- return out;
1637
- for (const part of s.split("&")) {
1638
- if (!part)
1639
- continue;
1640
- const [kRaw, vRaw = ""] = part.split("=");
1641
- const K = form ? decodeFormComponent(kRaw) : decodeSafe(kRaw);
1642
- const V = form ? decodeFormComponent(vRaw) : decodeSafe(vRaw);
1643
- if (repeat) {
1644
- ((_a = out[K]) !== null && _a !== void 0 ? _a : (out[K] = [])).push(V);
1645
- }
1646
- else {
1647
- out[K] = V;
1648
- }
1649
- }
1650
- return out;
1651
- };
1652
- /** Quick helper: percent-encode whole strings for placement in URLs */
1653
- const encodeTextForUrl = (text) => encode(text);
1654
- /** Quick helper: decode long blobs coming from share-intents/UTMs */
1655
- const decodeShareBlob = (blob) => decodeMaybeDouble(blob).replace(/\r\n/g, "\n");
1656
-
1657
- export { API_PREFIX, BASE_URL, Button, Checkbox, DEV_PREFIX, DOMAIN_NAME, Input, MEDIA_TYPES, MIME_TYPES, PROD_PREFIX, PROTOCOL, SUB_DIR, Spinner, alertIt, alertit, assureArray, assureList, assureNumber, assureString, assure_array, assure_list, assure_number, assure_string, buildUrl, callStorage, callWindowMethod, capitalize, capitalize_str, checkResponse, cleanArray, cleanText, confirmType, confirm_type, create_list_string, currentUsername, currentUsernames, decodeFormComponent, decodeJwt, decodeMaybeDouble, decodeSafe, decodeShareBlob, eatAll, eatEnd, eatInner, eatOuter, encode, encodeTextForUrl, ensureArray, ensureList, ensureNumber, ensureString, ensure_array, ensure_list, ensure_number, ensure_string, fetchIndexHtml, fetchIndexHtmlContainer, fetchIt, formatNumber, geAuthsUtilsDirectory, geBackupsUtilsDirectory, geConstantsUtilsDirectory, geEnvUtilsDirectory, geFetchUtilsDirectory, geFileUtilsDirectory, gePathUtilsDirectory, geStaticDirectory, geStringUtilsDirectory, geTypeUtilsDirectory, get, getAbsDir, getAbsPath, getAllFileTypes, getAllFileTypesSync, getAlphaNum, getAlphas, getAuthorizationHeader, getBaseDir, getBody, getChar, getCleanArray, getComponentsUtilsDirectory, getConfigContent, getConfigJson, getConfigVar, getDbConfigsPath, getDistDir, getDocumentProp, getEnvDir, getEnvPath, getFetchVars, getFunctionsDir, getFunctionsUtilsDirectory, getHeaders, getHooksUtilsDirectory, getHtmlDirectory, getLibUtilsDirectory, getMediaExts, getMediaMap, getMethod, getMimeType, getNums, getPublicDir, getResult, getSafeDocument, getSafeLocalStorage, getSafeWindow, getSchemasDirPath, getSchemasPath, getSrcDir, getSubstring, getToken, getWindowHost, getWindowProp, get_all_file_types, get_basename, get_dirname, get_extname, get_filename, get_full_path, get_full_url, get_key_value, get_keyword_string, get_media_exts, get_media_map, get_mime_type, get_relative_path, get_result, get_safe_path, get_splitext, get_window, get_window_location, get_window_parts, get_window_pathname, isLoggedIn, isMediaType, isNum, isStrInString, isTokenExpired, isType, is_media_type, makePath, make_path, make_sanitized_path, normalizeUrl, parseQuery, parseResult, path_to_url, processKeywords, readJsonFile, removeToken, requireToken, roundPercentage, safeDivide, safeGlobalProp, safeMultiply, safeNums, safeStorage, sanitizeFilename, stripPrefixes, truncateString, tryParse, urlJoin, url_to_path };
2089
+ export { API_PREFIX, BASE_URL, Button, Checkbox, DEV_PREFIX, DOMAIN_NAME, Input, MEDIA_TYPES, MIME_TYPES, PROD_PREFIX, PROTOCOL, SUB_DIR, Spinner, alertit, assureArray, assureList, assureNumber, assureString, assure_array, assure_list, assure_number, assure_string, callStorage, callWindowMethod, checkResponse, cleanArray, cleanText, confirmType, confirm_type, create_list_string, currentUsername, currentUsernames, decodeJwt, eatAll, eatEnd, eatInner, eatOuter, ensureArray, ensureList, ensureNumber, ensureString, ensure_array, ensure_list, ensure_number, ensure_string, fetchIndexHtml, fetchIndexHtmlContainer, fetchIt, formatNumber, geAuthsUtilsDirectory, geBackupsUtilsDirectory, geConstantsUtilsDirectory, geEnvUtilsDirectory, geFetchUtilsDirectory, geFileUtilsDirectory, gePathUtilsDirectory, geStaticDirectory, geStringUtilsDirectory, geTypeUtilsDirectory, get, getAbsDir, getAbsPath, getAllFileTypes, getAllFileTypesSync, getAlphaNum, getAlphas, getAuthorizationHeader, getBaseDir, getBody, getChar, getCleanArray, getComponentsUtilsDirectory, getConfig, getConfigContent, getConfigVar, getDbConfigsPath, getDistDir, getDocumentProp, getEnvDir, getEnvPath, getFetchVars, getFunctionsDir, getFunctionsUtilsDirectory, getHeaders, getHooksUtilsDirectory, getHtmlDirectory, getLibUtilsDirectory, getMediaExts, getMediaMap, getMethod, getMimeType, getNums, getPublicDir, getResult, getSafeDocument, getSafeLocalStorage, getSafeWindow, getSchemasDirPath, getSchemasPath, getSrcDir, getSubstring, getToken, getWindowHost, getWindowProp, get_all_file_types, get_basename, get_dirname, get_extname, get_filename, get_full_path, get_full_url, get_key_value, get_keyword_string, get_media_exts, get_media_map, get_mime_type, get_splitext, get_window, get_window_location, get_window_parts, get_window_pathname, isLoggedIn, isMediaType, isNum, isStrInString, isTokenExpired, isType, is_media_type, loadConfig, make_path, make_sanitized_path, normalizeUrl, parseResult, path_to_url, processKeywords, readJsonFile, requireToken, roundPercentage, safeDivide, safeGlobalProp, safeMultiply, safeNums, safeStorage, sanitizeFilename, stripPrefixes, truncateString, tryParse, urlJoin, url_to_path };
1658
2090
  //# sourceMappingURL=index.js.map