@vbarbarosh/node-helpers 3.74.0 → 3.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/browser.js +2 -2
- package/package.json +1 -1
- package/src/cache.js +15 -0
- package/src/cache.md +9 -0
- package/src/urlmod.test.js +5 -0
- package/src/urlparts.js +20 -0
- package/src/urlparts.test.js +294 -0
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ npm install @vbarbarosh/node-helpers
|
|
|
20
20
|
A subset of `@vbarbarosh/node-helpers` is available for browser:
|
|
21
21
|
|
|
22
22
|
```html
|
|
23
|
-
<script src="https://unpkg.com/@vbarbarosh/node-helpers@3.
|
|
23
|
+
<script src="https://unpkg.com/@vbarbarosh/node-helpers@3.75.0/dist/browser.js"></script>
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
⚠️ All browser functions are exposed globally.
|
package/dist/browser.js
CHANGED
|
@@ -2484,10 +2484,10 @@ var __webpack_exports__ = {};
|
|
|
2484
2484
|
\******************************/
|
|
2485
2485
|
const ns = new URL(document.currentScript.src).searchParams.get('var') ?? 'h';
|
|
2486
2486
|
if (typeof window[ns] !== 'undefined') {
|
|
2487
|
-
console.log(`❌ @vbarbarosh/node-helpers@${"3.
|
|
2487
|
+
console.log(`❌ @vbarbarosh/node-helpers@${"3.75.0"} was not injected — window.${ns} is already in use`);
|
|
2488
2488
|
}
|
|
2489
2489
|
else {
|
|
2490
|
-
console.log(`🎉 @vbarbarosh/node-helpers@${"3.
|
|
2490
|
+
console.log(`🎉 @vbarbarosh/node-helpers@${"3.75.0"} successfully exposed as window.${ns}`);
|
|
2491
2491
|
window[ns] = {};
|
|
2492
2492
|
// https://github.com/webpack/webpack/issues/625
|
|
2493
2493
|
// https://webpack.js.org/guides/dependency-management/#require-context
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"author": "Vladimir Barbarosh <vladimir.barbarosh@gmail.com>",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "@vbarbarosh/node-helpers",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.75.0",
|
|
6
6
|
"description": "A set of helpers for JavaScript/Node.js",
|
|
7
7
|
"unpkg": "dist/browser.js",
|
|
8
8
|
"jsdelivr": "dist/browser.js",
|
package/src/cache.js
ADDED
package/src/cache.md
ADDED
package/src/urlmod.test.js
CHANGED
|
@@ -32,4 +32,9 @@ describe('urlmod', function () {
|
|
|
32
32
|
assert.deepEqual(urlmod('/#ex', {b: 2}), '/?b=2#ex');
|
|
33
33
|
assert.deepEqual(urlmod('http://www.example.com/some/path?a=1#ex', {b: 2}), 'http://www.example.com/some/path?a=1&b=2#ex');
|
|
34
34
|
});
|
|
35
|
+
it('should keep port', function () {
|
|
36
|
+
const actual = urlmod('http://localhost:3000/auth/sign-in', {return: '/auth/profile'});
|
|
37
|
+
const expected = 'http://localhost:3000/auth/sign-in?return=%2Fauth%2Fprofile';
|
|
38
|
+
assert.strictEqual(actual, expected);
|
|
39
|
+
})
|
|
35
40
|
});
|
package/src/urlparts.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
function urlparts(url)
|
|
2
|
+
{
|
|
3
|
+
const tmp = url instanceof URL
|
|
4
|
+
? url
|
|
5
|
+
: new URL((typeof url === 'string' ? url : ''), 'fake://fake/');
|
|
6
|
+
return {
|
|
7
|
+
href: tmp.href,
|
|
8
|
+
protocol: tmp.protocol,
|
|
9
|
+
hostname: tmp.hostname,
|
|
10
|
+
username: tmp.username,
|
|
11
|
+
password: tmp.password,
|
|
12
|
+
host: tmp.host,
|
|
13
|
+
port: tmp.port,
|
|
14
|
+
path: tmp.pathname,
|
|
15
|
+
search: tmp.search,
|
|
16
|
+
hash: tmp.hash,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
module.exports = urlparts;
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const edge_values = require('@vbarbarosh/type-helpers/src/edge_values');
|
|
3
|
+
const urlparts = require('./urlparts');
|
|
4
|
+
|
|
5
|
+
const extra_edge_values = [
|
|
6
|
+
// whitespace strings
|
|
7
|
+
{label: '" "', value: ' '},
|
|
8
|
+
{label: '"\\t"', value: '\t'},
|
|
9
|
+
{label: '"\\n"', value: '\n'},
|
|
10
|
+
{label: '"\\r\\n"', value: '\r\n'},
|
|
11
|
+
|
|
12
|
+
// numeric strings
|
|
13
|
+
{label: '"0"', value: '0'},
|
|
14
|
+
{label: '"1"', value: '1'},
|
|
15
|
+
{label: '"NaN"', value: 'NaN'},
|
|
16
|
+
{label: '"Infinity"', value: 'Infinity'},
|
|
17
|
+
|
|
18
|
+
// weird unicode
|
|
19
|
+
{label: '"💩"', value: '💩'},
|
|
20
|
+
{label: '"😀"', value: '😀'},
|
|
21
|
+
{label: '"привет"', value: 'привет'},
|
|
22
|
+
{label: '"こんにちは"', value: 'こんにちは'},
|
|
23
|
+
|
|
24
|
+
// dangerous chars
|
|
25
|
+
{label: '"<script>"', value: '<script>'},
|
|
26
|
+
{label: '"../"', value: '../'},
|
|
27
|
+
{label: '"%20"', value: '%20'},
|
|
28
|
+
{label: '"a?b=c"', value: 'a?b=c'},
|
|
29
|
+
{label: '"a#b"', value: 'a#b'},
|
|
30
|
+
|
|
31
|
+
// arrays
|
|
32
|
+
{label: '[1,2,3]', value: [1, 2, 3]},
|
|
33
|
+
{label: '[null]', value: [null]},
|
|
34
|
+
{label: '[undefined]', value: [undefined]},
|
|
35
|
+
{label: 'new Array(5)', value: new Array(5)},
|
|
36
|
+
|
|
37
|
+
// typed arrays
|
|
38
|
+
{label: 'Uint8Array', value: new Uint8Array([1, 2, 3])},
|
|
39
|
+
{label: 'Buffer', value: Buffer.from('abc')},
|
|
40
|
+
|
|
41
|
+
// objects
|
|
42
|
+
{label: '{a:1}', value: {a: 1}},
|
|
43
|
+
{label: 'Object.create(null)', value: Object.create(null)},
|
|
44
|
+
|
|
45
|
+
// custom coercion
|
|
46
|
+
{label: 'toString() => x', value: {toString() {return 'x';}}},
|
|
47
|
+
{label: 'valueOf() => 123', value: {valueOf() {return 123;}}},
|
|
48
|
+
|
|
49
|
+
// dates
|
|
50
|
+
{label: 'new Date()', value: new Date()},
|
|
51
|
+
{label: 'Invalid Date', value: new Date('invalid')},
|
|
52
|
+
|
|
53
|
+
// regexp
|
|
54
|
+
{label: '/foo/g', value: /foo/g},
|
|
55
|
+
|
|
56
|
+
// maps/sets
|
|
57
|
+
{label: 'Map', value: new Map()},
|
|
58
|
+
{label: 'Set', value: new Set()},
|
|
59
|
+
{label: 'WeakMap', value: new WeakMap()},
|
|
60
|
+
{label: 'WeakSet', value: new WeakSet()},
|
|
61
|
+
|
|
62
|
+
// promises
|
|
63
|
+
{label: 'Promise.resolve(1)', value: Promise.resolve(1)},
|
|
64
|
+
|
|
65
|
+
// errors
|
|
66
|
+
{label: 'Error', value: new Error('boom')},
|
|
67
|
+
{label: 'TypeError', value: new TypeError('boom')},
|
|
68
|
+
|
|
69
|
+
// wrappers
|
|
70
|
+
{label: 'new String()', value: new String('abc')},
|
|
71
|
+
{label: 'new Number()', value: new Number(123)},
|
|
72
|
+
{label: 'new Boolean()', value: new Boolean(false)},
|
|
73
|
+
|
|
74
|
+
// url-like
|
|
75
|
+
{label: 'new URL("https://example.com")', value: new URL('https://example.com')},
|
|
76
|
+
|
|
77
|
+
// bigint
|
|
78
|
+
{label: '1n', value: 1n},
|
|
79
|
+
{label: '-1n', value: -1n},
|
|
80
|
+
|
|
81
|
+
// special numbers
|
|
82
|
+
{label: 'Number.EPSILON', value: Number.EPSILON},
|
|
83
|
+
|
|
84
|
+
// proxy
|
|
85
|
+
{label: 'Proxy', value: new Proxy({}, {})},
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
const happy_paths = [
|
|
89
|
+
{
|
|
90
|
+
label: 'parses full https url',
|
|
91
|
+
input: 'https://john:secret@example.com:8080/users/15?page=2#top',
|
|
92
|
+
expected: {
|
|
93
|
+
href: 'https://john:secret@example.com:8080/users/15?page=2#top',
|
|
94
|
+
protocol: 'https:',
|
|
95
|
+
hostname: 'example.com',
|
|
96
|
+
username: 'john',
|
|
97
|
+
password: 'secret',
|
|
98
|
+
host: 'example.com:8080',
|
|
99
|
+
port: '8080',
|
|
100
|
+
path: '/users/15',
|
|
101
|
+
search: '?page=2',
|
|
102
|
+
hash: '#top',
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
label: 'parses https url without auth',
|
|
107
|
+
input: 'https://example.com/users',
|
|
108
|
+
expected: {
|
|
109
|
+
href: 'https://example.com/users',
|
|
110
|
+
protocol: 'https:',
|
|
111
|
+
hostname: 'example.com',
|
|
112
|
+
username: '',
|
|
113
|
+
password: '',
|
|
114
|
+
host: 'example.com',
|
|
115
|
+
port: '',
|
|
116
|
+
path: '/users',
|
|
117
|
+
search: '',
|
|
118
|
+
hash: '',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
label: 'parses root url',
|
|
123
|
+
input: 'https://example.com',
|
|
124
|
+
expected: {
|
|
125
|
+
href: 'https://example.com/',
|
|
126
|
+
protocol: 'https:',
|
|
127
|
+
hostname: 'example.com',
|
|
128
|
+
username: '',
|
|
129
|
+
password: '',
|
|
130
|
+
host: 'example.com',
|
|
131
|
+
port: '',
|
|
132
|
+
path: '/',
|
|
133
|
+
search: '',
|
|
134
|
+
hash: '',
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
label: 'parses relative path',
|
|
139
|
+
input: '/users?page=5',
|
|
140
|
+
expected: {
|
|
141
|
+
href: 'fake://fake/users?page=5',
|
|
142
|
+
protocol: 'fake:',
|
|
143
|
+
hostname: 'fake',
|
|
144
|
+
username: '',
|
|
145
|
+
password: '',
|
|
146
|
+
host: 'fake',
|
|
147
|
+
port: '',
|
|
148
|
+
path: '/users',
|
|
149
|
+
search: '?page=5',
|
|
150
|
+
hash: '',
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
label: 'parses hash',
|
|
155
|
+
input: 'https://example.com/docs#intro',
|
|
156
|
+
expected: {
|
|
157
|
+
href: 'https://example.com/docs#intro',
|
|
158
|
+
protocol: 'https:',
|
|
159
|
+
hostname: 'example.com',
|
|
160
|
+
username: '',
|
|
161
|
+
password: '',
|
|
162
|
+
host: 'example.com',
|
|
163
|
+
port: '',
|
|
164
|
+
path: '/docs',
|
|
165
|
+
search: '',
|
|
166
|
+
hash: '#intro',
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
label: 'parses query string',
|
|
171
|
+
input: 'https://example.com?a=1&b=2',
|
|
172
|
+
expected: {
|
|
173
|
+
href: 'https://example.com/?a=1&b=2',
|
|
174
|
+
protocol: 'https:',
|
|
175
|
+
hostname: 'example.com',
|
|
176
|
+
username: '',
|
|
177
|
+
password: '',
|
|
178
|
+
host: 'example.com',
|
|
179
|
+
port: '',
|
|
180
|
+
path: '/',
|
|
181
|
+
search: '?a=1&b=2',
|
|
182
|
+
hash: '',
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
label: 'parses localhost with port',
|
|
187
|
+
input: 'http://localhost:3000/foo',
|
|
188
|
+
expected: {
|
|
189
|
+
href: 'http://localhost:3000/foo',
|
|
190
|
+
protocol: 'http:',
|
|
191
|
+
hostname: 'localhost',
|
|
192
|
+
username: '',
|
|
193
|
+
password: '',
|
|
194
|
+
host: 'localhost:3000',
|
|
195
|
+
port: '3000',
|
|
196
|
+
path: '/foo',
|
|
197
|
+
search: '',
|
|
198
|
+
hash: '',
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
label: 'parses ftp url',
|
|
203
|
+
input: 'ftp://example.com/file.txt',
|
|
204
|
+
expected: {
|
|
205
|
+
href: 'ftp://example.com/file.txt',
|
|
206
|
+
protocol: 'ftp:',
|
|
207
|
+
hostname: 'example.com',
|
|
208
|
+
username: '',
|
|
209
|
+
password: '',
|
|
210
|
+
host: 'example.com',
|
|
211
|
+
port: '',
|
|
212
|
+
path: '/file.txt',
|
|
213
|
+
search: '',
|
|
214
|
+
hash: '',
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
];
|
|
218
|
+
|
|
219
|
+
describe('urlparts', function () {
|
|
220
|
+
it('no args', function () {
|
|
221
|
+
assert.deepStrictEqual(urlparts(), {
|
|
222
|
+
href: 'fake://fake/',
|
|
223
|
+
protocol: 'fake:',
|
|
224
|
+
hostname: 'fake',
|
|
225
|
+
username: '',
|
|
226
|
+
password: '',
|
|
227
|
+
host: 'fake',
|
|
228
|
+
port: '',
|
|
229
|
+
path: '/',
|
|
230
|
+
search: '',
|
|
231
|
+
hash: '',
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
describe('happy paths', function () {
|
|
236
|
+
for (const item of happy_paths) {
|
|
237
|
+
it(item.label, function () {
|
|
238
|
+
const actual = urlparts(item.input);
|
|
239
|
+
assert.deepStrictEqual(actual, item.expected);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
describe('edge values', function () {
|
|
245
|
+
for (const item of [...edge_values, ...extra_edge_values]) {
|
|
246
|
+
it(item.label, function () {
|
|
247
|
+
if (typeof item.value === 'string') {
|
|
248
|
+
const tmp = new URL(item.value, 'fake://fake/');
|
|
249
|
+
assert.deepStrictEqual(urlparts(item.value), {
|
|
250
|
+
href: tmp.href,
|
|
251
|
+
protocol: tmp.protocol,
|
|
252
|
+
hostname: tmp.hostname,
|
|
253
|
+
username: tmp.username,
|
|
254
|
+
password: tmp.password,
|
|
255
|
+
host: tmp.host,
|
|
256
|
+
port: tmp.port,
|
|
257
|
+
path: tmp.pathname,
|
|
258
|
+
search: tmp.search,
|
|
259
|
+
hash: tmp.hash,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
else if (item.value instanceof URL) {
|
|
263
|
+
const tmp = item.value;
|
|
264
|
+
assert.deepStrictEqual(urlparts(item.value), {
|
|
265
|
+
href: tmp.href,
|
|
266
|
+
protocol: tmp.protocol,
|
|
267
|
+
hostname: tmp.hostname,
|
|
268
|
+
username: tmp.username,
|
|
269
|
+
password: tmp.password,
|
|
270
|
+
host: tmp.host,
|
|
271
|
+
port: tmp.port,
|
|
272
|
+
path: tmp.pathname,
|
|
273
|
+
search: tmp.search,
|
|
274
|
+
hash: tmp.hash,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
assert.deepStrictEqual(urlparts(item.value), {
|
|
279
|
+
href: 'fake://fake/',
|
|
280
|
+
protocol: 'fake:',
|
|
281
|
+
hostname: 'fake',
|
|
282
|
+
username: '',
|
|
283
|
+
password: '',
|
|
284
|
+
host: 'fake',
|
|
285
|
+
port: '',
|
|
286
|
+
path: '/',
|
|
287
|
+
search: '',
|
|
288
|
+
hash: '',
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
});
|