@scalar/helpers 0.4.0 → 0.4.2

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 (113) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/array/add-to-map-array.js +7 -8
  3. package/dist/array/is-defined.js +12 -5
  4. package/dist/array/sort-by-order.js +60 -18
  5. package/dist/consts/content-types.js +13 -14
  6. package/dist/dom/freeze-element.js +56 -42
  7. package/dist/dom/scroll-to-id.js +33 -27
  8. package/dist/file/json2xml.js +79 -61
  9. package/dist/general/create-limiter.js +47 -31
  10. package/dist/general/debounce.js +86 -66
  11. package/dist/general/extract-config-secrets.js +29 -27
  12. package/dist/general/has-modifier.js +9 -8
  13. package/dist/general/is-mac-os.d.ts +1 -5
  14. package/dist/general/is-mac-os.d.ts.map +1 -1
  15. package/dist/general/is-mac-os.js +24 -11
  16. package/dist/http/can-method-have-body.js +4 -6
  17. package/dist/http/http-info.js +63 -61
  18. package/dist/http/http-methods.js +4 -7
  19. package/dist/http/http-status-codes.js +316 -320
  20. package/dist/http/is-http-method.js +3 -6
  21. package/dist/http/normalize-http-method.js +19 -19
  22. package/dist/json/escape-json-pointer.js +6 -5
  23. package/dist/json/parse-json-pointer-segments.js +11 -6
  24. package/dist/json/pretty-print-json.d.ts +9 -0
  25. package/dist/json/pretty-print-json.d.ts.map +1 -0
  26. package/dist/json/pretty-print-json.js +42 -0
  27. package/dist/json/unescape-json-pointer.js +7 -5
  28. package/dist/node/path.js +168 -138
  29. package/dist/object/get-value-at-path.js +17 -11
  30. package/dist/object/is-object.js +24 -10
  31. package/dist/object/local-storage.js +50 -42
  32. package/dist/object/object-entries.js +2 -5
  33. package/dist/object/object-keys.js +5 -5
  34. package/dist/object/object-replace.js +13 -12
  35. package/dist/object/omit-undefined-values.js +18 -18
  36. package/dist/object/prevent-pollution.js +27 -10
  37. package/dist/object/to-json-compatible.js +71 -62
  38. package/dist/queue/queue.js +103 -84
  39. package/dist/regex/find-variables.js +13 -8
  40. package/dist/regex/regex-helpers.js +17 -17
  41. package/dist/regex/replace-variables.js +21 -19
  42. package/dist/string/camel-to-title.js +10 -5
  43. package/dist/string/capitalize.js +5 -5
  44. package/dist/string/create-hash.js +19 -16
  45. package/dist/string/generate-hash.js +153 -127
  46. package/dist/string/iterate-title.js +13 -11
  47. package/dist/string/truncate.js +16 -9
  48. package/dist/testing/console-spies.js +19 -24
  49. package/dist/testing/measure.js +42 -19
  50. package/dist/testing/measure.test-d.js +12 -9
  51. package/dist/testing/sleep.js +5 -5
  52. package/dist/url/ensure-protocol.js +8 -10
  53. package/dist/url/extract-server-from-path.js +53 -28
  54. package/dist/url/is-local-url.js +24 -18
  55. package/dist/url/is-relative-path.js +15 -13
  56. package/dist/url/is-valid-url.js +17 -10
  57. package/dist/url/make-url-absolute.js +39 -28
  58. package/dist/url/merge-urls.js +74 -52
  59. package/dist/url/redirect-to-proxy.js +68 -39
  60. package/package.json +5 -9
  61. package/dist/array/add-to-map-array.js.map +0 -7
  62. package/dist/array/is-defined.js.map +0 -7
  63. package/dist/array/sort-by-order.js.map +0 -7
  64. package/dist/consts/content-types.js.map +0 -7
  65. package/dist/dom/freeze-element.js.map +0 -7
  66. package/dist/dom/scroll-to-id.js.map +0 -7
  67. package/dist/file/json2xml.js.map +0 -7
  68. package/dist/general/create-limiter.js.map +0 -7
  69. package/dist/general/debounce.js.map +0 -7
  70. package/dist/general/extract-config-secrets.js.map +0 -7
  71. package/dist/general/has-modifier.js.map +0 -7
  72. package/dist/general/is-mac-os.js.map +0 -7
  73. package/dist/http/can-method-have-body.js.map +0 -7
  74. package/dist/http/http-info.js.map +0 -7
  75. package/dist/http/http-methods.js.map +0 -7
  76. package/dist/http/http-status-codes.js.map +0 -7
  77. package/dist/http/is-http-method.js.map +0 -7
  78. package/dist/http/normalize-http-method.js.map +0 -7
  79. package/dist/json/escape-json-pointer.js.map +0 -7
  80. package/dist/json/parse-json-pointer-segments.js.map +0 -7
  81. package/dist/json/unescape-json-pointer.js.map +0 -7
  82. package/dist/node/path.js.map +0 -7
  83. package/dist/object/get-value-at-path.js.map +0 -7
  84. package/dist/object/is-object.js.map +0 -7
  85. package/dist/object/local-storage.js.map +0 -7
  86. package/dist/object/object-entries.js.map +0 -7
  87. package/dist/object/object-keys.js.map +0 -7
  88. package/dist/object/object-replace.js.map +0 -7
  89. package/dist/object/omit-undefined-values.js.map +0 -7
  90. package/dist/object/prevent-pollution.js.map +0 -7
  91. package/dist/object/to-json-compatible.js.map +0 -7
  92. package/dist/queue/queue.js.map +0 -7
  93. package/dist/regex/find-variables.js.map +0 -7
  94. package/dist/regex/regex-helpers.js.map +0 -7
  95. package/dist/regex/replace-variables.js.map +0 -7
  96. package/dist/string/camel-to-title.js.map +0 -7
  97. package/dist/string/capitalize.js.map +0 -7
  98. package/dist/string/create-hash.js.map +0 -7
  99. package/dist/string/generate-hash.js.map +0 -7
  100. package/dist/string/iterate-title.js.map +0 -7
  101. package/dist/string/truncate.js.map +0 -7
  102. package/dist/testing/console-spies.js.map +0 -7
  103. package/dist/testing/measure.js.map +0 -7
  104. package/dist/testing/measure.test-d.js.map +0 -7
  105. package/dist/testing/sleep.js.map +0 -7
  106. package/dist/url/ensure-protocol.js.map +0 -7
  107. package/dist/url/extract-server-from-path.js.map +0 -7
  108. package/dist/url/is-local-url.js.map +0 -7
  109. package/dist/url/is-relative-path.js.map +0 -7
  110. package/dist/url/is-valid-url.js.map +0 -7
  111. package/dist/url/make-url-absolute.js.map +0 -7
  112. package/dist/url/merge-urls.js.map +0 -7
  113. package/dist/url/redirect-to-proxy.js.map +0 -7
@@ -1,130 +1,156 @@
1
- const generateHash = (input) => {
2
- const seed = 0;
3
- let h1 = seed;
4
- let h2 = seed;
5
- const len = input.length;
6
- const remainder = len & 15;
7
- const bytes = len - remainder;
8
- const c1 = 2277735313;
9
- const c2 = 1291169091;
10
- const c3 = 1390208809;
11
- const c4 = 944331445;
12
- for (let i = 0; i < bytes; i += 16) {
13
- let k1 = input.charCodeAt(i) & 255 | (input.charCodeAt(i + 1) & 255) << 8 | (input.charCodeAt(i + 2) & 255) << 16 | (input.charCodeAt(i + 3) & 255) << 24;
14
- let k2 = input.charCodeAt(i + 4) & 255 | (input.charCodeAt(i + 5) & 255) << 8 | (input.charCodeAt(i + 6) & 255) << 16 | (input.charCodeAt(i + 7) & 255) << 24;
15
- let k3 = input.charCodeAt(i + 8) & 255 | (input.charCodeAt(i + 9) & 255) << 8 | (input.charCodeAt(i + 10) & 255) << 16 | (input.charCodeAt(i + 11) & 255) << 24;
16
- let k4 = input.charCodeAt(i + 12) & 255 | (input.charCodeAt(i + 13) & 255) << 8 | (input.charCodeAt(i + 14) & 255) << 16 | (input.charCodeAt(i + 15) & 255) << 24;
17
- k1 = Math.imul(k1, c1);
18
- k1 = k1 << 15 | k1 >>> 17;
19
- k1 = Math.imul(k1, c2);
20
- h1 ^= k1;
21
- h1 = h1 << 13 | h1 >>> 19;
22
- h1 = Math.imul(h1, 5) + 3864292196;
23
- k2 = Math.imul(k2, c2);
24
- k2 = k2 << 16 | k2 >>> 16;
25
- k2 = Math.imul(k2, c3);
26
- h2 ^= k2;
27
- h2 = h2 << 17 | h2 >>> 15;
28
- h2 = Math.imul(h2, 5) + 461845907;
29
- k3 = Math.imul(k3, c3);
30
- k3 = k3 << 17 | k3 >>> 15;
31
- k3 = Math.imul(k3, c4);
32
- h1 ^= k3;
33
- h1 = h1 << 15 | h1 >>> 17;
34
- h1 = Math.imul(h1, 5) + 1390208809;
35
- k4 = Math.imul(k4, c4);
36
- k4 = k4 << 18 | k4 >>> 14;
37
- k4 = Math.imul(k4, c1);
38
- h2 ^= k4;
39
- h2 = h2 << 13 | h2 >>> 19;
40
- h2 = Math.imul(h2, 5) + 944331445;
41
- }
42
- if (remainder > 0) {
43
- let k1 = 0;
44
- let k2 = 0;
45
- let k3 = 0;
46
- let k4 = 0;
47
- if (remainder >= 15) {
48
- k4 ^= (input.charCodeAt(bytes + 14) & 255) << 16;
1
+ /**
2
+ * MurmurHash3 implementation
3
+ *
4
+ * Generate a hash from a string using the MurmurHash3 algorithm
5
+ * Provides 64-bit hash output with excellent speed and distribution
6
+ *
7
+ * We had to move away from xxhash-wasm since it was causing issues with content security policy (CSP) violations.
8
+ *
9
+ * We cannot use crypto.subtle because it is only available in secure contexts (HTTPS) or on localhost.
10
+ *
11
+ * @param input - The string to hash
12
+ * @returns The 64-bit hash of the input string as a 16-character hex string
13
+ */
14
+ export const generateHash = (input) => {
15
+ const seed = 0;
16
+ // Working with 64-bit values using pairs of 32-bit integers
17
+ let h1 = seed;
18
+ let h2 = seed;
19
+ const len = input.length;
20
+ const remainder = len & 15; // len % 16
21
+ const bytes = len - remainder;
22
+ const c1 = 0x87c37b91;
23
+ const c2 = 0x4cf5ad43;
24
+ const c3 = 0x52dce729;
25
+ const c4 = 0x38495ab5;
26
+ // Process 16-byte chunks
27
+ for (let i = 0; i < bytes; i += 16) {
28
+ let k1 = (input.charCodeAt(i) & 0xff) |
29
+ ((input.charCodeAt(i + 1) & 0xff) << 8) |
30
+ ((input.charCodeAt(i + 2) & 0xff) << 16) |
31
+ ((input.charCodeAt(i + 3) & 0xff) << 24);
32
+ let k2 = (input.charCodeAt(i + 4) & 0xff) |
33
+ ((input.charCodeAt(i + 5) & 0xff) << 8) |
34
+ ((input.charCodeAt(i + 6) & 0xff) << 16) |
35
+ ((input.charCodeAt(i + 7) & 0xff) << 24);
36
+ let k3 = (input.charCodeAt(i + 8) & 0xff) |
37
+ ((input.charCodeAt(i + 9) & 0xff) << 8) |
38
+ ((input.charCodeAt(i + 10) & 0xff) << 16) |
39
+ ((input.charCodeAt(i + 11) & 0xff) << 24);
40
+ let k4 = (input.charCodeAt(i + 12) & 0xff) |
41
+ ((input.charCodeAt(i + 13) & 0xff) << 8) |
42
+ ((input.charCodeAt(i + 14) & 0xff) << 16) |
43
+ ((input.charCodeAt(i + 15) & 0xff) << 24);
44
+ k1 = Math.imul(k1, c1);
45
+ k1 = (k1 << 15) | (k1 >>> 17);
46
+ k1 = Math.imul(k1, c2);
47
+ h1 ^= k1;
48
+ h1 = (h1 << 13) | (h1 >>> 19);
49
+ h1 = Math.imul(h1, 5) + 0xe6546b64;
50
+ k2 = Math.imul(k2, c2);
51
+ k2 = (k2 << 16) | (k2 >>> 16);
52
+ k2 = Math.imul(k2, c3);
53
+ h2 ^= k2;
54
+ h2 = (h2 << 17) | (h2 >>> 15);
55
+ h2 = Math.imul(h2, 5) + 0x1b873593;
56
+ k3 = Math.imul(k3, c3);
57
+ k3 = (k3 << 17) | (k3 >>> 15);
58
+ k3 = Math.imul(k3, c4);
59
+ h1 ^= k3;
60
+ h1 = (h1 << 15) | (h1 >>> 17);
61
+ h1 = Math.imul(h1, 5) + 0x52dce729;
62
+ k4 = Math.imul(k4, c4);
63
+ k4 = (k4 << 18) | (k4 >>> 14);
64
+ k4 = Math.imul(k4, c1);
65
+ h2 ^= k4;
66
+ h2 = (h2 << 13) | (h2 >>> 19);
67
+ h2 = Math.imul(h2, 5) + 0x38495ab5;
49
68
  }
50
- if (remainder >= 14) {
51
- k4 ^= (input.charCodeAt(bytes + 13) & 255) << 8;
69
+ // Process remaining bytes
70
+ if (remainder > 0) {
71
+ let k1 = 0;
72
+ let k2 = 0;
73
+ let k3 = 0;
74
+ let k4 = 0;
75
+ if (remainder >= 15) {
76
+ k4 ^= (input.charCodeAt(bytes + 14) & 0xff) << 16;
77
+ }
78
+ if (remainder >= 14) {
79
+ k4 ^= (input.charCodeAt(bytes + 13) & 0xff) << 8;
80
+ }
81
+ if (remainder >= 13) {
82
+ k4 ^= input.charCodeAt(bytes + 12) & 0xff;
83
+ k4 = Math.imul(k4, c4);
84
+ k4 = (k4 << 18) | (k4 >>> 14);
85
+ k4 = Math.imul(k4, c1);
86
+ h2 ^= k4;
87
+ }
88
+ if (remainder >= 12) {
89
+ k3 ^= (input.charCodeAt(bytes + 11) & 0xff) << 24;
90
+ }
91
+ if (remainder >= 11) {
92
+ k3 ^= (input.charCodeAt(bytes + 10) & 0xff) << 16;
93
+ }
94
+ if (remainder >= 10) {
95
+ k3 ^= (input.charCodeAt(bytes + 9) & 0xff) << 8;
96
+ }
97
+ if (remainder >= 9) {
98
+ k3 ^= input.charCodeAt(bytes + 8) & 0xff;
99
+ k3 = Math.imul(k3, c3);
100
+ k3 = (k3 << 17) | (k3 >>> 15);
101
+ k3 = Math.imul(k3, c4);
102
+ h1 ^= k3;
103
+ }
104
+ if (remainder >= 8) {
105
+ k2 ^= (input.charCodeAt(bytes + 7) & 0xff) << 24;
106
+ }
107
+ if (remainder >= 7) {
108
+ k2 ^= (input.charCodeAt(bytes + 6) & 0xff) << 16;
109
+ }
110
+ if (remainder >= 6) {
111
+ k2 ^= (input.charCodeAt(bytes + 5) & 0xff) << 8;
112
+ }
113
+ if (remainder >= 5) {
114
+ k2 ^= input.charCodeAt(bytes + 4) & 0xff;
115
+ k2 = Math.imul(k2, c2);
116
+ k2 = (k2 << 16) | (k2 >>> 16);
117
+ k2 = Math.imul(k2, c3);
118
+ h2 ^= k2;
119
+ }
120
+ if (remainder >= 4) {
121
+ k1 ^= (input.charCodeAt(bytes + 3) & 0xff) << 24;
122
+ }
123
+ if (remainder >= 3) {
124
+ k1 ^= (input.charCodeAt(bytes + 2) & 0xff) << 16;
125
+ }
126
+ if (remainder >= 2) {
127
+ k1 ^= (input.charCodeAt(bytes + 1) & 0xff) << 8;
128
+ }
129
+ if (remainder >= 1) {
130
+ k1 ^= input.charCodeAt(bytes) & 0xff;
131
+ k1 = Math.imul(k1, c1);
132
+ k1 = (k1 << 15) | (k1 >>> 17);
133
+ k1 = Math.imul(k1, c2);
134
+ h1 ^= k1;
135
+ }
52
136
  }
53
- if (remainder >= 13) {
54
- k4 ^= input.charCodeAt(bytes + 12) & 255;
55
- k4 = Math.imul(k4, c4);
56
- k4 = k4 << 18 | k4 >>> 14;
57
- k4 = Math.imul(k4, c1);
58
- h2 ^= k4;
59
- }
60
- if (remainder >= 12) {
61
- k3 ^= (input.charCodeAt(bytes + 11) & 255) << 24;
62
- }
63
- if (remainder >= 11) {
64
- k3 ^= (input.charCodeAt(bytes + 10) & 255) << 16;
65
- }
66
- if (remainder >= 10) {
67
- k3 ^= (input.charCodeAt(bytes + 9) & 255) << 8;
68
- }
69
- if (remainder >= 9) {
70
- k3 ^= input.charCodeAt(bytes + 8) & 255;
71
- k3 = Math.imul(k3, c3);
72
- k3 = k3 << 17 | k3 >>> 15;
73
- k3 = Math.imul(k3, c4);
74
- h1 ^= k3;
75
- }
76
- if (remainder >= 8) {
77
- k2 ^= (input.charCodeAt(bytes + 7) & 255) << 24;
78
- }
79
- if (remainder >= 7) {
80
- k2 ^= (input.charCodeAt(bytes + 6) & 255) << 16;
81
- }
82
- if (remainder >= 6) {
83
- k2 ^= (input.charCodeAt(bytes + 5) & 255) << 8;
84
- }
85
- if (remainder >= 5) {
86
- k2 ^= input.charCodeAt(bytes + 4) & 255;
87
- k2 = Math.imul(k2, c2);
88
- k2 = k2 << 16 | k2 >>> 16;
89
- k2 = Math.imul(k2, c3);
90
- h2 ^= k2;
91
- }
92
- if (remainder >= 4) {
93
- k1 ^= (input.charCodeAt(bytes + 3) & 255) << 24;
94
- }
95
- if (remainder >= 3) {
96
- k1 ^= (input.charCodeAt(bytes + 2) & 255) << 16;
97
- }
98
- if (remainder >= 2) {
99
- k1 ^= (input.charCodeAt(bytes + 1) & 255) << 8;
100
- }
101
- if (remainder >= 1) {
102
- k1 ^= input.charCodeAt(bytes) & 255;
103
- k1 = Math.imul(k1, c1);
104
- k1 = k1 << 15 | k1 >>> 17;
105
- k1 = Math.imul(k1, c2);
106
- h1 ^= k1;
107
- }
108
- }
109
- h1 ^= len;
110
- h2 ^= len;
111
- h1 += h2;
112
- h2 += h1;
113
- h1 ^= h1 >>> 16;
114
- h1 = Math.imul(h1, 2246822507);
115
- h1 ^= h1 >>> 13;
116
- h1 = Math.imul(h1, 3266489909);
117
- h1 ^= h1 >>> 16;
118
- h2 ^= h2 >>> 16;
119
- h2 = Math.imul(h2, 2246822507);
120
- h2 ^= h2 >>> 13;
121
- h2 = Math.imul(h2, 3266489909);
122
- h2 ^= h2 >>> 16;
123
- h1 += h2;
124
- h2 += h1;
125
- return (h1 >>> 0).toString(16).padStart(8, "0") + (h2 >>> 0).toString(16).padStart(8, "0");
126
- };
127
- export {
128
- generateHash
137
+ // Finalization
138
+ h1 ^= len;
139
+ h2 ^= len;
140
+ h1 += h2;
141
+ h2 += h1;
142
+ h1 ^= h1 >>> 16;
143
+ h1 = Math.imul(h1, 0x85ebca6b);
144
+ h1 ^= h1 >>> 13;
145
+ h1 = Math.imul(h1, 0xc2b2ae35);
146
+ h1 ^= h1 >>> 16;
147
+ h2 ^= h2 >>> 16;
148
+ h2 = Math.imul(h2, 0x85ebca6b);
149
+ h2 ^= h2 >>> 13;
150
+ h2 = Math.imul(h2, 0xc2b2ae35);
151
+ h2 ^= h2 >>> 16;
152
+ h1 += h2;
153
+ h2 += h1;
154
+ // Return 64-bit hash as hex string (two 32-bit values concatenated)
155
+ return (h1 >>> 0).toString(16).padStart(8, '0') + (h2 >>> 0).toString(16).padStart(8, '0');
129
156
  };
130
- //# sourceMappingURL=generate-hash.js.map
@@ -1,12 +1,14 @@
1
- const iterateTitle = (title, checkDuplicates, separator = " #") => {
2
- if (!checkDuplicates(title)) {
3
- return title;
4
- }
5
- const split = title.split(separator);
6
- const newTitle = split.length > 1 ? `${split.slice(0, -1).join()}${separator}${Number(split.at(-1)) + 1}` : `${split.join()}${separator}2`;
7
- return iterateTitle(newTitle, checkDuplicates, separator);
1
+ /**
2
+ * Check for duplicate titles, and iterate title
3
+ */
4
+ export const iterateTitle = (title, checkDuplicates, separator = ' #') => {
5
+ // If the title is not a duplicate return
6
+ if (!checkDuplicates(title)) {
7
+ return title;
8
+ }
9
+ const split = title.split(separator);
10
+ const newTitle = split.length > 1
11
+ ? `${split.slice(0, -1).join()}${separator}${Number(split.at(-1)) + 1}`
12
+ : `${split.join()}${separator}2`;
13
+ return iterateTitle(newTitle, checkDuplicates, separator);
8
14
  };
9
- export {
10
- iterateTitle
11
- };
12
- //# sourceMappingURL=iterate-title.js.map
@@ -1,10 +1,17 @@
1
- const truncate = (str, maxLength = 18) => {
2
- if (str.length <= maxLength) {
3
- return str;
4
- }
5
- return str.slice(0, maxLength) + "\u2026";
1
+ /**
2
+ * Truncates a string to a specified length and adds an ellipsis if it's longer in JS
3
+ *
4
+ * @param str - The string to truncate
5
+ * @param maxLength - The maximum length before truncation (default: 18)
6
+ * @returns The truncated string with ellipsis if needed
7
+ *
8
+ * @example
9
+ * truncate('Very long name that needs truncation') // 'Very long name th…'
10
+ * truncate('Short') // 'Short'
11
+ */
12
+ export const truncate = (str, maxLength = 18) => {
13
+ if (str.length <= maxLength) {
14
+ return str;
15
+ }
16
+ return str.slice(0, maxLength) + '…';
6
17
  };
7
- export {
8
- truncate
9
- };
10
- //# sourceMappingURL=truncate.js.map
@@ -1,25 +1,20 @@
1
- import { vi } from "vitest";
2
- const consoleWarnSpy = vi.spyOn(console, "warn");
3
- let isConsoleWarnEnabled = false;
4
- const consoleErrorSpy = vi.spyOn(console, "error");
5
- let isConsoleErrorEnabled = false;
6
- const resetConsoleSpies = () => {
7
- consoleWarnSpy.mockClear();
8
- consoleErrorSpy.mockClear();
1
+ import { vi } from 'vitest';
2
+ /** Spy on console.warn */
3
+ export const consoleWarnSpy = vi.spyOn(console, 'warn');
4
+ export let isConsoleWarnEnabled = false;
5
+ /** Spy on console.error */
6
+ export const consoleErrorSpy = vi.spyOn(console, 'error');
7
+ export let isConsoleErrorEnabled = false;
8
+ /** Reset the spies */
9
+ export const resetConsoleSpies = () => {
10
+ consoleWarnSpy.mockClear();
11
+ consoleErrorSpy.mockClear();
9
12
  };
10
- const enableConsoleWarn = () => isConsoleWarnEnabled = true;
11
- const disableConsoleWarn = () => isConsoleWarnEnabled = false;
12
- const enableConsoleError = () => isConsoleErrorEnabled = true;
13
- const disableConsoleError = () => isConsoleErrorEnabled = false;
14
- export {
15
- consoleErrorSpy,
16
- consoleWarnSpy,
17
- disableConsoleError,
18
- disableConsoleWarn,
19
- enableConsoleError,
20
- enableConsoleWarn,
21
- isConsoleErrorEnabled,
22
- isConsoleWarnEnabled,
23
- resetConsoleSpies
24
- };
25
- //# sourceMappingURL=console-spies.js.map
13
+ /** Helper to re-enable console warn checks */
14
+ export const enableConsoleWarn = () => (isConsoleWarnEnabled = true);
15
+ /** Helper to disable console warn checks */
16
+ export const disableConsoleWarn = () => (isConsoleWarnEnabled = false);
17
+ /** Helper to enable console error checks */
18
+ export const enableConsoleError = () => (isConsoleErrorEnabled = true);
19
+ /** Helper to disable console error checks */
20
+ export const disableConsoleError = () => (isConsoleErrorEnabled = false);
@@ -1,21 +1,44 @@
1
- const measureSync = (name, fn) => {
2
- const start = performance.now();
3
- const result = fn();
4
- const end = performance.now();
5
- const duration = Math.round(end - start);
6
- console.info(`${name}: ${duration} ms`);
7
- return result;
1
+ /**
2
+ * Measures the execution time of a function and logs it.
3
+ *
4
+ * Works only with sync functions and returns the result of the measured function.
5
+ *
6
+ * @example
7
+ *
8
+ * ```ts
9
+ * // Sync function
10
+ * const result = measureSync('computation', () => {
11
+ * return heavyComputation()
12
+ * })
13
+ * ```
14
+ */
15
+ export const measureSync = (name, fn) => {
16
+ const start = performance.now();
17
+ const result = fn();
18
+ const end = performance.now();
19
+ const duration = Math.round(end - start);
20
+ console.info(`${name}: ${duration} ms`);
21
+ return result;
8
22
  };
9
- const measureAsync = async (name, fn) => {
10
- const start = performance.now();
11
- const result = await fn();
12
- const end = performance.now();
13
- const duration = Math.round(end - start);
14
- console.info(`${name}: ${duration} ms`);
15
- return result;
23
+ /**
24
+ * Measures the execution time of an async function and logs it.
25
+ *
26
+ * Works only with async functions and returns the result of the measured function.
27
+ *
28
+ * @example
29
+ *
30
+ * ```ts
31
+ * // Async function
32
+ * const result = await measure('api-call', async () => {
33
+ * return await fetchData()
34
+ * })
35
+ * ````
36
+ */
37
+ export const measureAsync = async (name, fn) => {
38
+ const start = performance.now();
39
+ const result = await fn();
40
+ const end = performance.now();
41
+ const duration = Math.round(end - start);
42
+ console.info(`${name}: ${duration} ms`);
43
+ return result;
16
44
  };
17
- export {
18
- measureAsync,
19
- measureSync
20
- };
21
- //# sourceMappingURL=measure.js.map
@@ -1,12 +1,15 @@
1
- import { describe, vi } from "vitest";
2
- import { measureAsync, measureSync } from "./measure.js";
1
+ import { describe, vi } from 'vitest';
2
+ import { measureAsync, measureSync } from './measure.js';
3
3
  const asyncFunction = vi.fn();
4
- describe("measureAsync types", async () => {
5
- await measureAsync("test", asyncFunction);
6
- await measureAsync("test", () => 1);
4
+ describe('measureAsync types', async () => {
5
+ // works with async methods
6
+ await measureAsync('test', asyncFunction);
7
+ // @ts-expect-error should error because `fn` doesn't return a Promise
8
+ await measureAsync('test', () => 1);
7
9
  });
8
- describe("measureSync types", () => {
9
- measureSync("test", () => 1);
10
- measureSync("test", asyncFunction);
10
+ describe('measureSync types', () => {
11
+ // works with sync methods
12
+ measureSync('test', () => 1);
13
+ // @ts-expect-error should error because `fn` doesn't return a Promise
14
+ measureSync('test', asyncFunction);
11
15
  });
12
- //# sourceMappingURL=measure.test-d.js.map
@@ -1,5 +1,5 @@
1
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
2
- export {
3
- sleep
4
- };
5
- //# sourceMappingURL=sleep.js.map
1
+ /**
2
+ * Little helper for sleeping for x milliseconds
3
+ * an async await friendly setTimeout
4
+ */
5
+ export const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
@@ -1,11 +1,9 @@
1
- import { REGEX } from "../regex/regex-helpers.js";
2
- function ensureProtocol(url) {
3
- if (REGEX.PROTOCOL.test(url)) {
4
- return url;
5
- }
6
- return `http://${url.replace(/^\//, "")}`;
1
+ import { REGEX } from '../regex/regex-helpers.js';
2
+ /** Ensure URL has a protocol prefix */
3
+ export function ensureProtocol(url) {
4
+ if (REGEX.PROTOCOL.test(url)) {
5
+ return url;
6
+ }
7
+ // Default to http if no protocol is specified
8
+ return `http://${url.replace(/^\//, '')}`;
7
9
  }
8
- export {
9
- ensureProtocol
10
- };
11
- //# sourceMappingURL=ensure-protocol.js.map
@@ -1,32 +1,57 @@
1
- const extractServerFromPath = (path = "") => {
2
- if (!path.trim()) {
3
- return null;
4
- }
5
- if (path.startsWith("//")) {
6
- try {
7
- const url = new URL(`https:${path}`);
8
- if (url.origin === "null") {
1
+ /**
2
+ * Extracts the server from a string, used to check for servers in paths during migration
3
+ *
4
+ * @param path - The URL string to parse. If no protocol is provided, the URL API will throw an error.
5
+ * @returns A tuple of [origin, remainingPath] or null if the input is empty, whitespace-only, or invalid.
6
+ *
7
+ * @example
8
+ * extractServer('https://api.example.com/v1/users?id=123')
9
+ * // Returns: ['https://api.example.com', '/v1/users?id=123']
10
+ *
11
+ * @example
12
+ * extractServer('/users')
13
+ * // Returns: null
14
+ *
15
+ * @example
16
+ * extractServer('/users')
17
+ * // Returns: null
18
+ *
19
+ * @example
20
+ * extractServer('//api.example.com/v1/users')
21
+ * // Returns: ['//api.example.com', '/v1/users']
22
+ */
23
+ export const extractServerFromPath = (path = '') => {
24
+ if (!path.trim()) {
9
25
  return null;
10
- }
11
- const origin = url.origin.replace(/^https?:/, "");
12
- const remainingPath = decodeURIComponent(url.pathname) + url.search + url.hash;
13
- return [origin, remainingPath];
14
- } catch {
15
- return null;
16
26
  }
17
- }
18
- try {
19
- const url = new URL(path);
20
- if (url.origin === "null") {
21
- return null;
27
+ /** Handle protocol-relative URLs (e.g., "//api.example.com") */
28
+ if (path.startsWith('//')) {
29
+ try {
30
+ /** Use dummy protocol to parse, then strip it */
31
+ const url = new URL(`https:${path}`);
32
+ if (url.origin === 'null') {
33
+ return null;
34
+ }
35
+ const origin = url.origin.replace(/^https?:/, '');
36
+ /** Decode pathname to preserve OpenAPI template variables like {userId} */
37
+ const remainingPath = decodeURIComponent(url.pathname) + url.search + url.hash;
38
+ return [origin, remainingPath];
39
+ }
40
+ catch {
41
+ return null;
42
+ }
43
+ }
44
+ try {
45
+ const url = new URL(path);
46
+ /** URL API returns "null" for file:// and other invalid protocols */
47
+ if (url.origin === 'null') {
48
+ return null;
49
+ }
50
+ /** Decode pathname to preserve OpenAPI template variables like {userId} */
51
+ const remainingPath = decodeURIComponent(url.pathname) + url.search + url.hash;
52
+ return [url.origin, remainingPath];
53
+ }
54
+ catch {
55
+ return null;
22
56
  }
23
- const remainingPath = decodeURIComponent(url.pathname) + url.search + url.hash;
24
- return [url.origin, remainingPath];
25
- } catch {
26
- return null;
27
- }
28
- };
29
- export {
30
- extractServerFromPath
31
57
  };
32
- //# sourceMappingURL=extract-server-from-path.js.map
@@ -1,21 +1,27 @@
1
- const LOCAL_HOSTNAMES = ["localhost", "127.0.0.1", "[::1]", "0.0.0.0"];
2
- const RESERVED_TLDS = ["test", "example", "invalid", "localhost"];
3
- function isLocalUrl(url) {
4
- try {
5
- const { hostname } = new URL(url);
6
- if (LOCAL_HOSTNAMES.includes(hostname)) {
7
- return true;
1
+ /** Obviously local hostnames */
2
+ const LOCAL_HOSTNAMES = ['localhost', '127.0.0.1', '[::1]', '0.0.0.0'];
3
+ /** Reserved TLDs that are guaranteed to never be assigned */
4
+ const RESERVED_TLDS = ['test', 'example', 'invalid', 'localhost'];
5
+ /**
6
+ * Detect requests to localhost or reserved TLDs
7
+ */
8
+ export function isLocalUrl(url) {
9
+ try {
10
+ const { hostname } = new URL(url);
11
+ // Check if hostname is in the local hostnames list
12
+ if (LOCAL_HOSTNAMES.includes(hostname)) {
13
+ return true;
14
+ }
15
+ // Check if hostname ends with a reserved TLD
16
+ const tld = hostname.split('.').pop();
17
+ if (tld && RESERVED_TLDS.includes(tld)) {
18
+ return true;
19
+ }
20
+ return false;
8
21
  }
9
- const tld = hostname.split(".").pop();
10
- if (tld && RESERVED_TLDS.includes(tld)) {
11
- return true;
22
+ catch {
23
+ // If it's not a valid URL, we can't use the proxy anyway,
24
+ // but it also covers cases like relative URLs (e.g. `openapi.json`).
25
+ return true;
12
26
  }
13
- return false;
14
- } catch {
15
- return true;
16
- }
17
27
  }
18
- export {
19
- isLocalUrl
20
- };
21
- //# sourceMappingURL=is-local-url.js.map