@ceeblue/web-utils 6.0.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -322,7 +322,7 @@ type Params = {
322
322
  * If `endPoint` is a complete URL and `streamName` is not provided, {@link buildURL} will set this parameter automatically
323
323
  * using the second part of the URL's path (the first part being the protocol name), or the first path if no other part exists.
324
324
  */
325
- streamName: string;
325
+ streamName?: string;
326
326
  /**
327
327
  * Optional access token to use to join a private stream
328
328
  */
@@ -891,14 +891,24 @@ declare function safePromise<T>(timeout: number, promise: Promise<T>): Promise<u
891
891
  */
892
892
  declare function sleep(ms: number): Promise<unknown>;
893
893
  /**
894
- * Test equality between two value whatever their type, array included
894
+ * Test equality between two value whatever their type, object and array included
895
895
  */
896
- declare function equal(a: any, b: any): boolean;
896
+ declare function equal(a: any, b: any, seen?: WeakMap<WeakKey, any>): boolean;
897
897
  /**
898
- * fetch help method with few usefull fix:
899
- * - throw an string exception if response code is not 200 with the text of the response or uses statusText
898
+ * Fetch help method adding an explicit error property when Response is NOK, with the more accurate textual error inside
900
899
  */
901
- declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
900
+ declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response & {
901
+ error?: string;
902
+ }>;
903
+ /**
904
+ * Fetch help method adding an explicit error property when Response is NOK, with the more accurate textual error inside
905
+ * Also measure the rtt of fetching and returns it in the property Response.rtt (guaranteed to be ≥ 1),
906
+ * supports subtracting server processing time using either the Response-Delay or CMSD-rd header when available
907
+ */
908
+ declare function fetchWithRTT(input: RequestInfo | URL, init?: RequestInit): Promise<Response & {
909
+ rtt: number;
910
+ error?: string;
911
+ }>;
902
912
  /**
903
913
  * Get Extension part from path
904
914
  * @param path path to parse
@@ -942,6 +952,7 @@ declare function trimEnd(value: string, chars?: string): string;
942
952
  declare const Util_EMPTY_FUNCTION: typeof EMPTY_FUNCTION;
943
953
  declare const Util_equal: typeof equal;
944
954
  declare const Util_fetch: typeof fetch;
955
+ declare const Util_fetchWithRTT: typeof fetchWithRTT;
945
956
  declare const Util_getBaseFile: typeof getBaseFile;
946
957
  declare const Util_getExtension: typeof getExtension;
947
958
  declare const Util_getFile: typeof getFile;
@@ -958,7 +969,7 @@ declare const Util_trimEnd: typeof trimEnd;
958
969
  declare const Util_trimStart: typeof trimStart;
959
970
  declare const Util_unixTime: typeof unixTime;
960
971
  declare namespace Util {
961
- export { Util_EMPTY_FUNCTION as EMPTY_FUNCTION, Util_equal as equal, Util_fetch as fetch, Util_getBaseFile as getBaseFile, Util_getExtension as getExtension, Util_getFile as getFile, Util_iterableEntries as iterableEntries, Util_objectFrom as objectFrom, Util_options as options, Util_safePromise as safePromise, Util_sleep as sleep, Util_stringify as stringify, Util_time as time, Util_toBin as toBin, Util_trim as trim, Util_trimEnd as trimEnd, Util_trimStart as trimStart, Util_unixTime as unixTime };
972
+ export { Util_EMPTY_FUNCTION as EMPTY_FUNCTION, Util_equal as equal, Util_fetch as fetch, Util_fetchWithRTT as fetchWithRTT, Util_getBaseFile as getBaseFile, Util_getExtension as getExtension, Util_getFile as getFile, Util_iterableEntries as iterableEntries, Util_objectFrom as objectFrom, Util_options as options, Util_safePromise as safePromise, Util_sleep as sleep, Util_stringify as stringify, Util_time as time, Util_toBin as toBin, Util_trim as trim, Util_trimEnd as trimEnd, Util_trimStart as trimStart, Util_unixTime as unixTime };
962
973
  }
963
974
 
964
975
  /**
package/dist/web-utils.js CHANGED
@@ -371,52 +371,136 @@ function safePromise(timeout, promise) {
371
371
  * Wait in milliseconds, requires a call with await keyword!
372
372
  */
373
373
  function sleep(ms) {
374
- return new Promise(resolve => {
375
- setTimeout(resolve, ms);
374
+ return __awaiter(this, void 0, void 0, function* () {
375
+ return new Promise(resolve => {
376
+ setTimeout(resolve, ms);
377
+ });
376
378
  });
377
379
  }
378
380
  /**
379
- * Test equality between two value whatever their type, array included
381
+ * Test equality between two value whatever their type, object and array included
380
382
  */
381
- function equal(a, b) {
382
- if (Object(a) !== a) {
383
- if (Object(b) === b) {
384
- return false;
385
- }
386
- // both primitive (null and undefined included)
387
- return a === b;
383
+ function equal(a, b, seen = new WeakMap()) {
384
+ // 1. Check primitve identiy or NaN
385
+ if (a === b) {
386
+ return true;
388
387
  }
389
- // complexe object
390
- if (a[Symbol.iterator]) {
391
- if (!b[Symbol.iterator]) {
392
- return false;
388
+ if (Number.isNaN(a) && Number.isNaN(b)) {
389
+ return true;
390
+ }
391
+ // 2. Check the both are complexe object
392
+ if (Object(a) !== a || Object(b) !== b) {
393
+ return false;
394
+ }
395
+ // 3. Catch circular reference
396
+ if (seen.has(a)) {
397
+ return seen.get(a) === b;
398
+ }
399
+ seen.set(a, b);
400
+ // 4. Check « toStringTag » (Date, RegExp, Map, Set…)
401
+ const tagA = Object.prototype.toString.call(a);
402
+ if (tagA !== Object.prototype.toString.call(b)) {
403
+ return false;
404
+ }
405
+ // 5. Special Case
406
+ switch (tagA) {
407
+ case '[object Date]':
408
+ return a.getTime() === b.getTime();
409
+ case '[object RegExp]':
410
+ return a.source === b.source && a.flags === b.flags;
411
+ case '[object Set]':
412
+ case '[object Map]': {
413
+ if (a.size !== b.size) {
414
+ return false;
415
+ }
416
+ const aKeys = a.keys();
417
+ const bKeys = a.keys();
418
+ const aValues = a.values();
419
+ const bValues = b.values();
420
+ let aKey;
421
+ while (!(aKey = aKeys.next()).done) {
422
+ if (!equal(aKey.value, bKeys.next().value)) {
423
+ return false;
424
+ }
425
+ const aValue = aValues.next().value;
426
+ const bValue = bValues.next().value;
427
+ if (aValue !== aKey && !equal(aValue, bValue)) {
428
+ return false;
429
+ }
430
+ }
431
+ return true;
393
432
  }
394
- if (a.length !== b.length) {
433
+ }
434
+ // 6. Arrays
435
+ if (Array.isArray(a)) {
436
+ if (!Array.isArray(b) || a.length !== b.length) {
395
437
  return false;
396
438
  }
397
- for (let i = 0; i !== a.length; ++i) {
398
- if (a[i] !== b[i]) {
439
+ for (let i = 0; i < a.length; i++) {
440
+ if (!equal(a[i], b[i], seen)) {
399
441
  return false;
400
442
  }
401
443
  }
402
444
  return true;
403
445
  }
404
- return a === b;
446
+ // 7. Generic object : keys + symbols
447
+ const keysA = [...Object.keys(a), ...Object.getOwnPropertySymbols(a)];
448
+ if (keysA.length !== Object.keys(b).length + Object.getOwnPropertySymbols(b).length) {
449
+ return false;
450
+ }
451
+ for (const key of keysA) {
452
+ if (!equal(a[key], b[key], seen)) {
453
+ return false;
454
+ }
455
+ }
456
+ return true;
405
457
  }
406
458
  /**
407
- * fetch help method with few usefull fix:
408
- * - throw an string exception if response code is not 200 with the text of the response or uses statusText
459
+ * Fetch help method adding an explicit error property when Response is NOK, with the more accurate textual error inside
409
460
  */
410
461
  function fetch(input, init) {
411
462
  return __awaiter(this, void 0, void 0, function* () {
412
- const response = yield self.fetch(input, init);
413
- if (response.status >= 300) {
414
- let error;
463
+ const response = (yield self.fetch(input, init));
464
+ if (!response.ok) {
415
465
  if (response.body) {
416
- error = yield response.text();
466
+ response.error = yield response.text();
467
+ }
468
+ if (!response.error) {
469
+ response.error = response.statusText || response.status.toString() || 'Unknown error';
470
+ }
471
+ }
472
+ return response;
473
+ });
474
+ }
475
+ /**
476
+ * Fetch help method adding an explicit error property when Response is NOK, with the more accurate textual error inside
477
+ * Also measure the rtt of fetching and returns it in the property Response.rtt (guaranteed to be ≥ 1),
478
+ * supports subtracting server processing time using either the Response-Delay or CMSD-rd header when available
479
+ */
480
+ function fetchWithRTT(input, init) {
481
+ return __awaiter(this, void 0, void 0, function* () {
482
+ // a first HEAD request to try to ensure a connection
483
+ yield fetch(input, Object.assign(Object.assign({}, init), { method: 'HEAD' }));
484
+ // the true request
485
+ const startTime = time();
486
+ const response = (yield fetch(input, init));
487
+ response.rtt = time() - startTime;
488
+ // remove the ResponseDelay if indicated by the server
489
+ let responseDelay = Number(response.headers.get('Response-Delay')) || 0;
490
+ if (!responseDelay) {
491
+ // search if we have a CMSD info?
492
+ // cmsd-dynamic "fly";rd=1
493
+ const cmsd = response.headers.get('cmsd-dynamic');
494
+ if (cmsd) {
495
+ for (const param of cmsd.split(';')) {
496
+ const [name, value] = param.split('=');
497
+ if (name.trim().toLowerCase() === 'rd') {
498
+ responseDelay = Number(value) || responseDelay;
499
+ }
500
+ }
417
501
  }
418
- throw (error || response.statusText || response.status).toString();
419
502
  }
503
+ response.rtt = Math.max(1, response.rtt - responseDelay);
420
504
  return response;
421
505
  });
422
506
  }
@@ -500,7 +584,7 @@ function trimEnd(value, chars = ' ') {
500
584
  --i;
501
585
  }
502
586
  return value.substring(0, i);
503
- }var Util=/*#__PURE__*/Object.freeze({__proto__:null,EMPTY_FUNCTION:EMPTY_FUNCTION,equal:equal,fetch:fetch,getBaseFile:getBaseFile,getExtension:getExtension,getFile:getFile,iterableEntries:iterableEntries,objectFrom:objectFrom,options:options,safePromise:safePromise,sleep:sleep,stringify:stringify,time:time,toBin:toBin,trim:trim,trimEnd:trimEnd,trimStart:trimStart,unixTime:unixTime});/**
587
+ }var Util=/*#__PURE__*/Object.freeze({__proto__:null,EMPTY_FUNCTION:EMPTY_FUNCTION,equal:equal,fetch:fetch,fetchWithRTT:fetchWithRTT,getBaseFile:getBaseFile,getExtension:getExtension,getFile:getFile,iterableEntries:iterableEntries,objectFrom:objectFrom,options:options,safePromise:safePromise,sleep:sleep,stringify:stringify,time:time,toBin:toBin,trim:trim,trimEnd:trimEnd,trimStart:trimStart,unixTime:unixTime});/**
504
588
  * Copyright 2024 Ceeblue B.V.
505
589
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
506
590
  * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
@@ -1167,7 +1251,21 @@ var Type;
1167
1251
  * @param params The parameters for which the media extension is to be defined
1168
1252
  */
1169
1253
  function defineMediaExt(type, params) {
1254
+ var _a;
1170
1255
  // Compute appropriate mediaExt out parameter
1256
+ if (!params.mediaExt) {
1257
+ try {
1258
+ const url = new URL(params.endPoint);
1259
+ // Set mediaExt with ?ext= param when set OR url extension
1260
+ params.mediaExt = (_a = url.searchParams.get('ext')) !== null && _a !== void 0 ? _a : getExtension(getFile(url.pathname));
1261
+ }
1262
+ catch (_) {
1263
+ // not an URL, it's only a host
1264
+ params.mediaExt = '';
1265
+ }
1266
+ }
1267
+ // Normalize mediaExt in removing the possible '.' prefix and change it to lower case
1268
+ params.mediaExt = trimStart(params.mediaExt, '.').toLowerCase();
1171
1269
  switch (type) {
1172
1270
  case Type.HESP:
1173
1271
  params.mediaExt = 'mp4';
@@ -1176,19 +1274,8 @@ function defineMediaExt(type, params) {
1176
1274
  params.mediaExt = 'rtp';
1177
1275
  break;
1178
1276
  case Type.WRTS: {
1179
- try {
1180
- const url = new URL(params.endPoint);
1181
- const ext = getExtension(getFile(url.pathname));
1182
- // set extension just if not json, json means a manifest file endPoint
1183
- if (ext && ext.toLowerCase() !== '.json') {
1184
- params.mediaExt = ext;
1185
- }
1186
- }
1187
- catch (_) {
1188
- // not an URL, it's only a host => keep mediaExt unchanged to build the URL
1189
- }
1190
- if (!params.mediaExt) {
1191
- // set to its default rts value => always set for WRTS!
1277
+ // json means a manifest file endPoint, replace with default rts media extension
1278
+ if (!params.mediaExt || params.mediaExt === 'json') {
1192
1279
  params.mediaExt = 'rts';
1193
1280
  }
1194
1281
  break;
@@ -1200,12 +1287,9 @@ function defineMediaExt(type, params) {
1200
1287
  params.mediaExt = 'json';
1201
1288
  break;
1202
1289
  default:
1203
- params.mediaExt = ''; // set always a value to know that the parameters have been fixed
1204
- console.warn('Unknown params type ' + type);
1290
+ log('Unknown params type ' + type).warn();
1205
1291
  break;
1206
1292
  }
1207
- // Fix mediaExt in removing the possible '.' prefix
1208
- params.mediaExt = trimStart(params.mediaExt, '.');
1209
1293
  }
1210
1294
  /**
1211
1295
  * Build an URL from {@link Type | type} and {@link Params | params}
@@ -1238,7 +1322,7 @@ function buildURL(type, params, protocol = 'wss') {
1238
1322
  url.pathname = '/' + params.streamName + '.json';
1239
1323
  break;
1240
1324
  default:
1241
- console.warn('Unknown url type ' + type);
1325
+ log('Unknown url type ' + type).warn();
1242
1326
  break;
1243
1327
  }
1244
1328
  }
@@ -2462,4 +2546,4 @@ class UIMetrics {
2462
2546
  * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License.
2463
2547
  * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details.
2464
2548
  */
2465
- const VERSION = '6.0.0';export{BinaryReader,BinaryWriter,BitReader,ByteRate,Connect,EpochTime,EventEmitter,FixMap,Log,LogLevel,Loggable,NetAddress,Numbers,Queue,SDP,UIMetrics,Util,VERSION,WebSocketReliable,log};//# sourceMappingURL=web-utils.js.map
2549
+ const VERSION = '7.0.0';export{BinaryReader,BinaryWriter,BitReader,ByteRate,Connect,EpochTime,EventEmitter,FixMap,Log,LogLevel,Loggable,NetAddress,Numbers,Queue,SDP,UIMetrics,Util,VERSION,WebSocketReliable,log};//# sourceMappingURL=web-utils.js.map