You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

j-queue-sdk-web

Package Overview
Dependencies
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

j-queue-sdk-web - npm Package Compare versions

Comparing version

to
1.0.20

2

dist/j-queue-sdk-web.js

@@ -1,2 +0,2 @@

!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("io")):"function"==typeof define&&define.amd?define(["io"],e):"object"==typeof exports?exports.ConnectionJQueueSdkWeb=e(require("io")):t.ConnectionJQueueSdkWeb=e(t.io)}(this,(t=>(()=>{"use strict";var e={156:function(t,e,n){var i=this&&this.__awaiter||function(t,e,n,i){return new(n||(n=Promise))((function(o,s){function a(t){try{u(i.next(t))}catch(t){s(t)}}function r(t){try{u(i.throw(t))}catch(t){s(t)}}function u(t){var e;t.done?o(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(a,r)}u((i=i.apply(t,e||[])).next())}))};Object.defineProperty(e,"__esModule",{value:!0});const o=n(676),s=n(613);class a{static log(t,e="info",n){("error"===e?console.error:"warn"===e?console.warn:console.log)(`[J-Queue] ${t}`,null!=n?n:"")}static injectStyles(t){if("undefined"==typeof document||document.querySelector("style[data-jqueue-styles]"))return;const e=document.createElement("style");e.dataset.jqueueStyles="",e.textContent=this.CONFIG.STYLES.LOADER(t),document.head.appendChild(e)}static createPopup(t,e){if("undefined"==typeof document)return;this.removePopup();const n=document.createElement("div");n.id="__jqueue_popup",n.style.cssText=null!=e?e:this.CONFIG.STYLES.POPUP,n.innerHTML=t,document.body.appendChild(n),this.state.popupEl=n}static removePopup(){var t;"undefined"!=typeof document&&(null===(t=this.state.popupEl)||void 0===t||t.remove(),this.state.popupEl=null)}static toggleNavigation(t){"undefined"!=typeof window&&this.state.isNavigating!==t&&(window.onbeforeunload=t?()=>{var t;return(null===(t=this.state.queueStatus)||void 0===t?void 0:t.uuid)&&this.state.apiUrl&&this.sendLeaveRequest(),"Navigation is currently blocked."}:null,this.state.isNavigating=t)}static sendLeaveRequest(){const{apiUrl:t,queueStatus:e}=this.state;if(t&&(null==e?void 0:e.uuid))try{const n=JSON.stringify({uuid:e.uuid});navigator.sendBeacon(`${t}${this.CONFIG.API_ENDPOINTS.LEAVE}`,n)}catch(t){this.log("Leave API (sendBeacon) failed","error",t)}}static getDefaultPopupContent(t,e="ko",n){var i;const o=this.CONFIG.MESSAGES[e],s=null!==(i=null==n?void 0:n.textColor)&&void 0!==i?i:"#276bff";return`\n <div style="display: flex; flex-direction: column; align-items: center; width: 100%;">\n <div style="padding: 20px; text-align: center;">\n <p style="font-size: 16px; line-height: 1.5; margin: 0 0 20px 0; color: ${s};">\n ${o.MESS_1}<br>${o.MESS_2}\n </p>\n <div style="position: relative; width: 150px; height: 150px; margin: 20px auto;">\n <span style="position: absolute; inset: 0;" class="loader-jqueue_popup"></span>\n <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center;">\n <div style="font-size: 14px; color: ${s};">${o.MESS_3}</div>\n <div style="font-size: 36px; color: ${s}; font-weight: bold;">${t}</div>\n </div>\n </div>\n </div>\n </div>\n `}static getAdjustedPollInterval(t,e){return t>=100?e+t/100*1e3:e}static setupSocket(t,e,n,i,a){const r=(0,o.io)(t,{query:Object.assign(Object.assign({},e.query),{uuid:n}),transports:e.transports||["websocket"],reconnectionAttempts:e.reconnectionAttempts||3,reconnectionDelay:e.reconnectionDelay||1e3});this.state.socket=r;let u=this.getAdjustedPollInterval(0,this.CONFIG.TTL_INTERVAL);const l=()=>{this.ttlInterval&&clearInterval(this.ttlInterval),this.ttlInterval=setInterval((()=>{var t;r.connected&&(null===(t=this.state.queueStatus)||void 0===t?void 0:t.uuid)&&(r.emit("online-queue:set-ttl",Object.assign(Object.assign({},e.query),{uuid:this.state.queueStatus.uuid})),this.log("Sent online-queue:set-ttl"))}),u)};r.on("connect",(()=>{this.log("Socket.IO connected"),l()})),r.on("online-queue:set-ttl",(t=>{var e,n;if(!(null==t?void 0:t.data))return void this.log("Invalid status response received","warn");const{status:i,position:o,uuid:r}=t.data;this.state.queueStatus={status:i,position:o,uuid:r},this.state.storageKey&&"undefined"!=typeof sessionStorage&&sessionStorage.setItem(this.state.storageKey,r),this.statusListeners.forEach((t=>t({status:i,position:o,uuid:r})));const d=this.getAdjustedPollInterval(o,this.CONFIG.TTL_INTERVAL);if(d!==u&&(u=d,l()),i===s.OnlineQueueStatus.ACTIVE)this.removePopup(),this.toggleNavigation(!1);else{const t="function"==typeof(null==a?void 0:a.content)?a.content(o):null!==(e=null==a?void 0:a.content)&&void 0!==e?e:this.getDefaultPopupContent(o,null!==(n=null==a?void 0:a.language)&&void 0!==n?n:"ko",a);this.createPopup(t,null==a?void 0:a.style),this.toggleNavigation(!0)}})),i&&Object.keys(i).forEach((t=>{r.on(t,(e=>{i[t](e,{createPopup:this.createPopup.bind(this),removePopup:this.removePopup.bind(this),preventNavigation:()=>this.toggleNavigation(!0),allowNavigation:()=>this.toggleNavigation(!1)})}))})),r.on("connect_error",(t=>{this.log("Socket.IO connection error","error",t)})),r.on("disconnect",(t=>{this.log(`Socket.IO disconnected: ${t}`,"warn"),this.ttlInterval&&(clearInterval(this.ttlInterval),this.ttlInterval=null)}))}static addStatusListener(t){this.statusListeners.push(t)}static removeStatusListener(t){this.statusListeners=this.statusListeners.filter((e=>e!==t))}static getQueueStatus(){return this.state.queueStatus}static init(t){return i(this,arguments,void 0,(function*({wsUrl:t,apiUrl:e,socketConfig:n={},popupConfig:i={},customEvents:o={},option:s={storageKey:this.CONFIG.STORAGE_KEY}}){var a;if(!t||!e)throw new Error("Both wsUrl and apiUrl are required for initialization");if("undefined"==typeof window)throw new Error("Socket.IO is not supported in this environment.");this.state=Object.assign(Object.assign({},this.state),{storageKey:null!==(a=s.storageKey)&&void 0!==a?a:this.CONFIG.STORAGE_KEY,wsUrl:t,apiUrl:e,socketConfig:n}),this.injectStyles(i);try{return this.setupSocket(t,n,"",o,i),{disconnect:()=>this.disconnect()}}catch(t){return this.log("Initialization failed","error",t),{disconnect:()=>this.disconnect()}}}))}static cleanup(){this.state.storageKey&&"undefined"!=typeof sessionStorage&&sessionStorage.removeItem(this.state.storageKey),this.ttlInterval&&(clearInterval(this.ttlInterval),this.ttlInterval=null),this.removePopup(),this.toggleNavigation(!1),this.state={socket:null,popupEl:null,isNavigating:!1,storageKey:null,queueStatus:null,wsUrl:null,apiUrl:null,socketConfig:null},this.statusListeners=[]}static disconnect(){var t,e,n;(null===(t=this.state.socket)||void 0===t?void 0:t.connected)&&(null===(e=this.state.queueStatus)||void 0===e?void 0:e.uuid)&&this.state.apiUrl&&this.sendLeaveRequest(),null===(n=this.state.socket)||void 0===n||n.disconnect(),this.cleanup()}}a.CONFIG={TTL_INTERVAL:5e3,STORAGE_KEY:"queue_token",API_ENDPOINTS:{LEAVE:"/leave"},MESSAGES:{en:{MESS_1:"Progressing sequentially based on access order.",MESS_2:"We are doing our best to proceed quickly.",MESS_3:"Queue Number"},ko:{MESS_1:"접속한 순서대로 순차적 진행 중입니다.",MESS_2:"빠른 서비스 진행을 위해 최선을 다하고 있습니다.",MESS_3:"대기순번"}},STYLES:{POPUP:"\n position: fixed;\n inset: 0;\n width: 100%;\n height: 100%;\n background: #fff;\n z-index: 10000;\n display: flex;\n justify-content: center;\n align-items: center;\n font-size: 28px;\n ",LOADER:t=>{var e,n;return`\n .loader-jqueue_popup {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n display: inline-block;\n position: relative;\n background: linear-gradient(0deg, ${null!==(e=null==t?void 0:t.loaderGradientEnd)&&void 0!==e?e:"rgba(39,107,255,0.05)"} 33%, ${null!==(n=null==t?void 0:t.loaderGradientStart)&&void 0!==n?n:"#276bff"} 100%);\n box-sizing: border-box;\n animation: rotation 1s linear infinite;\n }\n .loader-jqueue_popup::after {\n content: '';\n box-sizing: border-box;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n width: 96%;\n height: 96%;\n border-radius: 50%;\n background: #fff;\n }\n @keyframes rotation {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n `}}},a.state={socket:null,popupEl:null,isNavigating:!1,storageKey:null,queueStatus:null,wsUrl:null,apiUrl:null,socketConfig:null},a.ttlInterval=null,a.statusListeners=[],"undefined"!=typeof window&&(window.ConnectionJQueueSdkWeb=a),e.default=a},613:(t,e)=>{var n;Object.defineProperty(e,"__esModule",{value:!0}),e.OnlineQueueStatus=void 0,function(t){t[t.WAITING=1]="WAITING",t[t.ACTIVE=2]="ACTIVE"}(n||(e.OnlineQueueStatus=n={}))},676:e=>{e.exports=t}},n={},i=function t(i){var o=n[i];if(void 0!==o)return o.exports;var s=n[i]={exports:{}};return e[i].call(s.exports,s,s.exports,t),s.exports}(156);return i.default})()));
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ConnectionJQueueSdkWeb=e():t.ConnectionJQueueSdkWeb=e()}(this,(()=>(()=>{"use strict";var t={156:function(t,e,n){var i=this&&this.__awaiter||function(t,e,n,i){return new(n||(n=Promise))((function(s,o){function a(t){try{l(i.next(t))}catch(t){o(t)}}function r(t){try{l(i.throw(t))}catch(t){o(t)}}function l(t){var e;t.done?s(t.value):(e=t.value,e instanceof n?e:new n((function(t){t(e)}))).then(a,r)}l((i=i.apply(t,e||[])).next())}))};Object.defineProperty(e,"__esModule",{value:!0});const s=n(613);class o{static log(t,e="info",n){("error"===e?console.error:"warn"===e?console.warn:console.log)(`[J-Queue] ${t}`,null!=n?n:"")}static injectStyles(t){if("undefined"==typeof document||document.querySelector("style[data-jqueue-styles]"))return;const e=document.createElement("style");e.dataset.jqueueStyles="",e.textContent=this.CONFIG.STYLES.LOADER(t),document.head.appendChild(e)}static createPopup(t,e){if("undefined"==typeof document)return;this.removePopup();const n=document.createElement("div");n.id="__jqueue_popup",n.style.cssText=null!=e?e:this.CONFIG.STYLES.POPUP,n.innerHTML=t,document.body.appendChild(n),this.state.popupEl=n}static removePopup(){var t;"undefined"!=typeof document&&(null===(t=this.state.popupEl)||void 0===t||t.remove(),this.state.popupEl=null)}static toggleNavigation(t){"undefined"!=typeof window&&this.state.isNavigating!==t&&(window.onbeforeunload=t?()=>{var t;return(null===(t=this.state.queueStatus)||void 0===t?void 0:t.uuid)&&this.state.apiUrl&&this.sendLeaveRequest(),"Navigation is currently blocked."}:null,this.state.isNavigating=t)}static sendLeaveRequest(){const{apiUrl:t,queueStatus:e}=this.state;if(t&&(null==e?void 0:e.uuid))try{const n=JSON.stringify({uuid:e.uuid});navigator.sendBeacon(`${t}${this.CONFIG.API_ENDPOINTS.LEAVE}`,n)}catch(t){this.log("Leave API (sendBeacon) failed","error",t)}}static getDefaultPopupContent(t,e="ko",n){var i;const s=this.CONFIG.MESSAGES[e],o=null!==(i=null==n?void 0:n.textColor)&&void 0!==i?i:"#276bff";return`\n <div style="display: flex; flex-direction: column; align-items: center; width: 100%;">\n <div style="padding: 20px; text-align: center;">\n <p style="font-size: 18px; line-height: 1.5; margin: 0 0 20px 0; color: ${o};">\n ${s.MESS_1}<br>${s.MESS_2}\n </p>\n <div style="position: relative; width: 150px; height: 150px; margin: 20px auto;">\n <span style="position: absolute; inset: 0;" class="loader-jqueue_popup"></span>\n <div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center;">\n <div style="font-size: 14px; color: ${o};">${s.MESS_3}</div>\n <div style="font-size: 36px; color: ${o}; font-weight: bold;">${t}</div>\n </div>\n </div>\n </div>\n </div>\n `}static getAdjustedPollInterval(t,e){return t>=100?e+t/100*1e3:e}static handleStatusUpdate(t,e,n){var i,o;if(!(null==t?void 0:t.data))return void this.log("Invalid status response received","warn");const{status:a,position:r,uuid:l}=t.data;this.state.queueStatus={status:a,position:r,uuid:l},this.state.storageKey&&"undefined"!=typeof sessionStorage&&sessionStorage.setItem(this.state.storageKey,l),this.statusListeners.forEach((t=>t({status:a,position:r,uuid:l})));const u=this.getAdjustedPollInterval(r,this.CONFIG.TTL_INTERVAL);if(u!==n.value&&(n.value=u,this.startTtlEmission(n.value)),a===s.OnlineQueueStatus.ACTIVE)this.removePopup(),this.toggleNavigation(!1);else{const t="function"==typeof(null==e?void 0:e.content)?e.content(r):null!==(i=null==e?void 0:e.content)&&void 0!==i?i:this.getDefaultPopupContent(r,null!==(o=null==e?void 0:e.language)&&void 0!==o?o:"ko",e);this.createPopup(t,null==e?void 0:e.style),this.toggleNavigation(!0)}}static startTtlEmission(t){this.ttlInterval&&clearInterval(this.ttlInterval),this.ttlInterval=setInterval((()=>{var t,e;if((null===(t=this.state.socket)||void 0===t?void 0:t.readyState)===WebSocket.OPEN&&(null===(e=this.state.queueStatus)||void 0===e?void 0:e.uuid)&&this.state.socketConfig)try{this.state.socket.send(JSON.stringify({event:"online-queue:set-ttl",data:Object.assign(Object.assign({},this.state.socketConfig.query),{uuid:this.state.queueStatus.uuid})})),this.log("Sent online-queue:set-ttl")}catch(t){this.log("Failed to send online-queue:set-ttl","error",t)}}),t)}static reconnect(t,e,n,i,s){this.reconnectAttempts>=this.CONFIG.RECONNECTION_ATTEMPTS?this.log("Max reconnection attempts reached","error"):(this.reconnectAttempts++,this.log(`Reconnection attempt ${this.reconnectAttempts} in ${this.CONFIG.RECONNECTION_DELAY}ms`,"info"),setTimeout((()=>{this.setupWebSocket(t,e,n,i,s)}),this.CONFIG.RECONNECTION_DELAY))}static setupWebSocket(t,e,n,i,s){const o=new URLSearchParams(Object.assign(Object.assign({},e.query),{uuid:n})).toString(),a=new WebSocket(`${t}?${o}`);this.state.socket=a;const r={value:this.getAdjustedPollInterval(0,this.CONFIG.TTL_INTERVAL)};a.onopen=()=>{if(this.log("WebSocket connected"),this.reconnectAttempts=0,this.isFirstConnection)try{a.send(JSON.stringify({event:"online-queue:join",data:Object.assign({},e.query)})),this.log("Sent online-queue:join"),this.isFirstConnection=!1}catch(t){this.log("Failed to send online-queue:join","error",t)}this.startTtlEmission(r.value)},a.onmessage=t=>{try{const e=JSON.parse(t.data);if(!e.event||!e.data)return void this.log("Invalid WebSocket message format","warn");switch(e.event){case"online-queue:join":case"online-queue:status":this.handleStatusUpdate(e.data,s,r);break;default:i&&i[e.event]?i[e.event](e.data,{createPopup:this.createPopup.bind(this),removePopup:this.removePopup.bind(this),preventNavigation:()=>this.toggleNavigation(!0),allowNavigation:()=>this.toggleNavigation(!1)}):this.log(`Unhandled WebSocket event: ${e.event}`,"warn")}}catch(t){this.log("Failed to parse WebSocket message","error",t)}},a.onerror=t=>{this.log("WebSocket error","error",t)},a.onclose=o=>{this.log(`WebSocket closed: code=${o.code}, reason=${o.reason}`,"warn"),this.ttlInterval&&(clearInterval(this.ttlInterval),this.ttlInterval=null),this.reconnect(t,e,n,i,s)}}static addStatusListener(t){this.statusListeners.push(t)}static removeStatusListener(t){this.statusListeners=this.statusListeners.filter((e=>e!==t))}static getQueueStatus(){return this.state.queueStatus}static init(t){return i(this,arguments,void 0,(function*({wsUrl:t,apiUrl:e,socketConfig:n={},popupConfig:i={},customEvents:s={},option:o={storageKey:this.CONFIG.STORAGE_KEY}}){var a;if(!t||!e)throw new Error("Both wsUrl and apiUrl are required for initialization");if("undefined"==typeof window)throw new Error("WebSocket is not supported in this environment.");this.state=Object.assign(Object.assign({},this.state),{storageKey:null!==(a=o.storageKey)&&void 0!==a?a:this.CONFIG.STORAGE_KEY,wsUrl:t,apiUrl:e,socketConfig:n}),this.injectStyles(i);try{return this.setupWebSocket(t,n,"",s,i),{disconnect:()=>this.disconnect()}}catch(t){return this.log("Initialization failed","error",t),{disconnect:()=>this.disconnect()}}}))}static cleanup(){this.state.storageKey&&"undefined"!=typeof sessionStorage&&sessionStorage.removeItem(this.state.storageKey),this.ttlInterval&&(clearInterval(this.ttlInterval),this.ttlInterval=null),this.removePopup(),this.toggleNavigation(!1),this.state={socket:null,popupEl:null,isNavigating:!1,storageKey:null,queueStatus:null,wsUrl:null,apiUrl:null,socketConfig:null},this.statusListeners=[],this.reconnectAttempts=0,this.isFirstConnection=!0}static disconnect(){var t,e;(null===(t=this.state.socket)||void 0===t?void 0:t.readyState)===WebSocket.OPEN&&(null===(e=this.state.queueStatus)||void 0===e?void 0:e.uuid)&&this.state.apiUrl&&this.sendLeaveRequest(),this.state.socket&&(this.state.socket.close(),this.state.socket=null),this.cleanup()}}o.CONFIG={TTL_INTERVAL:5e3,STORAGE_KEY:"queue_token",API_ENDPOINTS:{LEAVE:"/leave"},MESSAGES:{en:{MESS_1:"Progressing sequentially based on access order.",MESS_2:"We are doing our best to proceed quickly.",MESS_3:"Queue Number"},ko:{MESS_1:"접속한 순서대로 순차적 진행 중입니다.",MESS_2:"빠른 서비스 진행을 위해 최선을 다하고 있습니다.",MESS_3:"대기순번"}},STYLES:{POPUP:"\n position: fixed;\n inset: 0;\n width: 100%;\n height: 100%;\n background: #fff;\n z-index: 10000;\n display: flex;\n justify-content: center;\n align-items: center;\n font-size: 28px;\n ",LOADER:t=>{var e,n;return`\n .loader-jqueue_popup {\n width: 100%;\n height: 100%;\n border-radius: 50%;\n display: inline-block;\n position: relative;\n background: linear-gradient(0deg, ${null!==(e=null==t?void 0:t.loaderGradientEnd)&&void 0!==e?e:"rgba(39,107,255,0.05)"} 33%, ${null!==(n=null==t?void 0:t.loaderGradientStart)&&void 0!==n?n:"#276bff"} 100%);\n box-sizing: border-box;\n animation: rotation 1s linear infinite;\n }\n .loader-jqueue_popup::after {\n content: '';\n box-sizing: border-box;\n position: absolute;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%);\n width: 96%;\n height: 96%;\n border-radius: 50%;\n background: #fff;\n }\n @keyframes rotation {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n }\n `}},RECONNECTION_ATTEMPTS:3,RECONNECTION_DELAY:1e3},o.state={socket:null,popupEl:null,isNavigating:!1,storageKey:null,queueStatus:null,wsUrl:null,apiUrl:null,socketConfig:null},o.ttlInterval=null,o.statusListeners=[],o.reconnectAttempts=0,o.isFirstConnection=!0,"undefined"!=typeof window&&(window.ConnectionJQueueSdkWeb=o,console.log("Initialized on window")),e.default=o},613:(t,e)=>{var n;Object.defineProperty(e,"__esModule",{value:!0}),e.OnlineQueueStatus=void 0,function(t){t[t.WAITING=1]="WAITING",t[t.ACTIVE=2]="ACTIVE"}(n||(e.OnlineQueueStatus=n={}))}},e={},n=function n(i){var s=e[i];if(void 0!==s)return s.exports;var o=e[i]={exports:{}};return t[i].call(o.exports,o,o.exports,n),o.exports}(156);return n.default})()));
//# sourceMappingURL=j-queue-sdk-web.js.map

@@ -1,5 +0,4 @@

import { Socket } from 'socket.io-client';
import { InitConfig, OnlineQueueStatus } from './types';
interface ConnectionState {
socket: Socket | null;
socket: WebSocket | null;
popupEl: HTMLElement | null;

@@ -22,2 +21,4 @@ isNavigating: boolean;

private static statusListeners;
private static reconnectAttempts;
private static isFirstConnection;
/** Logs messages with a prefix, supporting different log levels. */

@@ -39,4 +40,10 @@ private static log;

private static getAdjustedPollInterval;
/** Configures the Socket.IO connection with event handlers and periodic TTL emission. */
private static setupSocket;
/** Handles status updates from online-queue:join or online-queue:status events. */
private static handleStatusUpdate;
/** Starts periodic TTL emission with the specified interval. */
private static startTtlEmission;
/** Attempts to reconnect to the WebSocket server. */
private static reconnect;
/** Configures the WebSocket connection with event handlers and periodic TTL emission. */
private static setupWebSocket;
/** Adds a listener for queue status updates. */

@@ -54,3 +61,3 @@ static addStatusListener(listener: (status: NonNullable<ConnectionState['queueStatus']>) => void): void;

private static cleanup;
/** Disconnects the Socket.IO connection and cleans up resources. */
/** Disconnects the WebSocket connection and cleans up resources. */
private static disconnect;

@@ -57,0 +64,0 @@ }

@@ -12,3 +12,2 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
const socket_io_client_1 = require("socket.io-client");
const types_1 = require("./types");

@@ -86,3 +85,3 @@ class ConnectionJQueueSdkWeb {

<div style="padding: 20px; text-align: center;">
<p style="font-size: 16px; line-height: 1.5; margin: 0 0 20px 0; color: ${textColor};">
<p style="font-size: 18px; line-height: 1.5; margin: 0 0 20px 0; color: ${textColor};">
${messages.MESS_1}<br>${messages.MESS_2}

@@ -105,75 +104,126 @@ </p>

}
/** Configures the Socket.IO connection with event handlers and periodic TTL emission. */
static setupSocket(wsUrl, socketConfig, uuid, customEvents, popupConfig) {
const socket = (0, socket_io_client_1.io)(wsUrl, {
query: Object.assign(Object.assign({}, socketConfig.query), { uuid }),
transports: socketConfig.transports || ['websocket'],
reconnectionAttempts: socketConfig.reconnectionAttempts || 3,
reconnectionDelay: socketConfig.reconnectionDelay || 1000,
});
this.state.socket = socket;
let currentTtlInterval = this.getAdjustedPollInterval(0, this.CONFIG.TTL_INTERVAL);
const startTtlEmission = () => {
if (this.ttlInterval)
clearInterval(this.ttlInterval);
this.ttlInterval = setInterval(() => {
var _a;
if (socket.connected && ((_a = this.state.queueStatus) === null || _a === void 0 ? void 0 : _a.uuid)) {
socket.emit('online-queue:set-ttl', Object.assign(Object.assign({}, socketConfig.query), { uuid: this.state.queueStatus.uuid }));
/** Handles status updates from online-queue:join or online-queue:status events. */
static handleStatusUpdate(data, popupConfig, currentTtlInterval) {
var _a, _b;
if (!(data === null || data === void 0 ? void 0 : data.data)) {
this.log('Invalid status response received', 'warn');
return;
}
const { status, position, uuid } = data.data;
this.state.queueStatus = { status, position, uuid };
if (this.state.storageKey && typeof sessionStorage !== 'undefined') {
sessionStorage.setItem(this.state.storageKey, uuid);
}
this.statusListeners.forEach((listener) => listener({ status, position, uuid }));
// Update TTL interval based on new position
const newTtlInterval = this.getAdjustedPollInterval(position, this.CONFIG.TTL_INTERVAL);
if (newTtlInterval !== currentTtlInterval.value) {
currentTtlInterval.value = newTtlInterval;
this.startTtlEmission(currentTtlInterval.value);
}
// Handle popup and navigation
if (status === types_1.OnlineQueueStatus.ACTIVE) {
this.removePopup();
this.toggleNavigation(false);
}
else {
const content = typeof (popupConfig === null || popupConfig === void 0 ? void 0 : popupConfig.content) === 'function'
? popupConfig.content(position)
: (_a = popupConfig === null || popupConfig === void 0 ? void 0 : popupConfig.content) !== null && _a !== void 0 ? _a : this.getDefaultPopupContent(position, (_b = popupConfig === null || popupConfig === void 0 ? void 0 : popupConfig.language) !== null && _b !== void 0 ? _b : 'ko', popupConfig);
this.createPopup(content, popupConfig === null || popupConfig === void 0 ? void 0 : popupConfig.style);
this.toggleNavigation(true);
}
}
/** Starts periodic TTL emission with the specified interval. */
static startTtlEmission(interval) {
if (this.ttlInterval)
clearInterval(this.ttlInterval);
this.ttlInterval = setInterval(() => {
var _a, _b;
if (((_a = this.state.socket) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN && ((_b = this.state.queueStatus) === null || _b === void 0 ? void 0 : _b.uuid) && this.state.socketConfig) {
try {
this.state.socket.send(JSON.stringify({
event: 'online-queue:set-ttl',
data: Object.assign(Object.assign({}, this.state.socketConfig.query), { uuid: this.state.queueStatus.uuid }),
}));
this.log('Sent online-queue:set-ttl');
}
}, currentTtlInterval);
};
socket.on('connect', () => {
this.log('Socket.IO connected');
startTtlEmission();
});
socket.on('online-queue:set-ttl', (data) => {
var _a, _b;
if (!(data === null || data === void 0 ? void 0 : data.data)) {
this.log('Invalid status response received', 'warn');
return;
catch (error) {
this.log('Failed to send online-queue:set-ttl', 'error', error);
}
}
const { status, position, uuid } = data.data;
this.state.queueStatus = { status, position, uuid };
if (this.state.storageKey && typeof sessionStorage !== 'undefined') {
sessionStorage.setItem(this.state.storageKey, uuid);
}, interval);
}
/** Attempts to reconnect to the WebSocket server. */
static reconnect(wsUrl, socketConfig, uuid, customEvents, popupConfig) {
if (this.reconnectAttempts >= this.CONFIG.RECONNECTION_ATTEMPTS) {
this.log('Max reconnection attempts reached', 'error');
return;
}
this.reconnectAttempts++;
this.log(`Reconnection attempt ${this.reconnectAttempts} in ${this.CONFIG.RECONNECTION_DELAY}ms`, 'info');
setTimeout(() => {
this.setupWebSocket(wsUrl, socketConfig, uuid, customEvents, popupConfig);
}, this.CONFIG.RECONNECTION_DELAY);
}
/** Configures the WebSocket connection with event handlers and periodic TTL emission. */
static setupWebSocket(wsUrl, socketConfig, uuid, customEvents, popupConfig) {
// Append query parameters to wsUrl
const query = new URLSearchParams(Object.assign(Object.assign({}, socketConfig.query), { uuid })).toString();
const ws = new WebSocket(`${wsUrl}?${query}`);
this.state.socket = ws;
const currentTtlInterval = { value: this.getAdjustedPollInterval(0, this.CONFIG.TTL_INTERVAL) };
ws.onopen = () => {
this.log('WebSocket connected');
this.reconnectAttempts = 0; // Reset reconnection attempts
if (this.isFirstConnection) {
try {
ws.send(JSON.stringify({
event: 'online-queue:join',
data: Object.assign({}, socketConfig.query),
}));
this.log('Sent online-queue:join');
this.isFirstConnection = false;
}
catch (error) {
this.log('Failed to send online-queue:join', 'error', error);
}
}
this.statusListeners.forEach((listener) => listener({ status, position, uuid }));
// Update TTL interval based on new position
const newTtlInterval = this.getAdjustedPollInterval(position, this.CONFIG.TTL_INTERVAL);
if (newTtlInterval !== currentTtlInterval) {
currentTtlInterval = newTtlInterval;
startTtlEmission();
this.startTtlEmission(currentTtlInterval.value);
};
ws.onmessage = (event) => {
try {
const message = JSON.parse(event.data);
if (!message.event || !message.data) {
this.log('Invalid WebSocket message format', 'warn');
return;
}
switch (message.event) {
case 'online-queue:join':
case 'online-queue:status':
this.handleStatusUpdate(message.data, popupConfig, currentTtlInterval);
break;
default:
if (customEvents && customEvents[message.event]) {
customEvents[message.event](message.data, {
createPopup: this.createPopup.bind(this),
removePopup: this.removePopup.bind(this),
preventNavigation: () => this.toggleNavigation(true),
allowNavigation: () => this.toggleNavigation(false),
});
}
else {
this.log(`Unhandled WebSocket event: ${message.event}`, 'warn');
}
}
}
// Handle popup and navigation
if (status === types_1.OnlineQueueStatus.ACTIVE) {
this.removePopup();
this.toggleNavigation(false);
catch (error) {
this.log('Failed to parse WebSocket message', 'error', error);
}
else {
const content = typeof (popupConfig === null || popupConfig === void 0 ? void 0 : popupConfig.content) === 'function'
? popupConfig.content(position)
: (_a = popupConfig === null || popupConfig === void 0 ? void 0 : popupConfig.content) !== null && _a !== void 0 ? _a : this.getDefaultPopupContent(position, (_b = popupConfig === null || popupConfig === void 0 ? void 0 : popupConfig.language) !== null && _b !== void 0 ? _b : 'ko', popupConfig);
this.createPopup(content, popupConfig === null || popupConfig === void 0 ? void 0 : popupConfig.style);
this.toggleNavigation(true);
}
});
if (customEvents) {
Object.keys(customEvents).forEach((event) => {
socket.on(event, (data) => {
customEvents[event](data, {
createPopup: this.createPopup.bind(this),
removePopup: this.removePopup.bind(this),
preventNavigation: () => this.toggleNavigation(true),
allowNavigation: () => this.toggleNavigation(false),
});
});
});
}
socket.on('connect_error', (error) => {
this.log('Socket.IO connection error', 'error', error);
});
socket.on('disconnect', (reason) => {
this.log(`Socket.IO disconnected: ${reason}`, 'warn');
};
ws.onerror = (error) => {
this.log('WebSocket error', 'error', error);
};
ws.onclose = (event) => {
this.log(`WebSocket closed: code=${event.code}, reason=${event.reason}`, 'warn');
if (this.ttlInterval) {

@@ -183,3 +233,4 @@ clearInterval(this.ttlInterval);

}
});
this.reconnect(wsUrl, socketConfig, uuid, customEvents, popupConfig);
};
}

@@ -205,3 +256,3 @@ /** Adds a listener for queue status updates. */

if (typeof window === 'undefined')
throw new Error('Socket.IO is not supported in this environment.');
throw new Error('WebSocket is not supported in this environment.');
this.state = Object.assign(Object.assign({}, this.state), { storageKey: (_b = option.storageKey) !== null && _b !== void 0 ? _b : this.CONFIG.STORAGE_KEY, wsUrl,

@@ -212,4 +263,3 @@ apiUrl,

try {
// Connect socket immediately
this.setupSocket(wsUrl, socketConfig, '', customEvents, popupConfig);
this.setupWebSocket(wsUrl, socketConfig, '', customEvents, popupConfig);
return { disconnect: () => this.disconnect() };

@@ -245,10 +295,15 @@ }

this.statusListeners = [];
this.reconnectAttempts = 0;
this.isFirstConnection = true;
}
/** Disconnects the Socket.IO connection and cleans up resources. */
/** Disconnects the WebSocket connection and cleans up resources. */
static disconnect() {
var _a, _b, _c;
if (((_a = this.state.socket) === null || _a === void 0 ? void 0 : _a.connected) && ((_b = this.state.queueStatus) === null || _b === void 0 ? void 0 : _b.uuid) && this.state.apiUrl) {
var _a, _b;
if (((_a = this.state.socket) === null || _a === void 0 ? void 0 : _a.readyState) === WebSocket.OPEN && ((_b = this.state.queueStatus) === null || _b === void 0 ? void 0 : _b.uuid) && this.state.apiUrl) {
this.sendLeaveRequest();
}
(_c = this.state.socket) === null || _c === void 0 ? void 0 : _c.disconnect();
if (this.state.socket) {
this.state.socket.close();
this.state.socket = null;
}
this.cleanup();

@@ -320,2 +375,4 @@ }

},
RECONNECTION_ATTEMPTS: 3,
RECONNECTION_DELAY: 1000,
};

@@ -334,6 +391,8 @@ ConnectionJQueueSdkWeb.state = {

ConnectionJQueueSdkWeb.statusListeners = [];
ConnectionJQueueSdkWeb.reconnectAttempts = 0;
ConnectionJQueueSdkWeb.isFirstConnection = true;
if (typeof window !== 'undefined') {
window.ConnectionJQueueSdkWeb = ConnectionJQueueSdkWeb;
// console.log('Initialized on window');
console.log('Initialized on window');
}
exports.default = ConnectionJQueueSdkWeb;
{
"name": "j-queue-sdk-web",
"version": "1.0.19",
"version": "1.0.20",
"description": "A TypeScript package to check WebSocket connection status and control web access with a popup",

@@ -5,0 +5,0 @@ "main": "dist/j-queue-sdk-web.js",

@@ -1,6 +0,5 @@

import { io, Socket } from 'socket.io-client';
import { InitConfig, PopupConfig, OnlineQueueStatus, CustomEventUtils } from './types';
interface ConnectionState {
socket: Socket | null;
socket: WebSocket | null;
popupEl: HTMLElement | null;

@@ -86,2 +85,4 @@ isNavigating: boolean;

},
RECONNECTION_ATTEMPTS: 3,
RECONNECTION_DELAY: 1000,
};

@@ -102,2 +103,4 @@

private static statusListeners: Array<(status: NonNullable<ConnectionState['queueStatus']>) => void> = [];
private static reconnectAttempts = 0;
private static isFirstConnection = true;

@@ -170,3 +173,3 @@ /** Logs messages with a prefix, supporting different log levels. */

<div style="padding: 20px; text-align: center;">
<p style="font-size: 16px; line-height: 1.5; margin: 0 0 20px 0; color: ${textColor};">
<p style="font-size: 18px; line-height: 1.5; margin: 0 0 20px 0; color: ${textColor};">
${messages.MESS_1}<br>${messages.MESS_2}

@@ -191,4 +194,74 @@ </p>

/** Configures the Socket.IO connection with event handlers and periodic TTL emission. */
private static setupSocket(
/** Handles status updates from online-queue:join or online-queue:status events. */
private static handleStatusUpdate(data: StatusResponse, popupConfig: InitConfig['popupConfig'], currentTtlInterval: { value: number }): void {
if (!data?.data) {
this.log('Invalid status response received', 'warn');
return;
}
const { status, position, uuid } = data.data;
this.state.queueStatus = { status, position, uuid };
if (this.state.storageKey && typeof sessionStorage !== 'undefined') {
sessionStorage.setItem(this.state.storageKey, uuid);
}
this.statusListeners.forEach((listener) => listener({ status, position, uuid }));
// Update TTL interval based on new position
const newTtlInterval = this.getAdjustedPollInterval(position, this.CONFIG.TTL_INTERVAL);
if (newTtlInterval !== currentTtlInterval.value) {
currentTtlInterval.value = newTtlInterval;
this.startTtlEmission(currentTtlInterval.value);
}
// Handle popup and navigation
if (status === OnlineQueueStatus.ACTIVE) {
this.removePopup();
this.toggleNavigation(false);
} else {
const content =
typeof popupConfig?.content === 'function'
? popupConfig.content(position)
: popupConfig?.content ?? this.getDefaultPopupContent(position, popupConfig?.language ?? 'ko', popupConfig);
this.createPopup(content, popupConfig?.style);
this.toggleNavigation(true);
}
}
/** Starts periodic TTL emission with the specified interval. */
private static startTtlEmission(interval: number): void {
if (this.ttlInterval) clearInterval(this.ttlInterval);
this.ttlInterval = setInterval(() => {
if (this.state.socket?.readyState === WebSocket.OPEN && this.state.queueStatus?.uuid && this.state.socketConfig) {
try {
this.state.socket.send(JSON.stringify({
event: 'online-queue:set-ttl',
data: { ...this.state.socketConfig.query, uuid: this.state.queueStatus.uuid },
}));
this.log('Sent online-queue:set-ttl');
} catch (error) {
this.log('Failed to send online-queue:set-ttl', 'error', error);
}
}
}, interval);
}
/** Attempts to reconnect to the WebSocket server. */
private static reconnect(wsUrl: string, socketConfig: NonNullable<InitConfig['socketConfig']>, uuid: string, customEvents: InitConfig['customEvents'], popupConfig: InitConfig['popupConfig']): void {
if (this.reconnectAttempts >= this.CONFIG.RECONNECTION_ATTEMPTS) {
this.log('Max reconnection attempts reached', 'error');
return;
}
this.reconnectAttempts++;
this.log(`Reconnection attempt ${this.reconnectAttempts} in ${this.CONFIG.RECONNECTION_DELAY}ms`, 'info');
setTimeout(() => {
this.setupWebSocket(wsUrl, socketConfig, uuid, customEvents, popupConfig);
}, this.CONFIG.RECONNECTION_DELAY);
}
/** Configures the WebSocket connection with event handlers and periodic TTL emission. */
private static setupWebSocket(
wsUrl: string,

@@ -200,82 +273,65 @@ socketConfig: NonNullable<InitConfig['socketConfig']>,

): void {
const socket = io(wsUrl, {
query: { ...socketConfig.query, uuid },
transports: socketConfig.transports || ['websocket'],
reconnectionAttempts: socketConfig.reconnectionAttempts || 3,
reconnectionDelay: socketConfig.reconnectionDelay || 1000,
});
this.state.socket = socket;
// Append query parameters to wsUrl
const query = new URLSearchParams({ ...socketConfig.query, uuid }).toString();
const ws = new WebSocket(`${wsUrl}?${query}`);
this.state.socket = ws;
let currentTtlInterval = this.getAdjustedPollInterval(0, this.CONFIG.TTL_INTERVAL);
const currentTtlInterval = { value: this.getAdjustedPollInterval(0, this.CONFIG.TTL_INTERVAL) };
const startTtlEmission = () => {
if (this.ttlInterval) clearInterval(this.ttlInterval);
this.ttlInterval = setInterval(() => {
if (socket.connected && this.state.queueStatus?.uuid) {
socket.emit('online-queue:set-ttl', { ...socketConfig.query, uuid: this.state.queueStatus.uuid });
this.log('Sent online-queue:set-ttl');
ws.onopen = () => {
this.log('WebSocket connected');
this.reconnectAttempts = 0; // Reset reconnection attempts
if (this.isFirstConnection) {
try {
ws.send(JSON.stringify({
event: 'online-queue:join',
data: { ...socketConfig.query },
}));
this.log('Sent online-queue:join');
this.isFirstConnection = false;
} catch (error) {
this.log('Failed to send online-queue:join', 'error', error);
}
}, currentTtlInterval);
};
socket.on('connect', () => {
this.log('Socket.IO connected');
startTtlEmission();
});
socket.on('online-queue:set-ttl', (data: StatusResponse) => {
if (!data?.data) {
this.log('Invalid status response received', 'warn');
return;
}
const { status, position, uuid } = data.data;
this.state.queueStatus = { status, position, uuid };
this.startTtlEmission(currentTtlInterval.value);
};
if (this.state.storageKey && typeof sessionStorage !== 'undefined') {
sessionStorage.setItem(this.state.storageKey, uuid);
}
ws.onmessage = (event) => {
try {
const message = JSON.parse(event.data as string);
if (!message.event || !message.data) {
this.log('Invalid WebSocket message format', 'warn');
return;
}
this.statusListeners.forEach((listener) => listener({ status, position, uuid }));
// Update TTL interval based on new position
const newTtlInterval = this.getAdjustedPollInterval(position, this.CONFIG.TTL_INTERVAL);
if (newTtlInterval !== currentTtlInterval) {
currentTtlInterval = newTtlInterval;
startTtlEmission();
switch (message.event) {
case 'online-queue:join':
case 'online-queue:status':
this.handleStatusUpdate(message.data, popupConfig, currentTtlInterval);
break;
default:
if (customEvents && customEvents[message.event]) {
customEvents[message.event](message.data, {
createPopup: this.createPopup.bind(this),
removePopup: this.removePopup.bind(this),
preventNavigation: () => this.toggleNavigation(true),
allowNavigation: () => this.toggleNavigation(false),
});
} else {
this.log(`Unhandled WebSocket event: ${message.event}`, 'warn');
}
}
} catch (error) {
this.log('Failed to parse WebSocket message', 'error', error);
}
};
// Handle popup and navigation
if (status === OnlineQueueStatus.ACTIVE) {
this.removePopup();
this.toggleNavigation(false);
} else {
const content =
typeof popupConfig?.content === 'function'
? popupConfig.content(position)
: popupConfig?.content ?? this.getDefaultPopupContent(position, popupConfig?.language ?? 'ko', popupConfig);
this.createPopup(content, popupConfig?.style);
this.toggleNavigation(true);
}
});
ws.onerror = (error) => {
this.log('WebSocket error', 'error', error);
};
if (customEvents) {
Object.keys(customEvents).forEach((event) => {
socket.on(event, (data: any) => {
customEvents[event](data, {
createPopup: this.createPopup.bind(this),
removePopup: this.removePopup.bind(this),
preventNavigation: () => this.toggleNavigation(true),
allowNavigation: () => this.toggleNavigation(false),
});
});
});
}
socket.on('connect_error', (error) => {
this.log('Socket.IO connection error', 'error', error);
});
socket.on('disconnect', (reason) => {
this.log(`Socket.IO disconnected: ${reason}`, 'warn');
ws.onclose = (event) => {
this.log(`WebSocket closed: code=${event.code}, reason=${event.reason}`, 'warn');
if (this.ttlInterval) {

@@ -285,3 +341,4 @@ clearInterval(this.ttlInterval);

}
});
this.reconnect(wsUrl, socketConfig, uuid, customEvents, popupConfig);
};
}

@@ -314,3 +371,3 @@

if (!wsUrl || !apiUrl) throw new Error('Both wsUrl and apiUrl are required for initialization');
if (typeof window === 'undefined') throw new Error('Socket.IO is not supported in this environment.');
if (typeof window === 'undefined') throw new Error('WebSocket is not supported in this environment.');

@@ -327,4 +384,3 @@ this.state = {

try {
// Connect socket immediately
this.setupSocket(wsUrl, socketConfig, '', customEvents, popupConfig);
this.setupWebSocket(wsUrl, socketConfig, '', customEvents, popupConfig);
return { disconnect: () => this.disconnect() };

@@ -359,10 +415,15 @@ } catch (error) {

this.statusListeners = [];
this.reconnectAttempts = 0;
this.isFirstConnection = true;
}
/** Disconnects the Socket.IO connection and cleans up resources. */
/** Disconnects the WebSocket connection and cleans up resources. */
private static disconnect(): void {
if (this.state.socket?.connected && this.state.queueStatus?.uuid && this.state.apiUrl) {
if (this.state.socket?.readyState === WebSocket.OPEN && this.state.queueStatus?.uuid && this.state.apiUrl) {
this.sendLeaveRequest();
}
this.state.socket?.disconnect();
if (this.state.socket) {
this.state.socket.close();
this.state.socket = null;
}
this.cleanup();

@@ -380,3 +441,3 @@ }

window.ConnectionJQueueSdkWeb = ConnectionJQueueSdkWeb;
// console.log('Initialized on window');
console.log('Initialized on window');
}

@@ -383,0 +444,0 @@

Sorry, the diff of this file is not supported yet