@scalar/helpers 0.4.1 → 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.
- package/CHANGELOG.md +6 -0
- package/dist/array/add-to-map-array.js +7 -8
- package/dist/array/is-defined.js +12 -5
- package/dist/array/sort-by-order.js +60 -18
- package/dist/consts/content-types.js +13 -14
- package/dist/dom/freeze-element.js +56 -42
- package/dist/dom/scroll-to-id.js +33 -27
- package/dist/file/json2xml.js +79 -61
- package/dist/general/create-limiter.js +47 -31
- package/dist/general/debounce.js +86 -66
- package/dist/general/extract-config-secrets.js +29 -27
- package/dist/general/has-modifier.js +9 -8
- package/dist/general/is-mac-os.js +23 -21
- package/dist/http/can-method-have-body.js +4 -6
- package/dist/http/http-info.js +63 -61
- package/dist/http/http-methods.js +4 -7
- package/dist/http/http-status-codes.js +316 -320
- package/dist/http/is-http-method.js +3 -6
- package/dist/http/normalize-http-method.js +19 -19
- package/dist/json/escape-json-pointer.js +6 -5
- package/dist/json/parse-json-pointer-segments.js +11 -6
- package/dist/json/pretty-print-json.d.ts +9 -0
- package/dist/json/pretty-print-json.d.ts.map +1 -0
- package/dist/json/pretty-print-json.js +42 -0
- package/dist/json/unescape-json-pointer.js +7 -5
- package/dist/node/path.js +168 -138
- package/dist/object/get-value-at-path.js +17 -11
- package/dist/object/is-object.js +24 -10
- package/dist/object/local-storage.js +50 -42
- package/dist/object/object-entries.js +2 -5
- package/dist/object/object-keys.js +5 -5
- package/dist/object/object-replace.js +13 -12
- package/dist/object/omit-undefined-values.js +18 -18
- package/dist/object/prevent-pollution.js +27 -10
- package/dist/object/to-json-compatible.js +71 -62
- package/dist/queue/queue.js +103 -84
- package/dist/regex/find-variables.js +13 -8
- package/dist/regex/regex-helpers.js +17 -17
- package/dist/regex/replace-variables.js +21 -19
- package/dist/string/camel-to-title.js +10 -5
- package/dist/string/capitalize.js +5 -5
- package/dist/string/create-hash.js +19 -16
- package/dist/string/generate-hash.js +153 -127
- package/dist/string/iterate-title.js +13 -11
- package/dist/string/truncate.js +16 -9
- package/dist/testing/console-spies.js +19 -24
- package/dist/testing/measure.js +42 -19
- package/dist/testing/measure.test-d.js +12 -9
- package/dist/testing/sleep.js +5 -5
- package/dist/url/ensure-protocol.js +8 -10
- package/dist/url/extract-server-from-path.js +53 -28
- package/dist/url/is-local-url.js +24 -18
- package/dist/url/is-relative-path.js +15 -13
- package/dist/url/is-valid-url.js +17 -10
- package/dist/url/make-url-absolute.js +39 -28
- package/dist/url/merge-urls.js +74 -52
- package/dist/url/redirect-to-proxy.js +68 -39
- package/package.json +5 -9
- package/dist/array/add-to-map-array.js.map +0 -7
- package/dist/array/is-defined.js.map +0 -7
- package/dist/array/sort-by-order.js.map +0 -7
- package/dist/consts/content-types.js.map +0 -7
- package/dist/dom/freeze-element.js.map +0 -7
- package/dist/dom/scroll-to-id.js.map +0 -7
- package/dist/file/json2xml.js.map +0 -7
- package/dist/general/create-limiter.js.map +0 -7
- package/dist/general/debounce.js.map +0 -7
- package/dist/general/extract-config-secrets.js.map +0 -7
- package/dist/general/has-modifier.js.map +0 -7
- package/dist/general/is-mac-os.js.map +0 -7
- package/dist/http/can-method-have-body.js.map +0 -7
- package/dist/http/http-info.js.map +0 -7
- package/dist/http/http-methods.js.map +0 -7
- package/dist/http/http-status-codes.js.map +0 -7
- package/dist/http/is-http-method.js.map +0 -7
- package/dist/http/normalize-http-method.js.map +0 -7
- package/dist/json/escape-json-pointer.js.map +0 -7
- package/dist/json/parse-json-pointer-segments.js.map +0 -7
- package/dist/json/unescape-json-pointer.js.map +0 -7
- package/dist/node/path.js.map +0 -7
- package/dist/object/get-value-at-path.js.map +0 -7
- package/dist/object/is-object.js.map +0 -7
- package/dist/object/local-storage.js.map +0 -7
- package/dist/object/object-entries.js.map +0 -7
- package/dist/object/object-keys.js.map +0 -7
- package/dist/object/object-replace.js.map +0 -7
- package/dist/object/omit-undefined-values.js.map +0 -7
- package/dist/object/prevent-pollution.js.map +0 -7
- package/dist/object/to-json-compatible.js.map +0 -7
- package/dist/queue/queue.js.map +0 -7
- package/dist/regex/find-variables.js.map +0 -7
- package/dist/regex/regex-helpers.js.map +0 -7
- package/dist/regex/replace-variables.js.map +0 -7
- package/dist/string/camel-to-title.js.map +0 -7
- package/dist/string/capitalize.js.map +0 -7
- package/dist/string/create-hash.js.map +0 -7
- package/dist/string/generate-hash.js.map +0 -7
- package/dist/string/iterate-title.js.map +0 -7
- package/dist/string/truncate.js.map +0 -7
- package/dist/testing/console-spies.js.map +0 -7
- package/dist/testing/measure.js.map +0 -7
- package/dist/testing/measure.test-d.js.map +0 -7
- package/dist/testing/sleep.js.map +0 -7
- package/dist/url/ensure-protocol.js.map +0 -7
- package/dist/url/extract-server-from-path.js.map +0 -7
- package/dist/url/is-local-url.js.map +0 -7
- package/dist/url/is-relative-path.js.map +0 -7
- package/dist/url/is-valid-url.js.map +0 -7
- package/dist/url/make-url-absolute.js.map +0 -7
- package/dist/url/merge-urls.js.map +0 -7
- package/dist/url/redirect-to-proxy.js.map +0 -7
|
@@ -1,130 +1,156 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
package/dist/string/truncate.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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);
|
package/dist/testing/measure.js
CHANGED
|
@@ -1,21 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
|
2
|
-
import { measureAsync, measureSync } from
|
|
1
|
+
import { describe, vi } from 'vitest';
|
|
2
|
+
import { measureAsync, measureSync } from './measure.js';
|
|
3
3
|
const asyncFunction = vi.fn();
|
|
4
|
-
describe(
|
|
5
|
-
|
|
6
|
-
|
|
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(
|
|
9
|
-
|
|
10
|
-
|
|
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
|
package/dist/testing/sleep.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
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
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
package/dist/url/is-local-url.js
CHANGED
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|