@ceeblue/web-utils 1.2.0 → 1.4.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 +52 -11
- package/dist/web-utils.d.ts +84 -19
- package/dist/web-utils.js +445 -281
- package/dist/web-utils.js.map +1 -1
- package/dist/web-utils.min.js +1 -1
- package/dist/web-utils.min.js.map +1 -1
- package/package.json +1 -1
package/dist/web-utils.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
/**
|
|
7
7
|
* BinaryReader allows to read binary data
|
|
8
8
|
*/
|
|
9
|
+
const _decoder$1 = new TextDecoder();
|
|
9
10
|
class BinaryReader {
|
|
10
11
|
constructor(data) {
|
|
11
12
|
this._data =
|
|
@@ -30,7 +31,7 @@ class BinaryReader {
|
|
|
30
31
|
return this._position;
|
|
31
32
|
}
|
|
32
33
|
reset(position = 0) {
|
|
33
|
-
this._position = position > this._size ? this._size : position;
|
|
34
|
+
this._position = Math.max(0, position > this._size ? this._size : position);
|
|
34
35
|
}
|
|
35
36
|
shrink(available) {
|
|
36
37
|
const rest = this._size - this._position;
|
|
@@ -45,7 +46,7 @@ class BinaryReader {
|
|
|
45
46
|
if (count > rest) {
|
|
46
47
|
count = rest;
|
|
47
48
|
}
|
|
48
|
-
this._position
|
|
49
|
+
this._position = Math.max(0, this._position + count);
|
|
49
50
|
return count;
|
|
50
51
|
}
|
|
51
52
|
read8() {
|
|
@@ -62,6 +63,12 @@ class BinaryReader {
|
|
|
62
63
|
read32() {
|
|
63
64
|
return this.next(4) === 4 ? this._view.getUint32(this._position - 4) : 0;
|
|
64
65
|
}
|
|
66
|
+
read64() {
|
|
67
|
+
if (this.next(8) !== 8) {
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
return this._view.getUint32(this._position - 8) * 4294967296 + this._view.getUint32(this._position - 4);
|
|
71
|
+
}
|
|
65
72
|
readFloat() {
|
|
66
73
|
return this.next(4) === 4 ? this._view.getFloat32(this._position - 4) : 0;
|
|
67
74
|
}
|
|
@@ -69,51 +76,51 @@ class BinaryReader {
|
|
|
69
76
|
return this.next(8) === 8 ? this._view.getFloat64(this._position - 8) : 0;
|
|
70
77
|
}
|
|
71
78
|
read7Bit(bytes = 5) {
|
|
72
|
-
if (bytes > 5) {
|
|
73
|
-
throw Error("BinaryReader in JS can't decode more than 32 usefull bits");
|
|
74
|
-
}
|
|
75
|
-
if (!(bytes > 0)) {
|
|
76
|
-
// negation to catch NaN value
|
|
77
|
-
throw Error('Have to indicate a positive number of bytes to decode');
|
|
78
|
-
}
|
|
79
79
|
let result = 0;
|
|
80
|
-
let
|
|
81
|
-
|
|
82
|
-
byte = this.read8();
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
let factor = 1;
|
|
81
|
+
while (this.available()) {
|
|
82
|
+
const byte = this.read8();
|
|
83
|
+
result += (byte & 0x7f) * factor;
|
|
84
|
+
if (!(byte & 0x80)) {
|
|
85
|
+
break;
|
|
85
86
|
}
|
|
86
|
-
|
|
87
|
-
}
|
|
87
|
+
factor *= 128;
|
|
88
|
+
}
|
|
88
89
|
return result;
|
|
89
90
|
}
|
|
90
91
|
readString() {
|
|
91
|
-
|
|
92
|
+
let i = this._position;
|
|
93
|
+
while (i < this._size && this._data[i]) {
|
|
94
|
+
++i;
|
|
95
|
+
}
|
|
96
|
+
const result = this.read(i - this._position);
|
|
97
|
+
this.next(); // skip the 0 termination
|
|
98
|
+
return _decoder$1.decode(result);
|
|
92
99
|
}
|
|
93
100
|
readHex(size) {
|
|
94
101
|
let hex = '';
|
|
95
|
-
while (size--) {
|
|
102
|
+
while (size-- > 0) {
|
|
96
103
|
hex += ('0' + this.read8().toString(16)).slice(-2);
|
|
97
104
|
}
|
|
98
105
|
return hex;
|
|
99
106
|
}
|
|
100
107
|
/**
|
|
101
|
-
* Read bytes, to convert bytes to string use String.fromCharCode(...reader.read(size))
|
|
108
|
+
* Read bytes, to convert bytes to string use String.fromCharCode(...reader.read(size)) or Util.stringify
|
|
102
109
|
* @param {UInt32} size
|
|
103
110
|
*/
|
|
104
111
|
read(size = this.available()) {
|
|
105
112
|
if (this.available() < size) {
|
|
106
113
|
return new Uint8Array(size); // default value = empty bytearray!
|
|
107
114
|
}
|
|
108
|
-
const
|
|
109
|
-
this._position += size;
|
|
110
|
-
return value;
|
|
115
|
+
const pos = this._position;
|
|
116
|
+
return this._data.subarray(pos, Math.max(pos, (this._position += size)));
|
|
111
117
|
}
|
|
112
118
|
}/**
|
|
113
119
|
* Copyright 2024 Ceeblue B.V.
|
|
114
120
|
* This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
|
|
115
121
|
* See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
|
|
116
122
|
*/
|
|
123
|
+
const _encoder$1 = new TextEncoder();
|
|
117
124
|
/**
|
|
118
125
|
* BinaryWriter allows to write data in its binary form
|
|
119
126
|
*/
|
|
@@ -161,16 +168,12 @@ class BinaryWriter {
|
|
|
161
168
|
clear(size = 0) {
|
|
162
169
|
return this.reserve((this._size = size));
|
|
163
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Write binary data
|
|
173
|
+
* @param data
|
|
174
|
+
*/
|
|
164
175
|
write(data) {
|
|
165
176
|
this.reserve(this._size + data.length);
|
|
166
|
-
if (typeof data === 'string') {
|
|
167
|
-
// beware here support just the 255 first bytes (compatible Latin-1)
|
|
168
|
-
for (let i = 0; i < data.length; ++i) {
|
|
169
|
-
const value = data.charCodeAt(i);
|
|
170
|
-
this._data[this._size++] = value > 255 ? 32 : value;
|
|
171
|
-
}
|
|
172
|
-
return this;
|
|
173
|
-
}
|
|
174
177
|
this._data.set(data, this._size);
|
|
175
178
|
this._size += data.length;
|
|
176
179
|
return this;
|
|
@@ -215,6 +218,10 @@ class BinaryWriter {
|
|
|
215
218
|
this._size += 4;
|
|
216
219
|
return this;
|
|
217
220
|
}
|
|
221
|
+
write64(value) {
|
|
222
|
+
this.write32(value / 4294967296);
|
|
223
|
+
return this.write32(value & 0xffffffff);
|
|
224
|
+
}
|
|
218
225
|
writeFloat(value) {
|
|
219
226
|
this.reserve(this._size + 4);
|
|
220
227
|
this.view.setFloat32(this._size, value);
|
|
@@ -227,35 +234,17 @@ class BinaryWriter {
|
|
|
227
234
|
this._size += 8;
|
|
228
235
|
return this;
|
|
229
236
|
}
|
|
230
|
-
write7Bit(value
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
throw Error('Have to indicate a positive number of bytes to encode');
|
|
237
|
+
write7Bit(value) {
|
|
238
|
+
let byte = value & 0x7f;
|
|
239
|
+
while ((value = Math.floor(value / 0x80))) {
|
|
240
|
+
// equivalent to >>=7 for JS!
|
|
241
|
+
this.write8(0x80 | byte);
|
|
242
|
+
byte = value & 0x7f;
|
|
237
243
|
}
|
|
238
|
-
|
|
239
|
-
const front = value > 0xffffffff ? 0x100 : value >>> bits;
|
|
240
|
-
if (front) {
|
|
241
|
-
++bits;
|
|
242
|
-
if (front > 0xff) {
|
|
243
|
-
value = 0xffffffff;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
else {
|
|
247
|
-
while ((bits -= 7) && !(value >>> bits)) {
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
while (bits > 1) {
|
|
252
|
-
this.write8(0x80 | ((value >>> bits) & 0xff));
|
|
253
|
-
bits -= 7;
|
|
254
|
-
}
|
|
255
|
-
return this.write8(value & (bits ? 0xff : 0x7f));
|
|
244
|
+
return this.write8(byte);
|
|
256
245
|
}
|
|
257
246
|
writeString(value) {
|
|
258
|
-
return this.
|
|
247
|
+
return this.write(_encoder$1.encode(value)).write8(0);
|
|
259
248
|
}
|
|
260
249
|
writeHex(value) {
|
|
261
250
|
for (let i = 0; i < value.length; i += 2) {
|
|
@@ -265,13 +254,13 @@ class BinaryWriter {
|
|
|
265
254
|
}
|
|
266
255
|
reserve(size) {
|
|
267
256
|
if (!this._data) {
|
|
268
|
-
throw
|
|
257
|
+
throw Error('buffer not writable');
|
|
269
258
|
}
|
|
270
259
|
if (size <= this._data.byteLength) {
|
|
271
260
|
return this;
|
|
272
261
|
}
|
|
273
262
|
if (this._isConst) {
|
|
274
|
-
throw
|
|
263
|
+
throw Error('writing exceeds maximum ' + this._data.byteLength + ' bytes limit');
|
|
275
264
|
}
|
|
276
265
|
--size;
|
|
277
266
|
size |= size >> 1;
|
|
@@ -352,6 +341,310 @@ class BitReader {
|
|
|
352
341
|
read32() {
|
|
353
342
|
return this.read(32);
|
|
354
343
|
}
|
|
344
|
+
}/******************************************************************************
|
|
345
|
+
Copyright (c) Microsoft Corporation.
|
|
346
|
+
|
|
347
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
348
|
+
purpose with or without fee is hereby granted.
|
|
349
|
+
|
|
350
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
351
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
352
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
353
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
354
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
355
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
356
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
357
|
+
***************************************************************************** */
|
|
358
|
+
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
362
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
363
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
364
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
365
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
366
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
367
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
372
|
+
var e = new Error(message);
|
|
373
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
374
|
+
};/**
|
|
375
|
+
* Copyright 2024 Ceeblue B.V.
|
|
376
|
+
* This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
|
|
377
|
+
* See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
|
|
378
|
+
*/
|
|
379
|
+
const _decoder = new TextDecoder();
|
|
380
|
+
const _encoder = new TextEncoder();
|
|
381
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
382
|
+
const _perf = performance; // to increase x10 now performance!
|
|
383
|
+
/**
|
|
384
|
+
* Some basic utility functions
|
|
385
|
+
*/
|
|
386
|
+
/**
|
|
387
|
+
* An empty lambda function, pratical to disable default behavior of function or events which are not expected to be null
|
|
388
|
+
* @example
|
|
389
|
+
* console.log = Util.EMPTY_FUNCTION; // disable logs without breaking calls
|
|
390
|
+
*/
|
|
391
|
+
const EMPTY_FUNCTION = () => { };
|
|
392
|
+
/**
|
|
393
|
+
* Efficient and high resolution timestamp in milliseconds elapsed since {@link Util.timeOrigin}
|
|
394
|
+
*/
|
|
395
|
+
function time() {
|
|
396
|
+
return Math.floor(_perf.now());
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Time origin represents the time when the application has started
|
|
400
|
+
*/
|
|
401
|
+
function timeOrigin() {
|
|
402
|
+
return Math.floor(_perf.now() + _perf.timeOrigin);
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Parse query and returns it in an easy-to-use Javascript object form
|
|
406
|
+
* @param urlOrQueryOrSearch string, url, or searchParams containing query. If not set it uses `location.search` to determinate query.
|
|
407
|
+
* @returns An javascript object containing each option
|
|
408
|
+
*/
|
|
409
|
+
function options(urlOrQueryOrSearch = typeof location === 'undefined'
|
|
410
|
+
? undefined
|
|
411
|
+
: location) {
|
|
412
|
+
if (!urlOrQueryOrSearch) {
|
|
413
|
+
return {};
|
|
414
|
+
}
|
|
415
|
+
try {
|
|
416
|
+
const url = urlOrQueryOrSearch;
|
|
417
|
+
urlOrQueryOrSearch = new URL(url).searchParams;
|
|
418
|
+
}
|
|
419
|
+
catch (e) {
|
|
420
|
+
if (typeof urlOrQueryOrSearch == 'string') {
|
|
421
|
+
if (urlOrQueryOrSearch.startsWith('?')) {
|
|
422
|
+
urlOrQueryOrSearch = urlOrQueryOrSearch.substring(1);
|
|
423
|
+
}
|
|
424
|
+
urlOrQueryOrSearch = new URLSearchParams(urlOrQueryOrSearch);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
// works same if urlOrQueryOrSearch is null, integer, or a already object etc...
|
|
428
|
+
return objectFrom(urlOrQueryOrSearch, { withType: true, noEmptyString: true });
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Returns an easy-to-use Javascript object something iterable, such as a Map, Set, or Array
|
|
432
|
+
* @param value iterable input
|
|
433
|
+
* @param params.withType `false`, if set it tries to cast string value to a JS number/boolean/undefined/null type.
|
|
434
|
+
* @param params.noEmptyString `false`, if set it converts empty string value to a true boolean, usefull to allow a `if(result.key)` check for example
|
|
435
|
+
* @returns An javascript object
|
|
436
|
+
*/
|
|
437
|
+
function objectFrom(value, params) {
|
|
438
|
+
params = Object.assign({ withType: false, noEmptyString: false }, params);
|
|
439
|
+
const obj = {};
|
|
440
|
+
if (!value) {
|
|
441
|
+
return obj;
|
|
442
|
+
}
|
|
443
|
+
for (const [key, val] of objectEntries(value)) {
|
|
444
|
+
value = val;
|
|
445
|
+
if (params.withType && value != null && value.substring) {
|
|
446
|
+
if (value) {
|
|
447
|
+
const number = Number(value);
|
|
448
|
+
if (isNaN(number)) {
|
|
449
|
+
switch (value.toLowerCase()) {
|
|
450
|
+
case 'true':
|
|
451
|
+
value = true;
|
|
452
|
+
break;
|
|
453
|
+
case 'false':
|
|
454
|
+
value = false;
|
|
455
|
+
break;
|
|
456
|
+
case 'null':
|
|
457
|
+
value = null;
|
|
458
|
+
break;
|
|
459
|
+
case 'undefined':
|
|
460
|
+
value = undefined;
|
|
461
|
+
break;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
value = number;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
else if (params.noEmptyString) {
|
|
469
|
+
// if empty string => TRUE to allow a if(options.key) check for example
|
|
470
|
+
value = true;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (obj[key]) {
|
|
474
|
+
if (!Array.isArray(obj[key])) {
|
|
475
|
+
obj[key] = new Array(obj[key]);
|
|
476
|
+
}
|
|
477
|
+
obj[key].push(value);
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
obj[key] = value;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
return obj;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Returns entries from something iterable, such as a Map, Set, or Array
|
|
487
|
+
* @param value iterable input
|
|
488
|
+
* @returns An javascript object
|
|
489
|
+
*/
|
|
490
|
+
function objectEntries(value) {
|
|
491
|
+
if (value.entries) {
|
|
492
|
+
return value.entries();
|
|
493
|
+
}
|
|
494
|
+
return Array.from({
|
|
495
|
+
[Symbol.iterator]: function* () {
|
|
496
|
+
for (const key in value) {
|
|
497
|
+
yield [key, value[key]];
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
}
|
|
502
|
+
/**
|
|
503
|
+
* Converts various data types, such as objects, strings, exceptions, errors,
|
|
504
|
+
* or numbers, into a string representation. Since it offers a more comprehensive format,
|
|
505
|
+
* this function is preferred to `JSON.stringify()`.
|
|
506
|
+
* @param obj Any objects, strings, exceptions, errors, or number
|
|
507
|
+
* @param params.space `''`, allows to configure space in the string representation
|
|
508
|
+
* @param params.decimal `2`, allows to choose the number of decimal to display in the string representation
|
|
509
|
+
* @param params.recursive `false`, allows to serialize recursively every object value, beware if a value refers to a already parsed value an infinite loop will occur
|
|
510
|
+
* @param params.noBin `false`, when set skip binary encoding and write inplace a bin-length information
|
|
511
|
+
* @returns the final string representation
|
|
512
|
+
*/
|
|
513
|
+
// Online Javascript Editor for free
|
|
514
|
+
// Write, Edit and Run your Javascript code using JS Online Compiler
|
|
515
|
+
function stringify(obj, params = {}) {
|
|
516
|
+
params = Object.assign({ space: ' ', decimal: 2, recursive: 1, noBin: false }, params);
|
|
517
|
+
if (obj == null) {
|
|
518
|
+
return String(obj);
|
|
519
|
+
}
|
|
520
|
+
const error = obj.error || obj.message;
|
|
521
|
+
if (error) {
|
|
522
|
+
// is a error!
|
|
523
|
+
obj = error;
|
|
524
|
+
}
|
|
525
|
+
// number
|
|
526
|
+
if (obj.toFixed) {
|
|
527
|
+
return obj.toFixed(Number(params.decimal) || 0);
|
|
528
|
+
}
|
|
529
|
+
// boolean or string type or stop recursivity
|
|
530
|
+
if (typeof obj === 'boolean' || obj.substring || !params.recursive) {
|
|
531
|
+
// is already a string OR has to be stringified
|
|
532
|
+
return String(obj);
|
|
533
|
+
}
|
|
534
|
+
const space = params.space || '';
|
|
535
|
+
if (Array.isArray(obj)) {
|
|
536
|
+
// Array!
|
|
537
|
+
let res = '';
|
|
538
|
+
for (const value of obj) {
|
|
539
|
+
res += (res ? ',' : '[') + space;
|
|
540
|
+
res += stringify(value, Object.assign(Object.assign({}, params), { recursive: params.recursive - 1 }));
|
|
541
|
+
}
|
|
542
|
+
return (res += space + ']');
|
|
543
|
+
}
|
|
544
|
+
if (obj.byteLength != null && (obj === null || obj === void 0 ? void 0 : obj[Symbol.iterator])) {
|
|
545
|
+
// Binary!
|
|
546
|
+
return _decoder.decode(obj);
|
|
547
|
+
}
|
|
548
|
+
let res = '';
|
|
549
|
+
if (params.noBin) {
|
|
550
|
+
return '[' + obj.byteLength + '#bytes]';
|
|
551
|
+
}
|
|
552
|
+
for (const name in obj) {
|
|
553
|
+
res += (res ? ',' : '{') + space + name + ':';
|
|
554
|
+
res += stringify(obj[name], Object.assign(Object.assign({}, params), { recursive: params.recursive - 1 }));
|
|
555
|
+
}
|
|
556
|
+
return (res += space + '}');
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* Encode a string to a binary representation
|
|
560
|
+
* @param value string value to convert
|
|
561
|
+
* @returns binary conversion
|
|
562
|
+
*/
|
|
563
|
+
function toBin(value) {
|
|
564
|
+
return _encoder.encode(value);
|
|
565
|
+
}
|
|
566
|
+
/**
|
|
567
|
+
* Execute a promise in a safe way with a timeout if caller doesn't resolve it in the accurate time
|
|
568
|
+
*/
|
|
569
|
+
function safePromise(timeout, promise) {
|
|
570
|
+
// Returns a race between our timeout and the passed in promise
|
|
571
|
+
let timer;
|
|
572
|
+
return Promise.race([
|
|
573
|
+
promise instanceof Promise ? promise : new Promise(promise),
|
|
574
|
+
new Promise((resolve, reject) => (timer = setTimeout(() => reject('timed out in ' + timeout + 'ms'), timeout)))
|
|
575
|
+
]).finally(() => clearTimeout(timer));
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Wait in milliseconds, requires a call with await keyword!
|
|
579
|
+
*/
|
|
580
|
+
function sleep(ms) {
|
|
581
|
+
return new Promise(resolve => {
|
|
582
|
+
setTimeout(resolve, ms);
|
|
583
|
+
});
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* fetch help method with few usefull fix:
|
|
587
|
+
* - throw an string exception if response code is not 200 with the text of the response or uses statusText
|
|
588
|
+
*/
|
|
589
|
+
function fetch(input, init) {
|
|
590
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
591
|
+
const response = yield self.fetch(input, init);
|
|
592
|
+
if (response.status >= 300) {
|
|
593
|
+
if (response.body) {
|
|
594
|
+
throw (yield response.text()) || response.statusText;
|
|
595
|
+
}
|
|
596
|
+
throw response.statusText;
|
|
597
|
+
}
|
|
598
|
+
return response;
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Extension parser
|
|
603
|
+
* @param path path to parse
|
|
604
|
+
* @returns the extension
|
|
605
|
+
*/
|
|
606
|
+
function parseExtension(path) {
|
|
607
|
+
const dot = path.lastIndexOf('.');
|
|
608
|
+
const ext = dot >= 0 && dot > path.lastIndexOf('/') ? path.substring(dot) : '';
|
|
609
|
+
return ext;
|
|
610
|
+
}var Util=/*#__PURE__*/Object.freeze({__proto__:null,EMPTY_FUNCTION:EMPTY_FUNCTION,fetch:fetch,objectEntries:objectEntries,objectFrom:objectFrom,options:options,parseExtension:parseExtension,safePromise:safePromise,sleep:sleep,stringify:stringify,time:time,timeOrigin:timeOrigin,toBin:toBin});/**
|
|
611
|
+
* Copyright 2024 Ceeblue B.V.
|
|
612
|
+
* This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
|
|
613
|
+
* See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
|
|
614
|
+
*/
|
|
615
|
+
/**
|
|
616
|
+
* Compute ByteRate every delta time
|
|
617
|
+
*/
|
|
618
|
+
class ByteRate {
|
|
619
|
+
onBytes(bytes) { }
|
|
620
|
+
get delta() {
|
|
621
|
+
return this._delta;
|
|
622
|
+
}
|
|
623
|
+
constructor(delta = 1000) {
|
|
624
|
+
this._time = time();
|
|
625
|
+
this._value = NaN;
|
|
626
|
+
this._delta = delta;
|
|
627
|
+
this._bytes = 0;
|
|
628
|
+
}
|
|
629
|
+
value() {
|
|
630
|
+
return Math.round(this.exact());
|
|
631
|
+
}
|
|
632
|
+
exact() {
|
|
633
|
+
const now = time();
|
|
634
|
+
const elapsed = now - this._time;
|
|
635
|
+
if (elapsed > this._delta || isNaN(this._value)) {
|
|
636
|
+
// wait "_delta" before next compute rate
|
|
637
|
+
this._value = (this._bytes * 1000) / elapsed;
|
|
638
|
+
this._bytes = 0;
|
|
639
|
+
this._time = now;
|
|
640
|
+
}
|
|
641
|
+
return this._value;
|
|
642
|
+
}
|
|
643
|
+
addBytes(bytes) {
|
|
644
|
+
this._bytes += bytes;
|
|
645
|
+
this.onBytes(bytes);
|
|
646
|
+
return this;
|
|
647
|
+
}
|
|
355
648
|
}/**
|
|
356
649
|
* Copyright 2024 Ceeblue B.V.
|
|
357
650
|
* This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
|
|
@@ -486,11 +779,11 @@ class NetAddress {
|
|
|
486
779
|
*/
|
|
487
780
|
var Type;
|
|
488
781
|
(function (Type) {
|
|
489
|
-
Type["HESP"] = "
|
|
490
|
-
Type["WEBRTS"] = "
|
|
491
|
-
Type["WEBRTC"] = "
|
|
492
|
-
Type["META"] = "
|
|
493
|
-
Type["DATA"] = "
|
|
782
|
+
Type["HESP"] = "HESP";
|
|
783
|
+
Type["WEBRTS"] = "WebRTS";
|
|
784
|
+
Type["WEBRTC"] = "WebRTC";
|
|
785
|
+
Type["META"] = "Meta";
|
|
786
|
+
Type["DATA"] = "Data";
|
|
494
787
|
})(Type || (Type = {}));
|
|
495
788
|
/**
|
|
496
789
|
* Some connection utility functions
|
|
@@ -533,6 +826,8 @@ function buildURL(type, params, protocol = 'wss') {
|
|
|
533
826
|
for (const key in params.query) {
|
|
534
827
|
url.searchParams.set(key, params.query[key]);
|
|
535
828
|
}
|
|
829
|
+
// Remove possible extension of streamName
|
|
830
|
+
params.streamName.substring(0, params.streamName.length - parseExtension(params.streamName).length);
|
|
536
831
|
return url;
|
|
537
832
|
}var Connect=/*#__PURE__*/Object.freeze({__proto__:null,get Type(){return Type},buildURL:buildURL});/**
|
|
538
833
|
* Copyright 2024 Ceeblue B.V.
|
|
@@ -597,18 +892,19 @@ class EventEmitter {
|
|
|
597
892
|
const events = new Set();
|
|
598
893
|
this._events.set(name.substring(2).toLowerCase(), events);
|
|
599
894
|
let defaultEvent = proto[name];
|
|
895
|
+
const raise = (...args) => {
|
|
896
|
+
// Call default event if not null (can happen in JS usage)
|
|
897
|
+
if (defaultEvent) {
|
|
898
|
+
defaultEvent.call(this, ...args);
|
|
899
|
+
}
|
|
900
|
+
// Call subscribers
|
|
901
|
+
for (const event of events) {
|
|
902
|
+
event(...args);
|
|
903
|
+
}
|
|
904
|
+
};
|
|
600
905
|
Object.defineProperties(this, {
|
|
601
906
|
[name]: {
|
|
602
|
-
get: () =>
|
|
603
|
-
// Call default event if not null (can happen in JS usage)
|
|
604
|
-
if (defaultEvent) {
|
|
605
|
-
defaultEvent.call(this, ...args);
|
|
606
|
-
}
|
|
607
|
-
// Call subscribers
|
|
608
|
-
for (const event of events) {
|
|
609
|
-
event(...args);
|
|
610
|
-
}
|
|
611
|
-
},
|
|
907
|
+
get: () => raise,
|
|
612
908
|
set: (value) => {
|
|
613
909
|
// Assign a default behavior!
|
|
614
910
|
defaultEvent = value;
|
|
@@ -633,9 +929,7 @@ class EventEmitter {
|
|
|
633
929
|
const events = this._event(name);
|
|
634
930
|
events.add(event);
|
|
635
931
|
if (abort) {
|
|
636
|
-
abort.signal.addEventListener('abort', () => {
|
|
637
|
-
events.delete(event);
|
|
638
|
-
});
|
|
932
|
+
abort.signal.addEventListener('abort', () => events.delete(event), { once: true });
|
|
639
933
|
}
|
|
640
934
|
}
|
|
641
935
|
/**
|
|
@@ -649,14 +943,12 @@ class EventEmitter {
|
|
|
649
943
|
throw Error('event to subscribe cannot be null');
|
|
650
944
|
}
|
|
651
945
|
const events = this._event(name);
|
|
652
|
-
events.add(() => {
|
|
946
|
+
events.add((...args) => {
|
|
653
947
|
events.delete(event); // delete from events
|
|
654
|
-
event(); // execute event
|
|
948
|
+
event(...args); // execute event
|
|
655
949
|
});
|
|
656
950
|
if (abort) {
|
|
657
|
-
abort.signal.addEventListener('abort', () => {
|
|
658
|
-
events.delete(event);
|
|
659
|
-
});
|
|
951
|
+
abort.signal.addEventListener('abort', () => events.delete(event), { once: true });
|
|
660
952
|
}
|
|
661
953
|
}
|
|
662
954
|
/**
|
|
@@ -682,6 +974,55 @@ class EventEmitter {
|
|
|
682
974
|
* This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
|
|
683
975
|
* See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
|
|
684
976
|
*/
|
|
977
|
+
/**
|
|
978
|
+
* Some fix for JS MAP:
|
|
979
|
+
* - find(key) search an item in the map and returns undefined if not found
|
|
980
|
+
* - get(key) return the item if exists or otherwise create and returns it
|
|
981
|
+
* - set(key, value) returns the value of the item (rather the MAP)
|
|
982
|
+
*/
|
|
983
|
+
class FixMap {
|
|
984
|
+
[Symbol.iterator]() {
|
|
985
|
+
return this._map[Symbol.iterator]();
|
|
986
|
+
}
|
|
987
|
+
get size() {
|
|
988
|
+
return this._map.size;
|
|
989
|
+
}
|
|
990
|
+
constructor(_initValue) {
|
|
991
|
+
this._initValue = _initValue;
|
|
992
|
+
this._map = new Map();
|
|
993
|
+
}
|
|
994
|
+
get(key) {
|
|
995
|
+
let value = this.find(key);
|
|
996
|
+
if (value === undefined) {
|
|
997
|
+
this._map.set(key, (value = this._initValue()));
|
|
998
|
+
}
|
|
999
|
+
return value;
|
|
1000
|
+
}
|
|
1001
|
+
find(key) {
|
|
1002
|
+
return this._map.get(key);
|
|
1003
|
+
}
|
|
1004
|
+
has(key) {
|
|
1005
|
+
return this._map.has(key);
|
|
1006
|
+
}
|
|
1007
|
+
clear() {
|
|
1008
|
+
this._map.clear();
|
|
1009
|
+
}
|
|
1010
|
+
delete(key) {
|
|
1011
|
+
return this._map.delete(key);
|
|
1012
|
+
}
|
|
1013
|
+
set(key, value) {
|
|
1014
|
+
this._map.set(key, value);
|
|
1015
|
+
return value;
|
|
1016
|
+
}
|
|
1017
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1018
|
+
forEach(callbackfn, thisArg) {
|
|
1019
|
+
this._map.forEach(callbackfn, thisArg);
|
|
1020
|
+
}
|
|
1021
|
+
}/**
|
|
1022
|
+
* Copyright 2024 Ceeblue B.V.
|
|
1023
|
+
* This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
|
|
1024
|
+
* See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
|
|
1025
|
+
*/
|
|
685
1026
|
/**
|
|
686
1027
|
* Queue typed similar to a {@link https://en.cppreference.com/w/cpp/container/queue | std::queue<Type>} with possibility to limit the capacity like a FIFO
|
|
687
1028
|
* @example
|
|
@@ -1099,202 +1440,6 @@ Object.freeze(SDP);/**
|
|
|
1099
1440
|
* This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
|
|
1100
1441
|
* See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
|
|
1101
1442
|
*/
|
|
1102
|
-
const _decoder = new TextDecoder();
|
|
1103
|
-
const _encoder = new TextEncoder();
|
|
1104
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1105
|
-
const _perf = performance; // to increase x10 now performance!
|
|
1106
|
-
/**
|
|
1107
|
-
* Some basic utility functions
|
|
1108
|
-
*/
|
|
1109
|
-
/**
|
|
1110
|
-
* An empty lambda function, pratical to disable default behavior of function or events which are not expected to be null
|
|
1111
|
-
* @example
|
|
1112
|
-
* console.log = Util.EMPTY_FUNCTION; // disable logs without breaking calls
|
|
1113
|
-
*/
|
|
1114
|
-
const EMPTY_FUNCTION = () => { };
|
|
1115
|
-
/**
|
|
1116
|
-
* Efficient and high resolution timestamp in milliseconds elapsed since {@link Util.timeOrigin}
|
|
1117
|
-
*/
|
|
1118
|
-
function time() {
|
|
1119
|
-
return Math.floor(_perf.now());
|
|
1120
|
-
}
|
|
1121
|
-
/**
|
|
1122
|
-
* Time origin represents the time when the application has started
|
|
1123
|
-
*/
|
|
1124
|
-
function timeOrigin() {
|
|
1125
|
-
return Math.floor(_perf.now() + _perf.timeOrigin);
|
|
1126
|
-
}
|
|
1127
|
-
/**
|
|
1128
|
-
* Parse query and returns it in an easy-to-use Javascript object form
|
|
1129
|
-
* @param urlOrQueryOrSearch string, url, or searchParams containing query. If not set it uses `location.search` to determinate query.
|
|
1130
|
-
* @returns An javascript object containing each option
|
|
1131
|
-
*/
|
|
1132
|
-
function options(urlOrQueryOrSearch = typeof location === 'undefined'
|
|
1133
|
-
? undefined
|
|
1134
|
-
: location) {
|
|
1135
|
-
if (!urlOrQueryOrSearch) {
|
|
1136
|
-
return {};
|
|
1137
|
-
}
|
|
1138
|
-
try {
|
|
1139
|
-
const url = urlOrQueryOrSearch;
|
|
1140
|
-
urlOrQueryOrSearch = new URL(url).searchParams;
|
|
1141
|
-
}
|
|
1142
|
-
catch (e) {
|
|
1143
|
-
if (typeof urlOrQueryOrSearch == 'string') {
|
|
1144
|
-
if (urlOrQueryOrSearch.startsWith('?')) {
|
|
1145
|
-
urlOrQueryOrSearch = urlOrQueryOrSearch.substring(1);
|
|
1146
|
-
}
|
|
1147
|
-
urlOrQueryOrSearch = new URLSearchParams(urlOrQueryOrSearch);
|
|
1148
|
-
}
|
|
1149
|
-
}
|
|
1150
|
-
// works same if urlOrQueryOrSearch is null, integer, or a already object etc...
|
|
1151
|
-
return objectFrom(urlOrQueryOrSearch, { withType: true, noEmptyString: true });
|
|
1152
|
-
}
|
|
1153
|
-
/**
|
|
1154
|
-
* Returns an easy-to-use Javascript object something iterable, such as a Map, Set, or Array
|
|
1155
|
-
* @param value iterable input
|
|
1156
|
-
* @param params.withType `false`, if set it tries to cast string value to a JS number/boolean/undefined/null type.
|
|
1157
|
-
* @param params.noEmptyString `false`, if set it converts empty string value to a true boolean, usefull to allow a `if(result.key)` check for example
|
|
1158
|
-
* @returns An javascript object
|
|
1159
|
-
*/
|
|
1160
|
-
function objectFrom(value, params) {
|
|
1161
|
-
params = Object.assign({ withType: false, noEmptyString: false }, params);
|
|
1162
|
-
const obj = {};
|
|
1163
|
-
if (!value) {
|
|
1164
|
-
return obj;
|
|
1165
|
-
}
|
|
1166
|
-
for (const [key, val] of objectEntries(value)) {
|
|
1167
|
-
value = val;
|
|
1168
|
-
if (params.withType && value != null && value.substring) {
|
|
1169
|
-
if (value) {
|
|
1170
|
-
const number = Number(value);
|
|
1171
|
-
if (isNaN(number)) {
|
|
1172
|
-
switch (value.toLowerCase()) {
|
|
1173
|
-
case 'true':
|
|
1174
|
-
value = true;
|
|
1175
|
-
break;
|
|
1176
|
-
case 'false':
|
|
1177
|
-
value = false;
|
|
1178
|
-
break;
|
|
1179
|
-
case 'null':
|
|
1180
|
-
value = null;
|
|
1181
|
-
break;
|
|
1182
|
-
case 'undefined':
|
|
1183
|
-
value = undefined;
|
|
1184
|
-
break;
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
else {
|
|
1188
|
-
value = number;
|
|
1189
|
-
}
|
|
1190
|
-
}
|
|
1191
|
-
else if (params.noEmptyString) {
|
|
1192
|
-
// if empty string => TRUE to allow a if(options.key) check for example
|
|
1193
|
-
value = true;
|
|
1194
|
-
}
|
|
1195
|
-
}
|
|
1196
|
-
if (obj[key]) {
|
|
1197
|
-
if (!Array.isArray(obj[key])) {
|
|
1198
|
-
obj[key] = new Array(obj[key]);
|
|
1199
|
-
}
|
|
1200
|
-
obj[key].push(value);
|
|
1201
|
-
}
|
|
1202
|
-
else {
|
|
1203
|
-
obj[key] = value;
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
return obj;
|
|
1207
|
-
}
|
|
1208
|
-
/**
|
|
1209
|
-
* Returns entries from something iterable, such as a Map, Set, or Array
|
|
1210
|
-
* @param value iterable input
|
|
1211
|
-
* @returns An javascript object
|
|
1212
|
-
*/
|
|
1213
|
-
function objectEntries(value) {
|
|
1214
|
-
if (value.entries) {
|
|
1215
|
-
return value.entries();
|
|
1216
|
-
}
|
|
1217
|
-
return Array.from({
|
|
1218
|
-
[Symbol.iterator]: function* () {
|
|
1219
|
-
for (const key in value) {
|
|
1220
|
-
yield [key, value[key]];
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
});
|
|
1224
|
-
}
|
|
1225
|
-
/**
|
|
1226
|
-
* Converts various data types, such as objects, strings, exceptions, errors,
|
|
1227
|
-
* or numbers, into a string representation. Since it offers a more comprehensive format,
|
|
1228
|
-
* this function is preferred to `JSON.stringify()`.
|
|
1229
|
-
* @param obj Any objects, strings, exceptions, errors, or number
|
|
1230
|
-
* @param params.space `''`, allows to configure space in the string representation
|
|
1231
|
-
* @param params.decimal `2`, allows to choose the number of decimal to display in the string representation
|
|
1232
|
-
* @param params.recursive `false`, allows to serialize recursively every object value, beware if a value refers to a already parsed value an infinite loop will occur.
|
|
1233
|
-
* @returns the final string representation
|
|
1234
|
-
*/
|
|
1235
|
-
// Online Javascript Editor for free
|
|
1236
|
-
// Write, Edit and Run your Javascript code using JS Online Compiler
|
|
1237
|
-
function stringify(obj, params = {}) {
|
|
1238
|
-
params = Object.assign({ space: ' ', decimal: 2, recursive: 1 }, params);
|
|
1239
|
-
if (obj == null) {
|
|
1240
|
-
return String(obj);
|
|
1241
|
-
}
|
|
1242
|
-
const error = obj.error || obj.message;
|
|
1243
|
-
if (error) {
|
|
1244
|
-
// is a error!
|
|
1245
|
-
obj = error;
|
|
1246
|
-
}
|
|
1247
|
-
if (obj.toFixed) {
|
|
1248
|
-
return obj.toFixed(Number(params.decimal) || 0);
|
|
1249
|
-
}
|
|
1250
|
-
if (obj.substring || !params.recursive) {
|
|
1251
|
-
// is already a string OR has to be stringified
|
|
1252
|
-
return String(obj);
|
|
1253
|
-
}
|
|
1254
|
-
const space = params.space || '';
|
|
1255
|
-
if (Array.isArray(obj)) {
|
|
1256
|
-
// Array!
|
|
1257
|
-
let res = '';
|
|
1258
|
-
for (const value of obj) {
|
|
1259
|
-
res += (res ? ',' : '[') + space;
|
|
1260
|
-
res += stringify(value, Object.assign(params, { recursive: params.recursive - 1 }));
|
|
1261
|
-
}
|
|
1262
|
-
return (res += space + ']');
|
|
1263
|
-
}
|
|
1264
|
-
if (obj.byteLength != null && (obj === null || obj === void 0 ? void 0 : obj[Symbol.iterator])) {
|
|
1265
|
-
// Binary!
|
|
1266
|
-
return _decoder.decode(obj);
|
|
1267
|
-
}
|
|
1268
|
-
let res = '';
|
|
1269
|
-
for (const name in obj) {
|
|
1270
|
-
res += (res ? ',' : '{') + space + name + ':';
|
|
1271
|
-
res += stringify(obj[name], Object.assign(params, { recursive: params.recursive - 1 }));
|
|
1272
|
-
}
|
|
1273
|
-
return (res += space + '}');
|
|
1274
|
-
}
|
|
1275
|
-
/**
|
|
1276
|
-
* Encode a string to a binary representation
|
|
1277
|
-
* @param value string value to convert
|
|
1278
|
-
* @returns binary conversion
|
|
1279
|
-
*/
|
|
1280
|
-
function toBin(value) {
|
|
1281
|
-
return _encoder.encode(value);
|
|
1282
|
-
}
|
|
1283
|
-
/**
|
|
1284
|
-
* Execute a promise in a safe way with a timeout if caller doesn't resolve it in the accurate time
|
|
1285
|
-
*/
|
|
1286
|
-
function safePromise(timeout, promise) {
|
|
1287
|
-
// Returns a race between our timeout and the passed in promise
|
|
1288
|
-
let timer;
|
|
1289
|
-
return Promise.race([
|
|
1290
|
-
promise instanceof Promise ? promise : new Promise(promise),
|
|
1291
|
-
new Promise((resolve, reject) => (timer = setTimeout(() => reject('timed out in ' + timeout + 'ms'), timeout)))
|
|
1292
|
-
]).finally(() => clearTimeout(timer));
|
|
1293
|
-
}var Util=/*#__PURE__*/Object.freeze({__proto__:null,EMPTY_FUNCTION:EMPTY_FUNCTION,objectEntries:objectEntries,objectFrom:objectFrom,options:options,safePromise:safePromise,stringify:stringify,time:time,timeOrigin:timeOrigin,toBin:toBin});/**
|
|
1294
|
-
* Copyright 2024 Ceeblue B.V.
|
|
1295
|
-
* This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
|
|
1296
|
-
* See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
|
|
1297
|
-
*/
|
|
1298
1443
|
/**
|
|
1299
1444
|
* The WebSocketReliable class extends WebSocket to bring up the following improvements:
|
|
1300
1445
|
* - Fix all possible unintentional closing ways to get always a related error message, {@link onClose | onClose(error?) event}
|
|
@@ -1346,6 +1491,12 @@ class WebSocketReliable extends EventEmitter {
|
|
|
1346
1491
|
get binaryType() {
|
|
1347
1492
|
return 'arraybuffer';
|
|
1348
1493
|
}
|
|
1494
|
+
get recvByteRate() {
|
|
1495
|
+
return this._recvByteRate.value();
|
|
1496
|
+
}
|
|
1497
|
+
get sendByteRate() {
|
|
1498
|
+
return this._sendByteRate.value();
|
|
1499
|
+
}
|
|
1349
1500
|
/**
|
|
1350
1501
|
* url of connection
|
|
1351
1502
|
*/
|
|
@@ -1409,6 +1560,8 @@ class WebSocketReliable extends EventEmitter {
|
|
|
1409
1560
|
this._queueingBytes = 0;
|
|
1410
1561
|
this._opened = false;
|
|
1411
1562
|
this._closed = true;
|
|
1563
|
+
this._recvByteRate = new ByteRate();
|
|
1564
|
+
this._sendByteRate = new ByteRate();
|
|
1412
1565
|
if (url) {
|
|
1413
1566
|
this.open(url, protocols);
|
|
1414
1567
|
}
|
|
@@ -1422,7 +1575,11 @@ class WebSocketReliable extends EventEmitter {
|
|
|
1422
1575
|
this._closed = false;
|
|
1423
1576
|
const ws = (this._ws = new WebSocket(url, protocols));
|
|
1424
1577
|
ws.binaryType = this.binaryType;
|
|
1425
|
-
ws.onmessage = e =>
|
|
1578
|
+
ws.onmessage = e => {
|
|
1579
|
+
var _a;
|
|
1580
|
+
this._recvByteRate.addBytes((_a = e.data.byteLength) !== null && _a !== void 0 ? _a : e.data.length);
|
|
1581
|
+
this.onMessage(e.data);
|
|
1582
|
+
};
|
|
1426
1583
|
// Add details and fix close ways
|
|
1427
1584
|
ws.onclose = (e) => {
|
|
1428
1585
|
if (!this._opened) {
|
|
@@ -1461,7 +1618,7 @@ class WebSocketReliable extends EventEmitter {
|
|
|
1461
1618
|
this._queueingBytes += typeof message === 'string' ? message.length : message.byteLength;
|
|
1462
1619
|
}
|
|
1463
1620
|
else {
|
|
1464
|
-
this.
|
|
1621
|
+
this._send(message);
|
|
1465
1622
|
}
|
|
1466
1623
|
return this;
|
|
1467
1624
|
}
|
|
@@ -1471,7 +1628,7 @@ class WebSocketReliable extends EventEmitter {
|
|
|
1471
1628
|
flush() {
|
|
1472
1629
|
if (this._ws) {
|
|
1473
1630
|
for (const message of this._queueing) {
|
|
1474
|
-
this.
|
|
1631
|
+
this._send(message);
|
|
1475
1632
|
}
|
|
1476
1633
|
}
|
|
1477
1634
|
this._queueing.length = 0;
|
|
@@ -1494,9 +1651,16 @@ class WebSocketReliable extends EventEmitter {
|
|
|
1494
1651
|
this._queueingBytes = 0;
|
|
1495
1652
|
this.onClose(error);
|
|
1496
1653
|
}
|
|
1654
|
+
_send(message) {
|
|
1655
|
+
if (!this._ws) {
|
|
1656
|
+
return;
|
|
1657
|
+
}
|
|
1658
|
+
this._sendByteRate.addBytes(typeof message === 'string' ? message.length : message.byteLength);
|
|
1659
|
+
this._ws.send(message);
|
|
1660
|
+
}
|
|
1497
1661
|
}/**
|
|
1498
1662
|
* Copyright 2024 Ceeblue B.V.
|
|
1499
1663
|
* This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
|
|
1500
1664
|
* See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
|
|
1501
1665
|
*/
|
|
1502
|
-
const VERSION = '1.
|
|
1666
|
+
const VERSION = '1.4.0';export{BinaryReader,BinaryWriter,BitReader,ByteRate,Connect,EventEmitter,FixMap,NetAddress,Numbers,Queue,SDP,Util,VERSION,WebSocketReliable};//# sourceMappingURL=web-utils.js.map
|