@js-toolkit/web-utils 1.47.0 → 1.48.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.
Files changed (51) hide show
  1. package/ConnectionController.d.ts +7 -0
  2. package/ConnectionController.js +1 -0
  3. package/EventEmitterListener.utils.js +1 -1
  4. package/fullscreen.js +1 -1
  5. package/getAspectRatio.js +1 -1
  6. package/getEventAwaiter.d.ts +1 -1
  7. package/getEventAwaiter.js +1 -1
  8. package/getSecondsCounter.js +1 -1
  9. package/iframe/getAutoConnectClient.js +1 -1
  10. package/iframe/getAutoConnectHost.js +1 -1
  11. package/iframe/getAutoConnector.js +1 -1
  12. package/iframe/utils.d.ts +1 -0
  13. package/iframe/utils.js +1 -1
  14. package/media/{mse.d.ts → mse/getMediaSource.d.ts} +0 -2
  15. package/media/mse/getMediaSource.js +1 -0
  16. package/media/mse/index.d.ts +2 -0
  17. package/media/mse/index.js +1 -0
  18. package/media/mse/isMSESupported.d.ts +1 -0
  19. package/media/mse/isMSESupported.js +1 -0
  20. package/package.json +16 -16
  21. package/{detection → platform}/getIOSVersion.d.ts +1 -1
  22. package/platform/getIOSVersion.js +1 -0
  23. package/{detection → platform}/isAirPlayAvailable.d.ts +0 -1
  24. package/{detection → platform}/isAirPlayAvailable.js +1 -1
  25. package/{detection → platform}/isAndroid.d.ts +0 -1
  26. package/{detection → platform}/isAndroid.js +1 -1
  27. package/{detection → platform}/isIOS.d.ts +0 -1
  28. package/platform/isIOS.js +1 -0
  29. package/{detection → platform}/isMacOS.d.ts +0 -1
  30. package/platform/isMacOS.js +1 -0
  31. package/{detection → platform}/isMobile.d.ts +0 -1
  32. package/platform/isMobile.js +1 -0
  33. package/{detection → platform}/isSafari.d.ts +0 -1
  34. package/platform/isSafari.js +1 -0
  35. package/{isStandaloneApp.d.ts → platform/isStandaloneApp.d.ts} +0 -1
  36. package/{isStandaloneApp.js → platform/isStandaloneApp.js} +1 -1
  37. package/takeSnapshot.js +1 -1
  38. package/types/refs.d.ts +1 -1
  39. package/types/refs.js +1 -1
  40. package/webrtc/PeerConnection.d.ts +1 -1
  41. package/webrtc/PeerConnection.js +1 -1
  42. package/ws/WSController.d.ts +1 -1
  43. package/ws/WSController.js +1 -1
  44. package/detection/getIOSVersion.js +0 -1
  45. package/detection/isIOS.js +0 -1
  46. package/detection/isMacOS.js +0 -1
  47. package/detection/isMobile.js +0 -1
  48. package/detection/isSafari.js +0 -1
  49. package/media/mse.js +0 -1
  50. /package/{detection → platform}/getUAParserResult.d.ts +0 -0
  51. /package/{detection → platform}/getUAParserResult.js +0 -0
@@ -0,0 +1,7 @@
1
+ import { DataEventEmitter } from '@js-toolkit/utils/DataEventEmitter';
2
+ export declare class ConnectionController extends DataEventEmitter<'online' | 'offline' | 'destroy'> {
3
+ private readonly listener;
4
+ constructor(target?: Window & typeof globalThis);
5
+ isOnline(): boolean;
6
+ destroy(): void;
7
+ }
@@ -0,0 +1 @@
1
+ import{DataEventEmitter}from"@js-toolkit/utils/DataEventEmitter";import{EventEmitterListener}from"./EventEmitterListener";export class ConnectionController extends DataEventEmitter{constructor(t=window){super(),this.listener=new EventEmitterListener(t).on("online",(()=>this.emit("online"))).on("offline",(()=>this.emit("offline")))}isOnline(){return navigator.onLine}destroy(){this.listener.removeAllListeners(),this.emit("destroy"),this.removeAllListeners()}}
@@ -1 +1 @@
1
- import{__rest}from"tslib";import isEmptyObject from"@jstoolkit/utils/isEmptyObject";export function isEventTargetLike(t){return void 0!==t.addEventListener&&void 0!==t.removeEventListener}export function isDomEventTarget(t){return isEventTargetLike(t)&&void 0!==t.dispatchEvent}export function isEventEmitterLike(t){return!isEventTargetLike(t)&&!isDomEventTarget(t)&&void 0!==t.on&&void 0!==t.once&&void 0!==t.off}let passiveSupported=!1;export function isPassiveSupported(){return passiveSupported}try{const t={get passive(){return passiveSupported=!0,!1}};window.addEventListener("__testpassive__",null,t)}catch(e){}export function normalizeOptions(t){if(t&&"object"==typeof t){let e=t;if("passive"in t&&!passiveSupported){const{passive:i}=t;e=__rest(t,["passive"])}return isEmptyObject(e)?void 0:e}return t}
1
+ import{__rest}from"tslib";import isEmptyObject from"@js-toolkit/utils/isEmptyObject";export function isEventTargetLike(t){return void 0!==t.addEventListener&&void 0!==t.removeEventListener}export function isDomEventTarget(t){return isEventTargetLike(t)&&void 0!==t.dispatchEvent}export function isEventEmitterLike(t){return!isEventTargetLike(t)&&!isDomEventTarget(t)&&void 0!==t.on&&void 0!==t.once&&void 0!==t.off}let passiveSupported=!1;export function isPassiveSupported(){return passiveSupported}try{const t={get passive(){return passiveSupported=!0,!1}};window.addEventListener("__testpassive__",null,t)}catch(e){}export function normalizeOptions(t){if(t&&"object"==typeof t){let e=t;if("passive"in t&&!passiveSupported){const{passive:i}=t;e=__rest(t,["passive"])}return isEmptyObject(e)?void 0:e}return t}
package/fullscreen.js CHANGED
@@ -1 +1 @@
1
- import es5ErrorCompat from"@jstoolkit/utils/es5ErrorCompat";export class FullscreenUnavailableError extends Error{constructor(){super("Fullscreen is not available"),es5ErrorCompat(this,FullscreenUnavailableError)}}export var fullscreen;!function(e){e.names=[{requestFullscreenName:"requestFullscreen",exitFullscreenName:"exitFullscreen",fullscreenElementName:"fullscreenElement",fullscreenEnabledName:"fullscreenEnabled",changeEventName:"fullscreenchange",errorEventName:"fullscreenerror"},{requestFullscreenName:"webkitRequestFullscreen",exitFullscreenName:"webkitExitFullscreen",fullscreenElementName:"webkitFullscreenElement",fullscreenEnabledName:"webkitFullscreenEnabled",changeEventName:"webkitfullscreenchange",errorEventName:"webkitfullscreenerror"},{requestFullscreenName:"webkitRequestFullScreen",exitFullscreenName:"webkitCancelFullScreen",fullscreenElementName:"webkitCurrentFullScreenElement",fullscreenEnabledName:"webkitCancelFullScreen",changeEventName:"webkitfullscreenchange",errorEventName:"webkitfullscreenerror"},{requestFullscreenName:"mozRequestFullScreen",exitFullscreenName:"mozCancelFullScreen",fullscreenElementName:"mozFullScreenElement",fullscreenEnabledName:"mozFullScreenEnabled",changeEventName:"mozfullscreenchange",errorEventName:"mozfullscreenerror"},{requestFullscreenName:"msRequestFullscreen",exitFullscreenName:"msExitFullscreen",fullscreenElementName:"msFullscreenElement",fullscreenEnabledName:"msFullscreenEnabled",changeEventName:"MSFullscreenChange",errorEventName:"MSFullscreenError"}].find((({exitFullscreenName:e})=>e in document));const n={change:null===e.names||void 0===e.names?void 0:e.names.changeEventName,error:null===e.names||void 0===e.names?void 0:e.names.errorEventName};function r(){if(!e.names)throw new e.UnavailableError;return Boolean(document[e.names.fullscreenElementName])}function l(e,r,l){const a=n[e];a&&document.addEventListener(a,r,l)}function a(e,r,l){const a=n[e];a&&document.removeEventListener(a,r,l)}function t(n,r){return new Promise(((t,s)=>{if(!e.names)throw new e.UnavailableError;const c=()=>{a("change",c),a("error",u),t()},u=e=>{a("change",c),a("error",u),s(e)};l("change",c),l("error",u);const o=n[e.names.requestFullscreenName](r);o instanceof Promise&&o.then(c,u)}))}function s(){return new Promise(((n,t)=>{if(!e.names)throw new e.UnavailableError;if(!r)return void n();const s=()=>{a("change",s),a("error",c),n()},c=e=>{a("change",s),a("error",c),t(e)};l("change",s),l("error",c);const u=document[e.names.exitFullscreenName]();u instanceof Promise&&u.then(s,c)}))}e.UnavailableError=FullscreenUnavailableError,e.isSupported=function(){return!!e.names},e.isEnabled=function(){return!!e.names&&Boolean(document[e.names.fullscreenEnabledName])},e.isFullscreen=r,e.getElement=function(){if(!e.names)throw new e.UnavailableError;return document[e.names.fullscreenElementName]},e.on=l,e.off=a,e.request=t,e.exit=s,e.toggle=function(e){return Promise.resolve().then((()=>r()?s():t(e)))},e.onChange=function(e){l("change",e)},e.onError=function(e){l("error",e)}}(fullscreen||(fullscreen={}));export default fullscreen;
1
+ import{es5ErrorCompat}from"@js-toolkit/utils/es5ErrorCompat";import{promisify}from"@js-toolkit/utils/promisify";export class FullscreenUnavailableError extends Error{constructor(){super("Fullscreen is not available"),es5ErrorCompat(this,FullscreenUnavailableError)}}export var fullscreen;!function(e){e.names=[{requestFullscreenName:"requestFullscreen",exitFullscreenName:"exitFullscreen",fullscreenElementName:"fullscreenElement",fullscreenEnabledName:"fullscreenEnabled",changeEventName:"fullscreenchange",errorEventName:"fullscreenerror"},{requestFullscreenName:"webkitRequestFullscreen",exitFullscreenName:"webkitExitFullscreen",fullscreenElementName:"webkitFullscreenElement",fullscreenEnabledName:"webkitFullscreenEnabled",changeEventName:"webkitfullscreenchange",errorEventName:"webkitfullscreenerror"},{requestFullscreenName:"webkitRequestFullScreen",exitFullscreenName:"webkitCancelFullScreen",fullscreenElementName:"webkitCurrentFullScreenElement",fullscreenEnabledName:"webkitCancelFullScreen",changeEventName:"webkitfullscreenchange",errorEventName:"webkitfullscreenerror"},{requestFullscreenName:"mozRequestFullScreen",exitFullscreenName:"mozCancelFullScreen",fullscreenElementName:"mozFullScreenElement",fullscreenEnabledName:"mozFullScreenEnabled",changeEventName:"mozfullscreenchange",errorEventName:"mozfullscreenerror"},{requestFullscreenName:"msRequestFullscreen",exitFullscreenName:"msExitFullscreen",fullscreenElementName:"msFullscreenElement",fullscreenEnabledName:"msFullscreenEnabled",changeEventName:"MSFullscreenChange",errorEventName:"MSFullscreenError"}].find((({exitFullscreenName:e})=>e in document));const n={change:null===e.names||void 0===e.names?void 0:e.names.changeEventName,error:null===e.names||void 0===e.names?void 0:e.names.errorEventName};function r(){if(!e.names)throw new e.UnavailableError;return Boolean(document[e.names.fullscreenElementName])}function l(e,r,l){const t=n[e];t&&document.addEventListener(t,r,l)}function t(e,r,l){const t=n[e];t&&document.removeEventListener(t,r,l)}function a(n,r){return new Promise(((a,s)=>{if(!e.names)throw new e.UnavailableError;const c=()=>{t("change",c),t("error",u),a()},u=e=>{t("change",c),t("error",u),s(e)};l("change",c),l("error",u);const o=n[e.names.requestFullscreenName](r);o instanceof Promise&&o.then(c,u)}))}function s(){return new Promise(((n,a)=>{if(!e.names)throw new e.UnavailableError;if(!r)return void n();const s=()=>{t("change",s),t("error",c),n()},c=e=>{t("change",s),t("error",c),a(e)};l("change",s),l("error",c);const u=document[e.names.exitFullscreenName]();u instanceof Promise&&u.then(s,c)}))}e.UnavailableError=FullscreenUnavailableError,e.isSupported=function(){return!!e.names},e.isEnabled=function(){return!!e.names&&Boolean(document[e.names.fullscreenEnabledName])},e.isFullscreen=r,e.getElement=function(){if(!e.names)throw new e.UnavailableError;return document[e.names.fullscreenElementName]},e.on=l,e.off=t,e.request=a,e.exit=s,e.toggle=function(e){return promisify((()=>r()?s():a(e)))},e.onChange=function(e){l("change",e)},e.onError=function(e){l("error",e)}}(fullscreen||(fullscreen={}));export default fullscreen;
package/getAspectRatio.js CHANGED
@@ -1 +1 @@
1
- import farey from"@jstoolkit/utils/farey";export function getAspectRatio(t,e){const o=t/e,[r,i]=farey(o,50);return{width:r,height:i,ratio:o}}export default getAspectRatio;
1
+ import farey from"@js-toolkit/utils/farey";export function getAspectRatio(t,e){const o=t/e,[r,i]=farey(o,50);return{width:r,height:i,ratio:o}}export default getAspectRatio;
@@ -1,4 +1,4 @@
1
- import { type Awaiter } from '@jstoolkit/utils/getAwaiter';
1
+ import { type Awaiter } from '@js-toolkit/utils/getAwaiter';
2
2
  import { type EmitterTarget, type GetEventType } from './EventEmitterListener.utils';
3
3
  export type EventAwaiter = Awaiter<void>;
4
4
  export declare function getEventAwaiter<T extends EmitterTarget, E extends GetEventType<T>>(target: T, resolveEvent: E | E[], rejectEvent?: E | E[],
@@ -1 +1 @@
1
- import{getAwaiter}from"@jstoolkit/utils/getAwaiter";import{EventEmitterListener}from"./EventEmitterListener";import{isEventEmitterLike}from"./EventEmitterListener.utils";export function getEventAwaiter(t,e,r,i){const o=getAwaiter({lazy:!0}),n=Array.isArray(e)?e:[e],s=Array.isArray(r)?r:[r],E=isEventEmitterLike(t)?t:new EventEmitterListener(t),a=()=>{n.forEach((t=>E.off(t,m))),s.forEach((t=>E.off(t,m)))},c=o.resolve;o.resolve=(...t)=>{a(),c(...t)};const f=o.reject;o.reject=(...t)=>{f(...t),a()};const m=()=>{o.resolve()},v=t=>{const e=i?i(t):t;null!=e&&o.reject(e)};return n.forEach((t=>E.on(t,m))),s.forEach((t=>E.on(t,v))),o}
1
+ import{getAwaiter}from"@js-toolkit/utils/getAwaiter";import{EventEmitterListener}from"./EventEmitterListener";import{isEventEmitterLike}from"./EventEmitterListener.utils";export function getEventAwaiter(t,e,r,i){const o=getAwaiter({lazy:!0}),n=Array.isArray(e)?e:[e],s=Array.isArray(r)?r:[r],E=isEventEmitterLike(t)?t:new EventEmitterListener(t),a=()=>{n.forEach((t=>E.off(t,m))),s.forEach((t=>E.off(t,m)))},c=o.resolve;o.resolve=(...t)=>{a(),c(...t)};const f=o.reject;o.reject=(...t)=>{f(...t),a()};const m=()=>{o.resolve()},v=t=>{const e=i?i(t):t;null!=e&&o.reject(e)};return n.forEach((t=>E.on(t,m))),s.forEach((t=>E.on(t,v))),o}
@@ -1 +1 @@
1
- import{toInt}from"@jstoolkit/utils/toInt";export function getSecondsCounter({onChange:t}={}){const e=new Set;let n=t,o=!1;return{getTotal:()=>e.size,push(t){if(o)throw new Error("SecondsCounter was destroyed.");const r="number"==typeof t?t:"currentTime"in t?t.currentTime:t.data.currentTime;if(null==t)return;const s=toInt(r);s>0&&!e.has(s)&&(e.add(s),n&&n({value:s,total:e.size}))},get onChange(){return n},set onChange(t){n=t},reset(){e.clear()},destroy(){o=!0,n=void 0,this.reset()}}}export default getSecondsCounter;
1
+ import{toInt}from"@js-toolkit/utils/toInt";export function getSecondsCounter({onChange:t}={}){const e=new Set;let n=t,o=!1;return{getTotal:()=>e.size,push(t){if(o)throw new Error("SecondsCounter was destroyed.");const r="number"==typeof t?t:"currentTime"in t?t.currentTime:t.data.currentTime;if(null==t)return;const s=toInt(r);s>0&&!e.has(s)&&(e.add(s),n&&n({value:s,total:e.size}))},get onChange(){return n},set onChange(t){n=t},reset(){e.clear()},destroy(){o=!0,n=void 0,this.reset()}}}export default getSecondsCounter;
@@ -1 +1 @@
1
- import{v4 as uuid}from"uuid";import{IFRAME_CLIENT_READY,IFRAME_HOST_READY,IFRAME_PING,isPingMessage,isTargetReadyMessage}from"./messages";import{getOriginFromMessage}from"./getOriginFromMessage";export function getAutoConnectClient({data:e,target:s=window.parent,isReady:a=(()=>!0),onConnect:t,logger:o=console,messagesTypes:n}){const i={Ping:(null==n?void 0:n.Ping)||IFRAME_PING,TargetReady:(null==n?void 0:n.TargetReady)||IFRAME_HOST_READY,SelfReady:(null==n?void 0:n.SelfReady)||IFRAME_CLIENT_READY},r=uuid();let g;const d=(e,s,a)=>{window!==e&&(e instanceof MessagePort||e instanceof ServiceWorker?(e.postMessage(s),o.debug("Post message to parent MessageEventSource:",s)):(e.postMessage(s,a),o.debug(`Post message to parent window (origin=${a}):`,s)))},u=n=>{if(!n.source||n.source!==s)return;if(!isPingMessage(n.data,i)&&!isTargetReadyMessage(n.data,i))return;o.debug(`Receive message from parent window (origin=${n.origin}):`,n.data);const u=getOriginFromMessage(n);if(isPingMessage(n.data,i))((e,s,t)=>{a()&&d(e,{uid:r,type:i.SelfReady,data:s},t)})(n.source,e,u);else{m();const{data:e}=n.data;[g]=n.ports,t(e,u,g),o.debug("Iframe connected.")}},m=()=>{window.removeEventListener("message",u)};return window.addEventListener("message",u),{ready:(e="*")=>{d(s,{uid:r,type:i.Ping},e)},destroy:()=>{m(),g&&(g.close(),g.onmessage=null,g.onmessageerror=null)}}}
1
+ import{v4 as uuid}from"uuid";import{IFRAME_CLIENT_READY,IFRAME_HOST_READY,IFRAME_PING,isPingMessage,isTargetReadyMessage}from"./messages";import{getOriginFromMessage}from"./getOriginFromMessage";import{isWindowProxy}from"./utils";export function getAutoConnectClient({data:e,target:s=window.parent,isReady:o=(()=>!0),onConnect:a,logger:t=console,messagesTypes:i}){const n={Ping:(null==i?void 0:i.Ping)||IFRAME_PING,TargetReady:(null==i?void 0:i.TargetReady)||IFRAME_HOST_READY,SelfReady:(null==i?void 0:i.SelfReady)||IFRAME_CLIENT_READY},r=uuid();let g;const d=(e,s,o)=>{window!==e&&(isWindowProxy(e)?(e.postMessage(s,o),t.debug(`Post message to parent window (origin=${o}):`,s)):(e.postMessage(s),t.debug("Post message to parent MessageEventSource:",s)))},u=i=>{if(!i.source||i.source!==s)return;if(!isPingMessage(i.data,n)&&!isTargetReadyMessage(i.data,n))return;t.debug(`Receive message from parent window (origin=${i.origin}):`,i.data);const u=getOriginFromMessage(i);if(isPingMessage(i.data,n))((e,s,a)=>{o()&&d(e,{uid:r,type:n.SelfReady,data:s},a)})(i.source,e,u);else{m();const{data:e}=i.data;[g]=i.ports,a(e,u,g),t.debug("Iframe connected.")}},m=()=>{window.removeEventListener("message",u)};return window.addEventListener("message",u),{ready:(e="*")=>{d(s,{uid:r,type:n.Ping},e)},destroy:()=>{m(),g&&(g.close(),g.onmessage=null,g.onmessageerror=null)}}}
@@ -1 +1 @@
1
- import{v4 as uuid}from"uuid";import{onDOMReady}from"../onDOMReady";import{IFRAME_HOST_READY,IFRAME_CLIENT_READY,IFRAME_PING,isPingMessage,isTargetReadyMessage}from"./messages";import{selectFrames}from"./utils";import{getOriginFromMessage}from"./getOriginFromMessage";export function getAutoConnectHost({onSendData:e,logger:o=console,openChannel:s,onConnect:t,messagesTypes:n}){const r={Ping:(null==n?void 0:n.Ping)||IFRAME_PING,TargetReady:(null==n?void 0:n.TargetReady)||IFRAME_CLIENT_READY,SelfReady:(null==n?void 0:n.SelfReady)||IFRAME_HOST_READY};let a,i;const d=uuid(),g=s?new MessageChannel:void 0,u=(e,s,t,n)=>{window!==s&&(s instanceof MessagePort||s instanceof ServiceWorker?(s.postMessage(e,n&&{transfer:n}),o.debug("Post message to MessageEventSource:",e)):(s.postMessage(e,t,n),o.debug(`Post message to iframe (origin=${t}):`,e)))},l=(e,o)=>{u({uid:d,type:r.Ping},e,o)},c=(e,o,s="*")=>{u({uid:d,type:r.SelfReady,data:e},o,s,g?[g.port2]:void 0)},m=n=>{if(!n.source||n.source===window)return;if(!isPingMessage(n.data,r)&&!isTargetReadyMessage(n.data,r))return;o.debug(`Receive message from iframe (origin=${n.origin}):`,n.data);const a=n.source,i=getOriginFromMessage(n);if(isPingMessage(n.data,r))l(a,i);else{c(e?e(a,i):void 0,a,i);const{data:r}=n.data;setTimeout((()=>{s&&g?t(r,a,i,g.port1):s||t(r,a,i),o.debug("Iframe Host connected.")}),0)}},f=()=>{a&&(a(),a=void 0)};return{start:(...e)=>{if(a)return void o.warn("Already started. You should first call `stop`.");const s=onDOMReady((()=>{i=(()=>{const o="function"==typeof e[0]?e[0]():e;return o.length>0?o:void 0})();const o=i||selectFrames();window.addEventListener("message",m);for(let e=0;e<o.length;e+=1){const s=o[e];s.contentWindow&&l(s.contentWindow,"*")}}));a=()=>{s(),window.removeEventListener("message",m),i=void 0}},stop:f,ready:c,destroy:()=>{f(),g&&(g.port1.close(),g.port2.close(),g.port1.onmessage=null,g.port1.onmessageerror=null)}}}
1
+ import{v4 as uuid}from"uuid";import{onDOMReady}from"../onDOMReady";import{IFRAME_HOST_READY,IFRAME_CLIENT_READY,IFRAME_PING,isPingMessage,isTargetReadyMessage}from"./messages";import{isWindowProxy,selectFrames}from"./utils";import{getOriginFromMessage}from"./getOriginFromMessage";export function getAutoConnectHost({onSendData:e,logger:o=console,openChannel:s,onConnect:t,messagesTypes:n}){const r={Ping:(null==n?void 0:n.Ping)||IFRAME_PING,TargetReady:(null==n?void 0:n.TargetReady)||IFRAME_CLIENT_READY,SelfReady:(null==n?void 0:n.SelfReady)||IFRAME_HOST_READY};let a,i;const d=uuid(),g=s?new MessageChannel:void 0,u=(e,s,t,n)=>{window!==s&&(isWindowProxy(s)?(s.postMessage(e,t,n),o.debug(`Post message to iframe (origin=${t}):`,e)):(s.postMessage(e,n&&{transfer:n}),o.debug("Post message to MessageEventSource:",e)))},l=(e,o)=>{u({uid:d,type:r.Ping},e,o)},m=(e,o,s="*")=>{u({uid:d,type:r.SelfReady,data:e},o,s,g?[g.port2]:void 0)},c=n=>{if(!n.source||n.source===window)return;if(!isPingMessage(n.data,r)&&!isTargetReadyMessage(n.data,r))return;o.debug(`Receive message from iframe (origin=${n.origin}):`,n.data);const a=n.source,i=getOriginFromMessage(n);if(isPingMessage(n.data,r))l(a,i);else{m(e?e(a,i):void 0,a,i);const{data:r}=n.data;setTimeout((()=>{s&&g?t(r,a,i,g.port1):s||t(r,a,i),o.debug("Iframe Host connected.")}),0)}},f=()=>{a&&(a(),a=void 0)};return{start:(...e)=>{if(a)return void o.warn("Already started. You should first call `stop`.");const s=onDOMReady((()=>{i=(()=>{const o="function"==typeof e[0]?e[0]():e;return o.length>0?o:void 0})();const o=i||selectFrames();window.addEventListener("message",c);for(let e=0;e<o.length;e+=1){const s=o[e];s.contentWindow&&l(s.contentWindow,"*")}}));a=()=>{s(),window.removeEventListener("message",c),i=void 0}},stop:f,ready:m,destroy:()=>{f(),g&&(g.port1.close(),g.port2.close(),g.port1.onmessage=null,g.port1.onmessageerror=null)}}}
@@ -1 +1 @@
1
- import{v4 as uuid}from"uuid";import{onDOMReady}from"../onDOMReady";import{isPingMessage,isTargetReadyMessage}from"./messages";import{findTarget}from"./utils";import{getOriginFromMessage}from"./getOriginFromMessage";export{getClientMessages,getHostMessages}from"./messages";export function getAutoConnector({id:e,label:t,strictTargets:o=!0,messagesTypes:n,channel:s,logger:i=console,onSendData:a,onConnect:r}){const d=e||uuid(),g=t||d,u=new Map,c="open"===s?new Map:void 0;let l,f;const m=(e,t,o,n,s)=>{window!==t&&(t instanceof MessagePort||t instanceof ServiceWorker?(t.postMessage(e,s&&{transfer:s}),i.debug(`${g}: Post message to MessageEventSource (uid=${n}):`,e)):(t.postMessage(e,o,s),i.debug(`${g}: Post message to iframe (uid=${n},origin=${o}):`,e)))},v=(e,t,o)=>{m({uid:d,type:n.Ping},e,t,o)},p=e=>{var t,f,p,M;if(!e.source||e.source===window)return;if(!isPingMessage(e.data,n)&&!isTargetReadyMessage(e.data,n))return;if(e.data.uid===d)return;const h=e.source,w=e.data.uid;if(i.debug(`${g}: Receive message from iframe (uid=${w},origin=${e.origin}):`,e.data),o&&l){if(!findTarget(h,l))return void i.warn(`${g}: Could not find target (uid=${w}) by message.source.`)}const y=getOriginFromMessage(e);if(isPingMessage(e.data,n)&&!(null===(t=u.get(w))||void 0===t?void 0:t.Ping))return u.set(w,Object.assign(Object.assign({},u.get(w)),{Ping:!0})),void v(h,y,w);let $=!1;if((null===(f=u.get(w))||void 0===f?void 0:f.Ping)&&!(null===(p=u.get(w))||void 0===p?void 0:p.SelfReady)){u.set(w,Object.assign(Object.assign({},u.get(w)),{SelfReady:!0}));const e=c?(()=>{var e;const t=null!==(e=c.get(w))&&void 0!==e?e:new MessageChannel;return c.set(w,t),t.port2})():void 0;((e,t,o,s,i)=>{m({uid:d,type:n.SelfReady,data:e},t,o,s,i?[i]:void 0)})(a?a({target:h,origin:y}):void 0,h,y,w,e),$=!1}if(isTargetReadyMessage(e.data,n)&&(null===(M=u.get(w))||void 0===M?void 0:M.SelfReady)){u.delete(w);const t=(()=>{var t;if("open"===s){const e=null===(t=null==c?void 0:c.get(w))||void 0===t?void 0:t.port1;if(!e)throw new Error("Something went wrong: MessageChannel is not created despite the fact that the `channel` option is `open`.");return e}if("use"===s){const t=e.ports[0];if(!t)throw new Error("MessagePort is not received despite the fact that the `channel` option is `use`. The `channel` option of connector on another side must be equals `open`.");return t}})(),{data:o}=e.data,n=()=>{i.debug(`${g}: Iframe connection established (${d} + ${w}).`),r({data:o,target:h,origin:y},t)};$?setTimeout(n,0):n()}},M=()=>{f&&(f(),f=void 0)};return{start:e=>{if(f)return void i.warn(`${g}: Already started. You should first call \`stop\`.`);const t=()=>{l=(()=>{const t="function"==typeof e?e():e;return t.length>0?t:void 0})(),window.addEventListener("message",p);const t=null!=l?l:[];for(let e=0;e<t.length;e+=1){const o=t[e],n=o instanceof HTMLIFrameElement?o.contentWindow:o;n&&n!==window&&v(n,"*","")}},o="function"==typeof e?onDOMReady(t):t();f=()=>{o&&o(),window.removeEventListener("message",p),l=void 0}},stop:M,destroy:()=>{M(),u.clear(),c&&(c.forEach((e=>{e.port1.close(),e.port2.close()})),c.clear())}}}
1
+ import{v4 as uuid}from"uuid";import{onDOMReady}from"../onDOMReady";import{isPingMessage,isTargetReadyMessage}from"./messages";import{findTarget,isWindowProxy}from"./utils";import{getOriginFromMessage}from"./getOriginFromMessage";export{getClientMessages,getHostMessages}from"./messages";export function getAutoConnector({id:e,label:t,strictTargets:o=!0,messagesTypes:n,channel:s,logger:i=console,onSendData:a,onConnect:r}){const d=e||uuid(),g=t||d,u=new Map,c="open"===s?new Map:void 0;let l,f;const m=(e,t,o,n,s)=>{window!==t&&(isWindowProxy(t)?(t.postMessage(e,o,s),i.debug(`${g}: Post message to iframe (uid=${n},origin=${o}):`,e)):(t.postMessage(e,s&&{transfer:s}),i.debug(`${g}: Post message to MessageEventSource (uid=${n}):`,e)))},p=(e,t,o)=>{m({uid:d,type:n.Ping},e,t,o)},v=e=>{var t,f,v,w;if(!e.source||e.source===window)return;if(!isPingMessage(e.data,n)&&!isTargetReadyMessage(e.data,n))return;if(e.data.uid===d)return;const M=e.source,h=e.data.uid;if(i.debug(`${g}: Receive message from iframe (uid=${h},origin=${e.origin}):`,e.data),o&&l){if(!findTarget(M,l))return void i.warn(`${g}: Could not find target (uid=${h}) by message.source.`)}const y=getOriginFromMessage(e);if(isPingMessage(e.data,n)&&!(null===(t=u.get(h))||void 0===t?void 0:t.Ping))return u.set(h,Object.assign(Object.assign({},u.get(h)),{Ping:!0})),void p(M,y,h);let $=!1;if((null===(f=u.get(h))||void 0===f?void 0:f.Ping)&&!(null===(v=u.get(h))||void 0===v?void 0:v.SelfReady)){u.set(h,Object.assign(Object.assign({},u.get(h)),{SelfReady:!0}));const e=c?(()=>{var e;const t=null!==(e=c.get(h))&&void 0!==e?e:new MessageChannel;return c.set(h,t),t.port2})():void 0;((e,t,o,s,i)=>{m({uid:d,type:n.SelfReady,data:e},t,o,s,i?[i]:void 0)})(a?a({target:M,origin:y}):void 0,M,y,h,e),$=!1}if(isTargetReadyMessage(e.data,n)&&(null===(w=u.get(h))||void 0===w?void 0:w.SelfReady)){u.delete(h);const t=(()=>{var t;if("open"===s){const e=null===(t=null==c?void 0:c.get(h))||void 0===t?void 0:t.port1;if(!e)throw new Error("Something went wrong: MessageChannel is not created despite the fact that the `channel` option is `open`.");return e}if("use"===s){const t=e.ports[0];if(!t)throw new Error("MessagePort is not received despite the fact that the `channel` option is `use`. The `channel` option of connector on another side must be equals `open`.");return t}})(),{data:o}=e.data,n=()=>{i.debug(`${g}: Iframe connection established (${d} + ${h}).`),r({data:o,target:M,origin:y},t)};$?setTimeout(n,0):n()}},w=()=>{f&&(f(),f=void 0)};return{start:e=>{if(f)return void i.warn(`${g}: Already started. You should first call \`stop\`.`);const t=()=>{l=(()=>{const t="function"==typeof e?e():e;return t.length>0?t:void 0})(),window.addEventListener("message",v);const t=null!=l?l:[];for(let e=0;e<t.length;e+=1){const o=t[e],n=o instanceof HTMLIFrameElement?o.contentWindow:o;n&&n!==window&&p(n,"*","")}},o="function"==typeof e?onDOMReady(t):t();f=()=>{o&&o(),window.removeEventListener("message",v),l=void 0}},stop:w,destroy:()=>{w(),u.clear(),c&&(c.forEach((e=>{e.port1.close(),e.port2.close()})),c.clear())}}}
package/iframe/utils.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export type Target = HTMLIFrameElement | Window;
2
2
  export declare function selectFrames(): HTMLCollectionOf<HTMLIFrameElement>;
3
3
  export declare function findTarget<T extends Target>(source: Window, targets: ArrayLike<T>): T | undefined;
4
+ export declare function isWindowProxy(target: MessageEventSource): target is Window;
package/iframe/utils.js CHANGED
@@ -1 +1 @@
1
- export function selectFrames(){return document.getElementsByTagName("iframe")}export function findTarget(e,t){for(let n=0;n<t.length;n+=1){const r=t[n];if((r instanceof HTMLIFrameElement?r.contentWindow:r)===e)return r}}
1
+ export function selectFrames(){return document.getElementsByTagName("iframe")}export function findTarget(e,n){for(let t=0;t<n.length;t+=1){const o=n[t];if((o instanceof HTMLIFrameElement?o.contentWindow:o)===e)return o}}export function isWindowProxy(e){return!(void 0!==window.MessagePort&&e instanceof MessagePort||void 0!==window.ServiceWorker&&e instanceof ServiceWorker)}
@@ -4,5 +4,3 @@ declare global {
4
4
  }
5
5
  }
6
6
  export declare function getMediaSource(): typeof MediaSource | undefined;
7
- /** Media Source Extensions */
8
- export declare function isMSESupported(): boolean;
@@ -0,0 +1 @@
1
+ export function getMediaSource(){return window.MediaSource||window.WebKitMediaSource}
@@ -0,0 +1,2 @@
1
+ export * from './getMediaSource';
2
+ export * from './isMSESupported';
@@ -0,0 +1 @@
1
+ export*from"./getMediaSource";export*from"./isMSESupported";
@@ -0,0 +1 @@
1
+ export declare function isMSESupported(): boolean;
@@ -0,0 +1 @@
1
+ import{getMediaSource}from"./getMediaSource";export function isMSESupported(){var e;return!!(null===(e=getMediaSource())||void 0===e?void 0:e.isTypeSupported)}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@js-toolkit/web-utils",
3
- "version": "1.47.0",
3
+ "version": "1.48.0",
4
4
  "description": "Web utils",
5
5
  "author": "VZH",
6
6
  "license": "MIT",
@@ -13,33 +13,33 @@
13
13
  "copy:configs": "copyfiles package.json .npmignore README.md LICENSE ./dist/",
14
14
  "minify": "node-utils-minify --replace ./dist",
15
15
  "build": "npm run clean && tsc --build ./tsconfig.json && npm run minify",
16
- "patch-publish": "npm run build && npm version patch --no-workspaces-update -m 'v%s' && npm run copy:configs && cd ./dist && npm publish --access public && git push origin master --follow-tags",
17
- "minor-publish": "npm run build && npm version minor --no-workspaces-update -m 'v%s' && npm run copy:configs && cd ./dist && npm publish --access public && git push origin master --follow-tags"
16
+ "patch-publish": "npm run build && npm version patch --force --no-workspaces-update -m 'v%s' && npm run copy:configs && cd ./dist && npm publish --access public && git push origin master --follow-tags",
17
+ "minor-publish": "npm run build && npm version minor --force --no-workspaces-update -m 'v%s' && npm run copy:configs && cd ./dist && npm publish --access public && git push origin master --follow-tags"
18
18
  },
19
19
  "optionalDependencies": {
20
20
  "@js-toolkit/node-utils": "^1.1.4"
21
21
  },
22
22
  "devDependencies": {
23
23
  "@js-toolkit/configs": "^3.87.5",
24
- "@js-toolkit/utils": "^1.49.1",
25
- "@types/ua-parser-js": "^0.7.36",
26
- "@types/uuid": "^9.0.2",
27
- "@typescript-eslint/eslint-plugin": "^6.3.0",
28
- "@typescript-eslint/parser": "^6.3.0",
24
+ "@js-toolkit/utils": "^1.49.6",
25
+ "@types/ua-parser-js": "^0.7.37",
26
+ "@types/uuid": "^9.0.4",
27
+ "@typescript-eslint/eslint-plugin": "^6.7.4",
28
+ "@typescript-eslint/parser": "^6.7.4",
29
29
  "copyfiles": "^2.4.1",
30
- "eslint": "^8.47.0",
30
+ "eslint": "^8.50.0",
31
31
  "eslint-config-airbnb-base": "^15.0.0",
32
32
  "eslint-config-prettier": "^9.0.0",
33
- "eslint-plugin-import": "^2.28.0",
33
+ "eslint-plugin-import": "^2.28.1",
34
34
  "eslint-plugin-prettier": "^5.0.0",
35
35
  "eventemitter3": "^5.0.1",
36
- "prettier": "^3.0.1",
36
+ "prettier": "^3.0.3",
37
37
  "reconnecting-websocket": "^4.4.0",
38
- "rimraf": "^5.0.1",
39
- "terser": "^5.19.2",
40
- "typescript": "^5.1.6",
41
- "ua-parser-js": "^1.0.35",
42
- "uuid": "^9.0.0",
38
+ "rimraf": "^5.0.5",
39
+ "terser": "^5.20.0",
40
+ "typescript": "^5.2.2",
41
+ "ua-parser-js": "^1.0.36",
42
+ "uuid": "^9.0.1",
43
43
  "webpack": "^5.88.2",
44
44
  "yargs": "^17.7.2"
45
45
  }
@@ -6,4 +6,4 @@ declare class Semver {
6
6
  toString(): string;
7
7
  }
8
8
  export declare function getIOSVersion(): Semver | undefined;
9
- export default getIOSVersion;
9
+ export {};
@@ -0,0 +1 @@
1
+ import{getUAParserResult}from"./getUAParserResult";import{isIOS}from"./isIOS";class Semver{constructor(e,r,t){this.major=e,this.minor=r,this.patch=t}toString(){return`${this.major}_${this.minor}_${this.patch}`}}let memo;export function getIOSVersion(){if(void 0===memo){const{os:e}=getUAParserResult(),r=isIOS()&&e.version&&/(\d+)\.(\d+)(?:\.(\d+))?/.exec(e.version);memo=r?new Semver(parseInt(r[1],10)||0,parseInt(r[2],10)||0,parseInt(r[3],10)||0):null}return null!=memo?memo:void 0}
@@ -1,2 +1 @@
1
1
  export declare function isAirPlayAvailable(): boolean;
2
- export default isAirPlayAvailable;
@@ -1 +1 @@
1
- export function isAirPlayAvailable(){return!!window.WebKitPlaybackTargetAvailabilityEvent}export default isAirPlayAvailable;
1
+ export function isAirPlayAvailable(){return!!window.WebKitPlaybackTargetAvailabilityEvent}
@@ -1,2 +1 @@
1
1
  export declare function isAndroid(): boolean;
2
- export default isAndroid;
@@ -1 +1 @@
1
- import{getUAParserResult}from"./getUAParserResult";export function isAndroid(){const r=getUAParserResult().os.name;return"Android"===r||"Android-x86"===r}export default isAndroid;
1
+ import{getUAParserResult}from"./getUAParserResult";export function isAndroid(){const r=getUAParserResult().os.name;return"Android"===r||"Android-x86"===r}
@@ -1,2 +1 @@
1
1
  export declare function isIOS(): boolean;
2
- export default isIOS;
@@ -0,0 +1 @@
1
+ import{getUAParserResult}from"./getUAParserResult";import{isMobile}from"./isMobile";export function isIOS(){const e=getUAParserResult();return"iOS"===e.os.name||isMobile()&&"Apple"===e.device.vendor}
@@ -1,2 +1 @@
1
1
  export declare function isMacOS(): boolean;
2
- export default isMacOS;
@@ -0,0 +1 @@
1
+ import{getUAParserResult}from"./getUAParserResult";import{isMobile}from"./isMobile";export function isMacOS(){const e=getUAParserResult().os.name;return("Mac OS"===e||"macOS"===e)&&!isMobile()}
@@ -1,2 +1 @@
1
1
  export declare function isMobile(): boolean;
2
- export default isMobile;
@@ -0,0 +1 @@
1
+ import{getUAParserResult}from"./getUAParserResult";export function isMobile(){const e=getUAParserResult(),t=e.device.type;return!!("mobile"===t||"tablet"===t||!t&&"Apple"===e.device.vendor&&navigator.maxTouchPoints&&navigator.maxTouchPoints>2)}
@@ -1,2 +1 @@
1
1
  export declare function isSafari(): boolean;
2
- export default isSafari;
@@ -0,0 +1 @@
1
+ import{getUAParserResult}from"./getUAParserResult";import{isIOS}from"./isIOS";import{isMacOS}from"./isMacOS";export function isSafari(){const r=getUAParserResult().browser.name;return"Safari"===r||"Mobile Safari"===r||"WebKit"===r&&(isIOS()||isMacOS())}
@@ -1,2 +1 @@
1
1
  export declare function isStandaloneApp(): boolean;
2
- export default isStandaloneApp;
@@ -1 +1 @@
1
- export function isStandaloneApp(){return window.matchMedia("(display-mode: standalone)").matches}export default isStandaloneApp;
1
+ export function isStandaloneApp(){return window.matchMedia("(display-mode: standalone)").matches}
package/takeSnapshot.js CHANGED
@@ -1 +1 @@
1
- import{hasIn}from"@jstoolkit/utils/hasIn";export function get2dContextError(){return new Error("Failed to get canvas 2d context.")}const getDefaultWidth=t=>t instanceof HTMLVideoElement?t.videoWidth:hasIn(t,"displayWidth")?t.displayWidth:t.width instanceof SVGAnimatedLength?t.width.animVal.value:t.width,getDefaultHeight=t=>t instanceof HTMLVideoElement?t.videoHeight:hasIn(t,"displayHeight")?t.displayHeight:t.height instanceof SVGAnimatedLength?t.height.animVal.value:t.height;export function takeSnapshot(t,{width:e=getDefaultWidth(t),height:i=getDefaultHeight(t),type:n="image/jpeg",quality:a=1}={}){const o=document.createElement("canvas");o.width=e,o.height=i;const h=o.getContext("2d");if(!h)throw get2dContextError();return h.drawImage(t,0,0),o.toDataURL(n,a)}export function takeSnapshotAsync(t,{width:e=getDefaultWidth(t),height:i=getDefaultHeight(t),type:n="image/jpeg",quality:a=1}={}){return new Promise(((o,h)=>{const d=document.createElement("canvas");d.width=e,d.height=i;const g=d.getContext("2d");if(!g)throw get2dContextError();g.drawImage(t,0,0),d.toBlob((t=>{null==t?h(new Error("Unable get blob")):o(t)}),n,a)}))}
1
+ import{hasIn}from"@js-toolkit/utils/hasIn";export function get2dContextError(){return new Error("Failed to get canvas 2d context.")}const getDefaultWidth=t=>t instanceof HTMLVideoElement?t.videoWidth:hasIn(t,"displayWidth")?t.displayWidth:t.width instanceof SVGAnimatedLength?t.width.animVal.value:t.width,getDefaultHeight=t=>t instanceof HTMLVideoElement?t.videoHeight:hasIn(t,"displayHeight")?t.displayHeight:t.height instanceof SVGAnimatedLength?t.height.animVal.value:t.height;export function takeSnapshot(t,{width:e=getDefaultWidth(t),height:i=getDefaultHeight(t),type:n="image/jpeg",quality:a=1}={}){const o=document.createElement("canvas");o.width=e,o.height=i;const h=o.getContext("2d");if(!h)throw get2dContextError();return h.drawImage(t,0,0),o.toDataURL(n,a)}export function takeSnapshotAsync(t,{width:e=getDefaultWidth(t),height:i=getDefaultHeight(t),type:n="image/jpeg",quality:a=1}={}){return new Promise(((o,h)=>{const d=document.createElement("canvas");d.width=e,d.height=i;const g=d.getContext("2d");if(!g)throw get2dContextError();g.drawImage(t,0,0),d.toBlob((t=>{null==t?h(new Error("Unable get blob")):o(t)}),n,a)}))}
package/types/refs.d.ts CHANGED
@@ -1 +1 @@
1
- import '@jstoolkit/utils/types';
1
+ import '@js-toolkit/utils/types';
package/types/refs.js CHANGED
@@ -1 +1 @@
1
- import"@jstoolkit/utils/types";
1
+ import"@js-toolkit/utils/types";
@@ -1,4 +1,4 @@
1
- import DataEventEmitter, { type DataEventListener, type DataEventMap } from '@jstoolkit/utils/DataEventEmitter';
1
+ import DataEventEmitter, { type DataEventListener, type DataEventMap } from '@js-toolkit/utils/DataEventEmitter';
2
2
  import * as sdpUtils from './sdputils';
3
3
  export declare class PeerConnection extends DataEventEmitter<PeerConnection.EventMap, PeerConnection> {
4
4
  readonly options: PeerConnection.Options;
@@ -1 +1 @@
1
- import{__awaiter}from"tslib";import DataEventEmitter,{}from"@jstoolkit/utils/DataEventEmitter";import getErrorMessage from"@jstoolkit/utils/getErrorMessage";import{hasIn}from"@jstoolkit/utils/hasIn";import*as sdpUtils from"./sdputils";export class PeerConnection extends DataEventEmitter{get Events(){return PeerConnection.Events}constructor(e={}){var t;super(),this.options=e,this.logger=null!==(t=e.logger)&&void 0!==t?t:console,this.pc=this.createPC()}clear(){this.pc.onsignalingstatechange=null,this.pc.onconnectionstatechange=null,this.pc.oniceconnectionstatechange=null,this.pc.ontrack=null,this.pc.onnegotiationneeded=null,this.pc.onicecandidate=null,this.pc.onicecandidateerror=null}createPC(){const e=new RTCPeerConnection(this.options.rtc);return e.onsignalingstatechange=()=>{this.logger.debug(`Signaling state changed to: ${e.signalingState}`),"closed"===e.signalingState&&(this.emit(this.Events.Closed),this.clear())},hasIn(RTCPeerConnection.prototype,"onconnectionstatechange")?e.onconnectionstatechange=()=>{this.logger.debug(`Connection state changed to: ${e.connectionState}`),"connected"===e.connectionState?this.emit(this.Events.Connected):"disconnected"===e.connectionState&&this.emit(this.Events.Disconnected)}:e.oniceconnectionstatechange=()=>{this.logger.debug(`ICE connection state changed to: ${e.iceConnectionState}`),"connected"===e.iceConnectionState?this.emit(this.Events.Connected):"disconnected"===e.iceConnectionState&&this.emit(this.Events.Disconnected)},e.ontrack=({streams:e,track:t})=>{if(this.logger.debug("Remote stream received.",e.length,t.kind),0===e.length)return;const[n]=e;n.onremovetrack=()=>{this.logger.debug("onremovetrack"),this.emit(this.Events.RemoteStreamChanged,n)},n.onaddtrack=()=>{this.logger.debug("onaddtrack"),this.emit(this.Events.RemoteStreamChanged,n)},this.emit(this.Events.RemoteStreamChanged,n)},e.onnegotiationneeded=()=>{const{iceConnectionState:t}=e;"connected"!==t&&"completed"!==t||(this.logger.debug("Reinitializing connection..."),this.emit(this.Events.ReinitializingConnectionRequired))},e.onicecandidate=({candidate:e})=>{e?sdpUtils.isValidIceCandidate(e)&&this.emit(this.Events.LocalIceCandidate,e):this.emit(this.Events.EndOfIceCandidates)},e.onicecandidateerror=e=>{if(e instanceof RTCPeerConnectionIceErrorEvent){const{errorCode:t,errorText:n,hostCandidate:i,url:o}=e;this.logger.warn(`ICE candidate error: errorCode=${t}, errorText=${n}, hostCandidate=${i}, url=${o}`)}else this.logger.warn(`ICE candidate error: ${getErrorMessage(e)}`)},e}setLocalDescription(e,t){return __awaiter(this,void 0,void 0,(function*(){const n=sdpUtils.prepareLocalDescription(t,this.options.codecs);return yield e.setLocalDescription(n),n}))}setRemoteDescription(e,t){return __awaiter(this,void 0,void 0,(function*(){const n=sdpUtils.prepareRemoteDescription(t,this.options.codecs);return yield e.setRemoteDescription(n),n}))}isConnected(){return"connected"===this.pc.iceConnectionState||"completed"===this.pc.iceConnectionState}isClosed(){return"closed"===this.pc.signalingState}addIceCandidate(e){return this.pc.addIceCandidate(e)}attachStream(e){const t=this.pc.getSenders(),n=t.length?e.getTracks().filter((e=>!t.find((({track:t})=>!!t&&t.id===e.id)))):e.getTracks();n.length?(n.forEach((t=>this.pc.addTrack(t,e))),this.logger.debug(`Attached ${n.length} track(s) to a peer connection.`)):this.logger.debug("No tracks to attach to a peer connection.")}reattachStream(e){const t=this.pc.iceConnectionState;if("new"!==t&&"connected"!==t&&"completed"!==t)return;const n=e?e.getTracks():[];this.pc.getSenders().forEach((e=>{const{track:t}=e;!t||"ended"!==t.readyState&&n.find((e=>e.id===t.id))||(this.pc.removeTrack(e),this.logger.debug(`'${t&&t.kind}' track is removed from a peer connection.`))})),e&&this.attachStream(e)}createOffer(){return __awaiter(this,void 0,void 0,(function*(){const e=yield this.pc.createOffer(this.options.offerOptions);return this.setLocalDescription(this.pc,e)}))}createAnswer(e){return __awaiter(this,void 0,void 0,(function*(){yield this.setRemoteDescription(this.pc,e);const t=yield this.pc.createAnswer(this.options.offerOptions);return this.setLocalDescription(this.pc,t)}))}applyAnswer(e){return this.setRemoteDescription(this.pc,e)}reconnect(){this.close(),this.pc=this.createPC()}close(){this.pc.close(),this.pc.onsignalingstatechange&&(this.emit(this.Events.Closed),this.clear())}destroy(){this.close(),this.removeAllListeners()}}!function(e){let t;!function(e){e.LocalIceCandidate="LocalIceCandidate",e.EndOfIceCandidates="EndOfIceCandidates",e.Connected="Connected",e.Disconnected="Disconnected",e.RemoteStreamChanged="RemoteStreamChanged",e.ReinitializingConnectionRequired="ReinitializingConnectionRequired",e.Closed="Closed"}(t=e.Events||(e.Events={}))}(PeerConnection||(PeerConnection={}));
1
+ import{__awaiter}from"tslib";import DataEventEmitter,{}from"@js-toolkit/utils/DataEventEmitter";import getErrorMessage from"@js-toolkit/utils/getErrorMessage";import{hasIn}from"@js-toolkit/utils/hasIn";import*as sdpUtils from"./sdputils";export class PeerConnection extends DataEventEmitter{get Events(){return PeerConnection.Events}constructor(e={}){var t;super(),this.options=e,this.logger=null!==(t=e.logger)&&void 0!==t?t:console,this.pc=this.createPC()}clear(){this.pc.onsignalingstatechange=null,this.pc.onconnectionstatechange=null,this.pc.oniceconnectionstatechange=null,this.pc.ontrack=null,this.pc.onnegotiationneeded=null,this.pc.onicecandidate=null,this.pc.onicecandidateerror=null}createPC(){const e=new RTCPeerConnection(this.options.rtc);return e.onsignalingstatechange=()=>{this.logger.debug(`Signaling state changed to: ${e.signalingState}`),"closed"===e.signalingState&&(this.emit(this.Events.Closed),this.clear())},hasIn(RTCPeerConnection.prototype,"onconnectionstatechange")?e.onconnectionstatechange=()=>{this.logger.debug(`Connection state changed to: ${e.connectionState}`),"connected"===e.connectionState?this.emit(this.Events.Connected):"disconnected"===e.connectionState&&this.emit(this.Events.Disconnected)}:e.oniceconnectionstatechange=()=>{this.logger.debug(`ICE connection state changed to: ${e.iceConnectionState}`),"connected"===e.iceConnectionState?this.emit(this.Events.Connected):"disconnected"===e.iceConnectionState&&this.emit(this.Events.Disconnected)},e.ontrack=({streams:e,track:t})=>{if(this.logger.debug("Remote stream received.",e.length,t.kind),0===e.length)return;const[n]=e;n.onremovetrack=()=>{this.logger.debug("onremovetrack"),this.emit(this.Events.RemoteStreamChanged,n)},n.onaddtrack=()=>{this.logger.debug("onaddtrack"),this.emit(this.Events.RemoteStreamChanged,n)},this.emit(this.Events.RemoteStreamChanged,n)},e.onnegotiationneeded=()=>{const{iceConnectionState:t}=e;"connected"!==t&&"completed"!==t||(this.logger.debug("Reinitializing connection..."),this.emit(this.Events.ReinitializingConnectionRequired))},e.onicecandidate=({candidate:e})=>{e?sdpUtils.isValidIceCandidate(e)&&this.emit(this.Events.LocalIceCandidate,e):this.emit(this.Events.EndOfIceCandidates)},e.onicecandidateerror=e=>{if(e instanceof RTCPeerConnectionIceErrorEvent){const{errorCode:t,errorText:n,hostCandidate:i,url:o}=e;this.logger.warn(`ICE candidate error: errorCode=${t}, errorText=${n}, hostCandidate=${i}, url=${o}`)}else this.logger.warn(`ICE candidate error: ${getErrorMessage(e)}`)},e}setLocalDescription(e,t){return __awaiter(this,void 0,void 0,(function*(){const n=sdpUtils.prepareLocalDescription(t,this.options.codecs);return yield e.setLocalDescription(n),n}))}setRemoteDescription(e,t){return __awaiter(this,void 0,void 0,(function*(){const n=sdpUtils.prepareRemoteDescription(t,this.options.codecs);return yield e.setRemoteDescription(n),n}))}isConnected(){return"connected"===this.pc.iceConnectionState||"completed"===this.pc.iceConnectionState}isClosed(){return"closed"===this.pc.signalingState}addIceCandidate(e){return this.pc.addIceCandidate(e)}attachStream(e){const t=this.pc.getSenders(),n=t.length?e.getTracks().filter((e=>!t.find((({track:t})=>!!t&&t.id===e.id)))):e.getTracks();n.length?(n.forEach((t=>this.pc.addTrack(t,e))),this.logger.debug(`Attached ${n.length} track(s) to a peer connection.`)):this.logger.debug("No tracks to attach to a peer connection.")}reattachStream(e){const t=this.pc.iceConnectionState;if("new"!==t&&"connected"!==t&&"completed"!==t)return;const n=e?e.getTracks():[];this.pc.getSenders().forEach((e=>{const{track:t}=e;!t||"ended"!==t.readyState&&n.find((e=>e.id===t.id))||(this.pc.removeTrack(e),this.logger.debug(`'${t&&t.kind}' track is removed from a peer connection.`))})),e&&this.attachStream(e)}createOffer(){return __awaiter(this,void 0,void 0,(function*(){const e=yield this.pc.createOffer(this.options.offerOptions);return this.setLocalDescription(this.pc,e)}))}createAnswer(e){return __awaiter(this,void 0,void 0,(function*(){yield this.setRemoteDescription(this.pc,e);const t=yield this.pc.createAnswer(this.options.offerOptions);return this.setLocalDescription(this.pc,t)}))}applyAnswer(e){return this.setRemoteDescription(this.pc,e)}reconnect(){this.close(),this.pc=this.createPC()}close(){this.pc.close(),this.pc.onsignalingstatechange&&(this.emit(this.Events.Closed),this.clear())}destroy(){this.close(),this.removeAllListeners()}}!function(e){let t;!function(e){e.LocalIceCandidate="LocalIceCandidate",e.EndOfIceCandidates="EndOfIceCandidates",e.Connected="Connected",e.Disconnected="Disconnected",e.RemoteStreamChanged="RemoteStreamChanged",e.ReinitializingConnectionRequired="ReinitializingConnectionRequired",e.Closed="Closed"}(t=e.Events||(e.Events={}))}(PeerConnection||(PeerConnection={}));
@@ -1,5 +1,5 @@
1
1
  import ReconnectingWebSocket, { type ErrorEvent, type Message, type Options as BaseOptions, type UrlProvider } from 'reconnecting-websocket';
2
- import DataEventEmitter, { type DataEventListener, type DataEventMap } from '@jstoolkit/utils/DataEventEmitter';
2
+ import DataEventEmitter, { type DataEventListener, type DataEventMap } from '@js-toolkit/utils/DataEventEmitter';
3
3
  export declare class WSController<TData = unknown> extends DataEventEmitter<WSController.EventMap<TData>, WSController<TData>> {
4
4
  get Events(): typeof WSController.Events;
5
5
  readonly logger: NonNullable<WSController.Options['logger']>;
@@ -1 +1 @@
1
- import{__rest}from"tslib";import ReconnectingWebSocket,{}from"reconnecting-websocket";import DataEventEmitter,{}from"@jstoolkit/utils/DataEventEmitter";import delayed from"@jstoolkit/utils/delayed";import{EventEmitterListener}from"../EventEmitterListener";function getNotConnectedError(){return new Error("The object is not connected yet.")}export class WSController extends DataEventEmitter{get Events(){return WSController.Events}constructor(e,t){super();const n=null!=t?t:{},{logger:s,protocols:o,binaryType:i,idleTimeout:r,halfOpenDetection:c,startClosed:l}=n,a=__rest(n,["logger","protocols","binaryType","idleTimeout","halfOpenDetection","startClosed"]);this.logger=null!=s?s:console,this.ws=new ReconnectingWebSocket(e,o,Object.assign(Object.assign({},a),{startClosed:!0})),null!=i&&(this.ws.binaryType=i),this.listener=new EventEmitterListener(this.ws),r&&r>0&&(this.reconnectOnIdle=delayed((()=>{this.logger.info(`WS connection reconnecting after ${r}ms due to inactivity.`),this.ws.reconnect()}),r)),this.halfOpen=(()=>{if(!c)return;const{pingTimeout:e=12e3,outMessage:t=(()=>JSON.stringify({type:"pong"})),inMessageFilter:n=(e=>e&&"object"==typeof e&&"ping"===e.type)}=c,s=delayed((()=>{this.logger.info(`WS connection reconnecting after ${e}ms due to the probability of a half-open connection.`),this.ws.reconnect()}),e),o=()=>{s(),this.ws.send("function"!=typeof t||t instanceof Blob?t:t())};return{heartbeat:o,cancel:()=>s.cancel(),onMessage:({data:e})=>{n(e)?o():s()}}})(),this.listener.on("open",(()=>{var e;this.reconnectOnIdle&&this.reconnectOnIdle(),null===(e=this.halfOpen)||void 0===e||e.heartbeat(),this.emit(this.Events.Connected)})).on("close",(({code:e})=>{var n,s;null===(n=this.reconnectOnIdle)||void 0===n||n.cancel(),null===(s=this.halfOpen)||void 0===s||s.cancel(),null!=(null==t?void 0:t.maxRetries)&&this.ws.readyState===this.ws.CLOSED&&this.ws.retryCount===t.maxRetries&&this.close(e,`Failed to connect after ${t.maxRetries} attempts.`)})).on("message",(e=>{var t;this.reconnectOnIdle&&this.reconnectOnIdle(),null===(t=this.halfOpen)||void 0===t||t.onMessage(e),this.emit(this.Events.Message,e)})).on("error",(({error:e,message:t})=>{this.emit(this.Events.Error,{error:e,message:t})})),this.halfOpen&&(this.isConnected()||this.ws.readyState===this.ws.CONNECTING)&&this.halfOpen.heartbeat(),l||this.connect()}isConnected(){return this.ws.readyState===this.ws.OPEN}getUrl(){return this.ws.url}connect(){this.ws.reconnect()}send(e){if(!this.ws)throw getNotConnectedError();this.ws.send(e)}close(e,t){const n=!!this.ws;try{this.reconnectOnIdle&&this.reconnectOnIdle.cancel(),this.halfOpen&&this.halfOpen.cancel(),this.ws.close(e,t)}catch(e){this.logger.warn(e)}n&&this.emit(this.Events.Closed,t?{reason:t}:void 0)}destroy(){this.close(),this.listener.removeAllListeners(),this.removeAllListeners()}}!function(e){let t;!function(e){e.Connected="Connected",e.Message="Message",e.Error="Error",e.Closed="Closed"}(t=e.Events||(e.Events={}))}(WSController||(WSController={}));
1
+ import{__rest}from"tslib";import ReconnectingWebSocket,{}from"reconnecting-websocket";import DataEventEmitter,{}from"@js-toolkit/utils/DataEventEmitter";import delayed from"@js-toolkit/utils/delayed";import{EventEmitterListener}from"../EventEmitterListener";function getNotConnectedError(){return new Error("The object is not connected yet.")}export class WSController extends DataEventEmitter{get Events(){return WSController.Events}constructor(e,t){super();const n=null!=t?t:{},{logger:s,protocols:o,binaryType:i,idleTimeout:r,halfOpenDetection:c,startClosed:l}=n,a=__rest(n,["logger","protocols","binaryType","idleTimeout","halfOpenDetection","startClosed"]);this.logger=null!=s?s:console,this.ws=new ReconnectingWebSocket(e,o,Object.assign(Object.assign({},a),{startClosed:!0})),null!=i&&(this.ws.binaryType=i),this.listener=new EventEmitterListener(this.ws),r&&r>0&&(this.reconnectOnIdle=delayed((()=>{this.logger.info(`WS connection reconnecting after ${r}ms due to inactivity.`),this.ws.reconnect()}),r)),this.halfOpen=(()=>{if(!c)return;const{pingTimeout:e=12e3,outMessage:t=(()=>JSON.stringify({type:"pong"})),inMessageFilter:n=(e=>e&&"object"==typeof e&&"ping"===e.type)}=c,s=delayed((()=>{this.logger.info(`WS connection reconnecting after ${e}ms due to the probability of a half-open connection.`),this.ws.reconnect()}),e),o=()=>{s(),this.ws.send("function"!=typeof t||t instanceof Blob?t:t())};return{heartbeat:o,cancel:()=>s.cancel(),onMessage:({data:e})=>{n(e)?o():s()}}})(),this.listener.on("open",(()=>{var e;this.reconnectOnIdle&&this.reconnectOnIdle(),null===(e=this.halfOpen)||void 0===e||e.heartbeat(),this.emit(this.Events.Connected)})).on("close",(({code:e})=>{var n,s;null===(n=this.reconnectOnIdle)||void 0===n||n.cancel(),null===(s=this.halfOpen)||void 0===s||s.cancel(),null!=(null==t?void 0:t.maxRetries)&&this.ws.readyState===this.ws.CLOSED&&this.ws.retryCount===t.maxRetries&&this.close(e,`Failed to connect after ${t.maxRetries} attempts.`)})).on("message",(e=>{var t;this.reconnectOnIdle&&this.reconnectOnIdle(),null===(t=this.halfOpen)||void 0===t||t.onMessage(e),this.emit(this.Events.Message,e)})).on("error",(({error:e,message:t})=>{this.emit(this.Events.Error,{error:e,message:t})})),this.halfOpen&&(this.isConnected()||this.ws.readyState===this.ws.CONNECTING)&&this.halfOpen.heartbeat(),l||this.connect()}isConnected(){return this.ws.readyState===this.ws.OPEN}getUrl(){return this.ws.url}connect(){this.ws.reconnect()}send(e){if(!this.ws)throw getNotConnectedError();this.ws.send(e)}close(e,t){const n=!!this.ws;try{this.reconnectOnIdle&&this.reconnectOnIdle.cancel(),this.halfOpen&&this.halfOpen.cancel(),this.ws.close(e,t)}catch(e){this.logger.warn(e)}n&&this.emit(this.Events.Closed,t?{reason:t}:void 0)}destroy(){this.close(),this.listener.removeAllListeners(),this.removeAllListeners()}}!function(e){let t;!function(e){e.Connected="Connected",e.Message="Message",e.Error="Error",e.Closed="Closed"}(t=e.Events||(e.Events={}))}(WSController||(WSController={}));
@@ -1 +0,0 @@
1
- import{getUAParserResult}from"./getUAParserResult";import{isIOS}from"./isIOS";class Semver{constructor(e,t,r){this.major=e,this.minor=t,this.patch=r}toString(){return`${this.major}_${this.minor}_${this.patch}`}}let memo;export function getIOSVersion(){if(void 0===memo){const{os:e}=getUAParserResult(),t=isIOS()&&e.version&&/(\d+)\.(\d+)(?:\.(\d+))?/.exec(e.version);memo=t?new Semver(parseInt(t[1],10)||0,parseInt(t[2],10)||0,parseInt(t[3],10)||0):null}return null!=memo?memo:void 0}export default getIOSVersion;
@@ -1 +0,0 @@
1
- import{getUAParserResult}from"./getUAParserResult";export function isIOS(){return"iOS"===getUAParserResult().os.name}export default isIOS;
@@ -1 +0,0 @@
1
- import{getUAParserResult}from"./getUAParserResult";export function isMacOS(){return"Mac OS"===getUAParserResult().os.name}export default isMacOS;
@@ -1 +0,0 @@
1
- import{getUAParserResult}from"./getUAParserResult";export function isMobile(){const e=getUAParserResult().device.type;return"mobile"===e||"tablet"===e}export default isMobile;
@@ -1 +0,0 @@
1
- import{getUAParserResult}from"./getUAParserResult";export function isSafari(){const r=getUAParserResult().browser.name;return"Safari"===r||"Mobile Safari"===r}export default isSafari;
package/media/mse.js DELETED
@@ -1 +0,0 @@
1
- export function getMediaSource(){return window.MediaSource||window.WebKitMediaSource}export function isMSESupported(){return!!getMediaSource()}
File without changes
File without changes