@cyphlens/2fa-sse-sdk 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -49,7 +49,7 @@ import Cyphlens from "@cyphlens/2fa-sse-sdk";
49
49
  const Cyphlens = require("@cyphlens/2fa-sse-sdk");
50
50
  ```
51
51
 
52
- #### 3. Browser (UMD)
52
+ #### 3. Browser (IIFE)
53
53
  After including the CDN script, the SDK is available as a global `Cyphlens` object:
54
54
  ```javascript
55
55
  const cyphlensClient = new Cyphlens("https://your-api-base-url/b2b/v1");
@@ -69,9 +69,9 @@ const cyphlensClient = new Cyphlens("https://your-api-base-url/b2b/v1");
69
69
 
70
70
  #### 2. Listen for Events
71
71
  ```javascript
72
- // Define the callback for handling events```
72
+ // Define the callback for handling events
73
73
  const onData = (eventType, data) => {
74
- if (eventType === "MFASwipe") {
74
+ if (eventType === Cyphlens.EventType.MFASwipe) {
75
75
  const twoFactorEvent = data;
76
76
  console.log("2FA Status:", twoFactorEvent.status);
77
77
  // Handle status change (e.g., update UI or trigger logic)
@@ -111,7 +111,7 @@ Stops the event listener and closes the connection.
111
111
  ---
112
112
 
113
113
  ## Event Types
114
- - **`MFASwipe`**: Triggered when a 2FA swipe event occurs.
114
+ - **`Cyphlens.EventType.MFASwipe`**: Triggered when a 2FA swipe event occurs.
115
115
  - **data**: `{ status: string, ... }` - Contains the event details, including the 2FA status.
116
116
 
117
117
  ---
@@ -135,6 +135,19 @@ We welcome contributions! Please follow these steps:
135
135
 
136
136
  ---
137
137
 
138
+ ## Creating and Pushing Git Tag
139
+
140
+ To create and push the `v1.0.3` release tag, run the following commands:
141
+
142
+ git tag -a v1.0.3 -m "Release version v1.0.3"
143
+ git push origin v1.0.3
144
+
145
+ 📌 This creates an annotated tag (-a) with a message and pushes it to the remote repository.
146
+
147
+ #### Note:
148
+ • Ensure your local branch is up to date with origin/main (or your target branch) before tagging.
149
+ • You can verify the tag using git tag.
150
+
138
151
  ## License 📄
139
152
  This project is licensed under the Cyphlens License. See the [LICENSE](https://cyphlens.com/legal/terms-and-conditions.html) file for details.
140
153
 
@@ -1,2 +1,2 @@
1
- var Cyphlens=function(t){"use strict";var e,s;t.EventType=void 0,(e=t.EventType||(t.EventType={})).MFASwipe="MFA.SWIPE",e.Disconnect="DISCONNECT",t.StatusType=void 0,(s=t.StatusType||(t.StatusType={})).Pending="PENDING",s.Success="SUCCESS",s.Expired="EXPIRED";class i{constructor(t="https://api.cyphme.com/b2c/v1"){this.eventSource=null,this.timeoutId=null,this.onVisibilityChange=()=>{/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&/iP(ad|od|hone)/i.test(navigator.userAgent)&&"visible"===document.visibilityState&&this.sessionID&&this.start()},this.baseUrl=t}setBaseUrl(t){this.baseUrl=t}start(){return this.sessionID?(this.stop(),this.eventSource=new EventSource(`${this.baseUrl}/cyphlens/status-events?sid=${this.sessionID}`),this.eventSource.addEventListener(t.EventType.MFASwipe,(e=>{var s,i;try{const i=JSON.parse(e.data);this.setupTimeout(i.expiresAt),null===(s=this.onSuccess)||void 0===s||s.call(this,t.EventType.MFASwipe,i)}catch(t){console.error("Error parsing event data:",t);const e=new Event("Something went wrong");null===(i=this.onError)||void 0===i||i.call(this,e)}})),this.eventSource.addEventListener("error",(t=>{var e;null===(e=this.onError)||void 0===e||e.call(this,t),this.stop()})),this.eventSource):null}setupTimeout(t){this.timeoutId&&clearTimeout(this.timeoutId);const e=t-Date.now()+5e3;this.timeoutId=setTimeout((()=>this.stop()),e)}listen(t,e,s){return this.sessionID=t,this.onSuccess=e,this.onError=s,"undefined"!=typeof document&&document.addEventListener("visibilitychange",this.onVisibilityChange),this.start()}stop(){this.eventSource&&(this.eventSource.close(),this.eventSource=null),this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null)}}return t.Cyphlens=i,t.default=i,Object.defineProperty(t,"__esModule",{value:!0}),t}({});
1
+ var Cyphlens=function(){"use strict";var t,e;!function(t){t.MFASwipe="MFA.SWIPE",t.Disconnect="DISCONNECT"}(t||(t={})),function(t){t.Pending="PENDING",t.Success="SUCCESS",t.Expired="EXPIRED"}(e||(e={}));class s{constructor(t="https://api.cyphme.com/b2c/v1"){this.eventSource=null,this.timeoutId=null,this.onVisibilityChange=()=>{/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&/iP(ad|od|hone)/i.test(navigator.userAgent)&&"visible"===document.visibilityState&&this.sessionID&&this.start()},this.baseUrl=t}setBaseUrl(t){this.baseUrl=t}start(){return this.sessionID?(this.stop(),this.eventSource=new EventSource(`${this.baseUrl}/cyphlens/status-events?sid=${this.sessionID}`),this.eventSource.addEventListener(t.MFASwipe,(e=>{var s,i;try{const i=JSON.parse(e.data);this.setupTimeout(i.expiresAt),null===(s=this.onSuccess)||void 0===s||s.call(this,t.MFASwipe,i)}catch(t){console.error("Error parsing event data:",t);const e=new Event("Something went wrong");null===(i=this.onError)||void 0===i||i.call(this,e)}})),this.eventSource.addEventListener("error",(t=>{var e;null===(e=this.onError)||void 0===e||e.call(this,t),this.stop()})),this.eventSource):null}setupTimeout(t){this.timeoutId&&clearTimeout(this.timeoutId);const e=t-Date.now()+5e3;this.timeoutId=setTimeout((()=>this.stop()),e)}listen(t,e,s){return this.sessionID=t,this.onSuccess=e,this.onError=s,"undefined"!=typeof document&&document.addEventListener("visibilitychange",this.onVisibilityChange),this.start()}stop(){this.eventSource&&(this.eventSource.close(),this.eventSource=null),this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null)}}return s.EventType=t,s.StatusType=e,s}();
2
2
  //# sourceMappingURL=bundle.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.min.js","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":["export enum EventType {\n MFASwipe = \"MFA.SWIPE\",\n Disconnect = \"DISCONNECT\",\n}\n\nexport enum StatusType {\n Pending = \"PENDING\",\n Success = \"SUCCESS\",\n Expired = \"EXPIRED\",\n}\n\nexport interface CyphlensEvent {}\n\nexport interface TwoFactorEvent extends CyphlensEvent { \n sessionId: string;\n status: StatusType;\n timestamp: number;\n expiresAt: number;\n}\n\nexport interface DisconnectEvent extends CyphlensEvent {\n message: string;\n}\n\nexport type EventCallback = (eventType: EventType, data: CyphlensEvent) => void;\nexport type CyphlensErrorCallback = (error: Event) => void;\n","import { EventCallback, TwoFactorEvent, EventType, CyphlensErrorCallback, StatusType, DisconnectEvent, CyphlensEvent } from './types';\nexport { EventCallback, TwoFactorEvent, EventType, CyphlensErrorCallback, StatusType, DisconnectEvent, CyphlensEvent }\nexport class Cyphlens {\n private baseUrl: string;\n private eventSource: EventSource | null = null;\n private sessionID?: string;\n private onSuccess?: EventCallback;\n private onError?: CyphlensErrorCallback;\n private timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n /**\n * Initializes the Cyphlens service with a base URL.\n * @param baseUrl The base API URL for connecting to the Cyphlens service.\n */\n constructor(baseUrl: string = \"https://api.cyphme.com/b2c/v1\") {\n this.baseUrl = baseUrl;\n }\n\n /**\n * Updates the base API URL.\n * @param baseUrl The new base URL.\n */\n setBaseUrl(baseUrl: string): void {\n this.baseUrl = baseUrl;\n }\n\n /**\n * Starts the Server-Sent Events (SSE) connection to listen for authentication events.\n * @returns The EventSource instance if successful, otherwise null.\n */\n private start(): EventSource | null {\n if (!this.sessionID) return null;\n\n this.stop(); // Ensure any existing connections are closed before starting a new one.\n\n this.eventSource = new EventSource(`${this.baseUrl}/cyphlens/status-events?sid=${this.sessionID}`);\n\n // Listen for MFA swipe events\n this.eventSource.addEventListener(EventType.MFASwipe, (event: MessageEvent) => {\n try {\n const data: TwoFactorEvent = JSON.parse(event.data);\n this.setupTimeout(data.expiresAt);\n this.onSuccess?.(EventType.MFASwipe, data);\n } catch (error) {\n console.error(\"Error parsing event data:\", error);\n const errorEvent = new Event('Something went wrong');\n this.onError?.(errorEvent);\n }\n });\n\n // Handle SSE errors\n this.eventSource.addEventListener(\"error\", (event: Event) => {\n this.onError?.(event);\n this.stop();\n });\n\n return this.eventSource;\n }\n\n /**\n * Sets up a timeout to automatically stop the SSE connection when the event expires.\n * @param expiresAt The expiration timestamp (milliseconds).\n */\n private setupTimeout(expiresAt: number): void {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n }\n\n // Calculate timeout duration and add a buffer (5000ms) before stopping the connection.\n const timeoutDuration = expiresAt - Date.now() + 5000;\n this.timeoutId = setTimeout(() => this.stop(), timeoutDuration);\n }\n\n /**\n * Starts listening for authentication events.\n * @param sessionId The session ID used for authentication.\n * @param onData Callback function for handling successful authentication events.\n * @param onError Callback function for handling errors.\n * @returns The EventSource instance if successfully started, otherwise null.\n */\n listen(sessionId: string, onData?: EventCallback, onError?: CyphlensErrorCallback): EventSource | null {\n this.sessionID = sessionId;\n this.onSuccess = onData;\n this.onError = onError;\n\n // Attach visibility change listener to handle browser background issues (especially for iOS Safari).\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n\n return this.start();\n }\n\n /**\n * Stops the SSE connection and clears any active timeouts.\n */\n stop(): void {\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n /**\n * Handles browser visibility changes to restart the SSE connection when the page becomes visible.\n * This is primarily to prevent connection loss in Safari when the tab goes to the background.\n * Only applies to Mobile Safari.\n */\n private readonly onVisibilityChange = (): void => {\n const isMobileSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) &&\n /iP(ad|od|hone)/i.test(navigator.userAgent);\n if (isMobileSafari && document.visibilityState === \"visible\" && this.sessionID) {\n this.start();\n }\n };\n }\n\nexport type CyphlensExports = {\n Cyphlens: typeof Cyphlens;\n EventType: typeof EventType;\n StatusType: typeof StatusType;\n TwoFactorEvent: TwoFactorEvent;\n CyphlensEvent: CyphlensEvent;\n DisconnectEvent: DisconnectEvent;\n EventCallback: EventCallback;\n CyphlensErrorCallback: CyphlensErrorCallback;\n};\n\nexport default Cyphlens;\n"],"names":["EventType","StatusType","Cyphlens","constructor","baseUrl","this","eventSource","timeoutId","onVisibilityChange","test","navigator","userAgent","document","visibilityState","sessionID","start","setBaseUrl","stop","EventSource","addEventListener","MFASwipe","event","data","JSON","parse","setupTimeout","expiresAt","_a","onSuccess","call","error","console","errorEvent","Event","_b","onError","clearTimeout","timeoutDuration","Date","now","setTimeout","listen","sessionId","onData","close"],"mappings":"sCAAA,IAAYA,EAKAC,EALAD,EAAAA,eAAAA,GAAAA,EAAAA,EAASA,YAATA,YAGX,CAAA,IAFC,SAAA,YACAA,EAAA,WAAA,aAGUC,EAAAA,gBAAAA,GAAAA,EAAAA,EAAUA,aAAVA,aAIX,CAAA,IAHC,QAAA,UACAA,EAAA,QAAA,UACAA,EAAA,QAAA,gBCNWC,EAYX,WAAAC,CAAYC,EAAkB,iCAVtBC,KAAWC,YAAuB,KAIlCD,KAASE,UAAyC,KAwGzCF,KAAkBG,mBAAG,KACb,iCAAiCC,KAAKC,UAAUC,YACjD,kBAAkBF,KAAKC,UAAUC,YACJ,YAA7BC,SAASC,iBAAiCR,KAAKS,WACnET,KAAKU,SArGPV,KAAKD,QAAUA,EAOjB,UAAAY,CAAWZ,GACTC,KAAKD,QAAUA,EAOT,KAAAW,GACN,OAAKV,KAAKS,WAEVT,KAAKY,OAELZ,KAAKC,YAAc,IAAIY,YAAY,GAAGb,KAAKD,sCAAsCC,KAAKS,aAGtFT,KAAKC,YAAYa,iBAAiBnB,EAASA,UAACoB,UAAWC,YACrD,IACE,MAAMC,EAAuBC,KAAKC,MAAMH,EAAMC,MAC9CjB,KAAKoB,aAAaH,EAAKI,WACN,QAAjBC,EAAAtB,KAAKuB,iBAAY,IAAAD,GAAAA,EAAAE,KAAAxB,KAAAL,EAAAA,UAAUoB,SAAUE,GACrC,MAAOQ,GACPC,QAAQD,MAAM,4BAA6BA,GAC3C,MAAME,EAAa,IAAIC,MAAM,wBACd,QAAfC,EAAA7B,KAAK8B,eAAU,IAAAD,GAAAA,EAAAL,KAAAxB,KAAA2B,OAKnB3B,KAAKC,YAAYa,iBAAiB,SAAUE,UAC3B,QAAfM,EAAAtB,KAAK8B,eAAU,IAAAR,GAAAA,EAAAE,KAAAxB,KAAAgB,GACfhB,KAAKY,MAAM,IAGNZ,KAAKC,aAzBgB,KAgCtB,YAAAmB,CAAaC,GACfrB,KAAKE,WACP6B,aAAa/B,KAAKE,WAIpB,MAAM8B,EAAkBX,EAAYY,KAAKC,MAAQ,IACjDlC,KAAKE,UAAYiC,YAAW,IAAMnC,KAAKY,QAAQoB,GAUjD,MAAAI,CAAOC,EAAmBC,EAAwBR,GAUhD,OATA9B,KAAKS,UAAY4B,EACjBrC,KAAKuB,UAAYe,EACjBtC,KAAK8B,QAAUA,EAGS,oBAAbvB,UACTA,SAASO,iBAAiB,mBAAoBd,KAAKG,oBAG9CH,KAAKU,QAMd,IAAAE,GACMZ,KAAKC,cACPD,KAAKC,YAAYsC,QACjBvC,KAAKC,YAAc,MAEjBD,KAAKE,YACP6B,aAAa/B,KAAKE,WAClBF,KAAKE,UAAY"}
1
+ {"version":3,"file":"bundle.min.js","sources":["../src/types.ts","../src/index.ts","../src/index.iife.js"],"sourcesContent":[null,null,"// we are using a separate index.iife.js file as entry point to generate bundle.min.js to have only one default export\nimport Cyphlens, {EventType, StatusType} from \"./index.ts\"\n\nCyphlens.EventType = EventType;\nCyphlens.StatusType = StatusType;\nexport default Cyphlens;\n\n"],"names":["EventType","StatusType","Cyphlens","constructor","baseUrl","this","eventSource","timeoutId","onVisibilityChange","test","navigator","userAgent","document","visibilityState","sessionID","start","setBaseUrl","stop","EventSource","addEventListener","MFASwipe","event","data","JSON","parse","setupTimeout","expiresAt","_a","onSuccess","call","error","console","errorEvent","Event","_b","onError","clearTimeout","timeoutDuration","Date","now","setTimeout","listen","sessionId","onData","close"],"mappings":"qCAAA,IAAYA,EAKAC,GALZ,SAAYD,GACVA,EAAA,SAAA,YACAA,EAAA,WAAA,YACD,CAHD,CAAYA,IAAAA,EAGX,CAAA,IAED,SAAYC,GACVA,EAAA,QAAA,UACAA,EAAA,QAAA,UACAA,EAAA,QAAA,SACD,CAJD,CAAYA,IAAAA,EAIX,CAAA,UCPYC,EAYX,WAAAC,CAAYC,EAAkB,iCAVtBC,KAAWC,YAAuB,KAIlCD,KAASE,UAAyC,KAwGzCF,KAAkBG,mBAAG,KACb,iCAAiCC,KAAKC,UAAUC,YACjD,kBAAkBF,KAAKC,UAAUC,YACJ,YAA7BC,SAASC,iBAAiCR,KAAKS,WACnET,KAAKU,SArGPV,KAAKD,QAAUA,EAOjB,UAAAY,CAAWZ,GACTC,KAAKD,QAAUA,EAOT,KAAAW,GACN,OAAKV,KAAKS,WAEVT,KAAKY,OAELZ,KAAKC,YAAc,IAAIY,YAAY,GAAGb,KAAKD,sCAAsCC,KAAKS,aAGtFT,KAAKC,YAAYa,iBAAiBnB,EAAUoB,UAAWC,YACrD,IACE,MAAMC,EAAuBC,KAAKC,MAAMH,EAAMC,MAC9CjB,KAAKoB,aAAaH,EAAKI,WACN,QAAjBC,EAAAtB,KAAKuB,iBAAY,IAAAD,GAAAA,EAAAE,KAAAxB,KAAAL,EAAUoB,SAAUE,GACrC,MAAOQ,GACPC,QAAQD,MAAM,4BAA6BA,GAC3C,MAAME,EAAa,IAAIC,MAAM,wBACd,QAAfC,EAAA7B,KAAK8B,eAAU,IAAAD,GAAAA,EAAAL,KAAAxB,KAAA2B,OAKnB3B,KAAKC,YAAYa,iBAAiB,SAAUE,UAC3B,QAAfM,EAAAtB,KAAK8B,eAAU,IAAAR,GAAAA,EAAAE,KAAAxB,KAAAgB,GACfhB,KAAKY,MAAM,IAGNZ,KAAKC,aAzBgB,KAgCtB,YAAAmB,CAAaC,GACfrB,KAAKE,WACP6B,aAAa/B,KAAKE,WAIpB,MAAM8B,EAAkBX,EAAYY,KAAKC,MAAQ,IACjDlC,KAAKE,UAAYiC,YAAW,IAAMnC,KAAKY,QAAQoB,GAUjD,MAAAI,CAAOC,EAAmBC,EAAwBR,GAUhD,OATA9B,KAAKS,UAAY4B,EACjBrC,KAAKuB,UAAYe,EACjBtC,KAAK8B,QAAUA,EAGS,oBAAbvB,UACTA,SAASO,iBAAiB,mBAAoBd,KAAKG,oBAG9CH,KAAKU,QAMd,IAAAE,GACMZ,KAAKC,cACPD,KAAKC,YAAYsC,QACjBvC,KAAKC,YAAc,MAEjBD,KAAKE,YACP6B,aAAa/B,KAAKE,WAClBF,KAAKE,UAAY,cCpGvBL,EAASF,UAAYA,EACrBE,EAASD,WAAaA"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":["export enum EventType {\n MFASwipe = \"MFA.SWIPE\",\n Disconnect = \"DISCONNECT\",\n}\n\nexport enum StatusType {\n Pending = \"PENDING\",\n Success = \"SUCCESS\",\n Expired = \"EXPIRED\",\n}\n\nexport interface CyphlensEvent {}\n\nexport interface TwoFactorEvent extends CyphlensEvent { \n sessionId: string;\n status: StatusType;\n timestamp: number;\n expiresAt: number;\n}\n\nexport interface DisconnectEvent extends CyphlensEvent {\n message: string;\n}\n\nexport type EventCallback = (eventType: EventType, data: CyphlensEvent) => void;\nexport type CyphlensErrorCallback = (error: Event) => void;\n","import { EventCallback, TwoFactorEvent, EventType, CyphlensErrorCallback, StatusType, DisconnectEvent, CyphlensEvent } from './types';\nexport { EventCallback, TwoFactorEvent, EventType, CyphlensErrorCallback, StatusType, DisconnectEvent, CyphlensEvent }\nexport class Cyphlens {\n private baseUrl: string;\n private eventSource: EventSource | null = null;\n private sessionID?: string;\n private onSuccess?: EventCallback;\n private onError?: CyphlensErrorCallback;\n private timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n /**\n * Initializes the Cyphlens service with a base URL.\n * @param baseUrl The base API URL for connecting to the Cyphlens service.\n */\n constructor(baseUrl: string = \"https://api.cyphme.com/b2c/v1\") {\n this.baseUrl = baseUrl;\n }\n\n /**\n * Updates the base API URL.\n * @param baseUrl The new base URL.\n */\n setBaseUrl(baseUrl: string): void {\n this.baseUrl = baseUrl;\n }\n\n /**\n * Starts the Server-Sent Events (SSE) connection to listen for authentication events.\n * @returns The EventSource instance if successful, otherwise null.\n */\n private start(): EventSource | null {\n if (!this.sessionID) return null;\n\n this.stop(); // Ensure any existing connections are closed before starting a new one.\n\n this.eventSource = new EventSource(`${this.baseUrl}/cyphlens/status-events?sid=${this.sessionID}`);\n\n // Listen for MFA swipe events\n this.eventSource.addEventListener(EventType.MFASwipe, (event: MessageEvent) => {\n try {\n const data: TwoFactorEvent = JSON.parse(event.data);\n this.setupTimeout(data.expiresAt);\n this.onSuccess?.(EventType.MFASwipe, data);\n } catch (error) {\n console.error(\"Error parsing event data:\", error);\n const errorEvent = new Event('Something went wrong');\n this.onError?.(errorEvent);\n }\n });\n\n // Handle SSE errors\n this.eventSource.addEventListener(\"error\", (event: Event) => {\n this.onError?.(event);\n this.stop();\n });\n\n return this.eventSource;\n }\n\n /**\n * Sets up a timeout to automatically stop the SSE connection when the event expires.\n * @param expiresAt The expiration timestamp (milliseconds).\n */\n private setupTimeout(expiresAt: number): void {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n }\n\n // Calculate timeout duration and add a buffer (5000ms) before stopping the connection.\n const timeoutDuration = expiresAt - Date.now() + 5000;\n this.timeoutId = setTimeout(() => this.stop(), timeoutDuration);\n }\n\n /**\n * Starts listening for authentication events.\n * @param sessionId The session ID used for authentication.\n * @param onData Callback function for handling successful authentication events.\n * @param onError Callback function for handling errors.\n * @returns The EventSource instance if successfully started, otherwise null.\n */\n listen(sessionId: string, onData?: EventCallback, onError?: CyphlensErrorCallback): EventSource | null {\n this.sessionID = sessionId;\n this.onSuccess = onData;\n this.onError = onError;\n\n // Attach visibility change listener to handle browser background issues (especially for iOS Safari).\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n\n return this.start();\n }\n\n /**\n * Stops the SSE connection and clears any active timeouts.\n */\n stop(): void {\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n /**\n * Handles browser visibility changes to restart the SSE connection when the page becomes visible.\n * This is primarily to prevent connection loss in Safari when the tab goes to the background.\n * Only applies to Mobile Safari.\n */\n private readonly onVisibilityChange = (): void => {\n const isMobileSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) &&\n /iP(ad|od|hone)/i.test(navigator.userAgent);\n if (isMobileSafari && document.visibilityState === \"visible\" && this.sessionID) {\n this.start();\n }\n };\n }\n\nexport type CyphlensExports = {\n Cyphlens: typeof Cyphlens;\n EventType: typeof EventType;\n StatusType: typeof StatusType;\n TwoFactorEvent: TwoFactorEvent;\n CyphlensEvent: CyphlensEvent;\n DisconnectEvent: DisconnectEvent;\n EventCallback: EventCallback;\n CyphlensErrorCallback: CyphlensErrorCallback;\n};\n\nexport default Cyphlens;\n"],"names":["EventType","StatusType","Cyphlens","constructor","baseUrl","this","eventSource","timeoutId","onVisibilityChange","test","navigator","userAgent","document","visibilityState","sessionID","start","setBaseUrl","stop","EventSource","addEventListener","MFASwipe","event","data","JSON","parse","setupTimeout","expiresAt","_a","onSuccess","call","error","console","errorEvent","Event","_b","onError","clearTimeout","timeoutDuration","Date","now","setTimeout","listen","sessionId","onData","close"],"mappings":"IAAYA,EAKAC,GALZ,SAAYD,GACVA,EAAA,SAAA,YACAA,EAAA,WAAA,YACD,CAHD,CAAYA,IAAAA,EAGX,CAAA,IAED,SAAYC,GACVA,EAAA,QAAA,UACAA,EAAA,QAAA,UACAA,EAAA,QAAA,SACD,CAJD,CAAYA,IAAAA,EAIX,CAAA,UCPYC,EAYX,WAAAC,CAAYC,EAAkB,iCAVtBC,KAAWC,YAAuB,KAIlCD,KAASE,UAAyC,KAwGzCF,KAAkBG,mBAAG,KACb,iCAAiCC,KAAKC,UAAUC,YACjD,kBAAkBF,KAAKC,UAAUC,YACJ,YAA7BC,SAASC,iBAAiCR,KAAKS,WACnET,KAAKU,SArGPV,KAAKD,QAAUA,EAOjB,UAAAY,CAAWZ,GACTC,KAAKD,QAAUA,EAOT,KAAAW,GACN,OAAKV,KAAKS,WAEVT,KAAKY,OAELZ,KAAKC,YAAc,IAAIY,YAAY,GAAGb,KAAKD,sCAAsCC,KAAKS,aAGtFT,KAAKC,YAAYa,iBAAiBnB,EAAUoB,UAAWC,YACrD,IACE,MAAMC,EAAuBC,KAAKC,MAAMH,EAAMC,MAC9CjB,KAAKoB,aAAaH,EAAKI,WACN,QAAjBC,EAAAtB,KAAKuB,iBAAY,IAAAD,GAAAA,EAAAE,KAAAxB,KAAAL,EAAUoB,SAAUE,GACrC,MAAOQ,GACPC,QAAQD,MAAM,4BAA6BA,GAC3C,MAAME,EAAa,IAAIC,MAAM,wBACd,QAAfC,EAAA7B,KAAK8B,eAAU,IAAAD,GAAAA,EAAAL,KAAAxB,KAAA2B,OAKnB3B,KAAKC,YAAYa,iBAAiB,SAAUE,UAC3B,QAAfM,EAAAtB,KAAK8B,eAAU,IAAAR,GAAAA,EAAAE,KAAAxB,KAAAgB,GACfhB,KAAKY,MAAM,IAGNZ,KAAKC,aAzBgB,KAgCtB,YAAAmB,CAAaC,GACfrB,KAAKE,WACP6B,aAAa/B,KAAKE,WAIpB,MAAM8B,EAAkBX,EAAYY,KAAKC,MAAQ,IACjDlC,KAAKE,UAAYiC,YAAW,IAAMnC,KAAKY,QAAQoB,GAUjD,MAAAI,CAAOC,EAAmBC,EAAwBR,GAUhD,OATA9B,KAAKS,UAAY4B,EACjBrC,KAAKuB,UAAYe,EACjBtC,KAAK8B,QAAUA,EAGS,oBAAbvB,UACTA,SAASO,iBAAiB,mBAAoBd,KAAKG,oBAG9CH,KAAKU,QAMd,IAAAE,GACMZ,KAAKC,cACPD,KAAKC,YAAYsC,QACjBvC,KAAKC,YAAc,MAEjBD,KAAKE,YACP6B,aAAa/B,KAAKE,WAClBF,KAAKE,UAAY"}
1
+ {"version":3,"file":"index.esm.js","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":[null,null],"names":["EventType","StatusType","Cyphlens","constructor","baseUrl","this","eventSource","timeoutId","onVisibilityChange","test","navigator","userAgent","document","visibilityState","sessionID","start","setBaseUrl","stop","EventSource","addEventListener","MFASwipe","event","data","JSON","parse","setupTimeout","expiresAt","_a","onSuccess","call","error","console","errorEvent","Event","_b","onError","clearTimeout","timeoutDuration","Date","now","setTimeout","listen","sessionId","onData","close"],"mappings":"IAAYA,EAKAC,GALZ,SAAYD,GACVA,EAAA,SAAA,YACAA,EAAA,WAAA,YACD,CAHD,CAAYA,IAAAA,EAGX,CAAA,IAED,SAAYC,GACVA,EAAA,QAAA,UACAA,EAAA,QAAA,UACAA,EAAA,QAAA,SACD,CAJD,CAAYA,IAAAA,EAIX,CAAA,UCPYC,EAYX,WAAAC,CAAYC,EAAkB,iCAVtBC,KAAWC,YAAuB,KAIlCD,KAASE,UAAyC,KAwGzCF,KAAkBG,mBAAG,KACb,iCAAiCC,KAAKC,UAAUC,YACjD,kBAAkBF,KAAKC,UAAUC,YACJ,YAA7BC,SAASC,iBAAiCR,KAAKS,WACnET,KAAKU,SArGPV,KAAKD,QAAUA,EAOjB,UAAAY,CAAWZ,GACTC,KAAKD,QAAUA,EAOT,KAAAW,GACN,OAAKV,KAAKS,WAEVT,KAAKY,OAELZ,KAAKC,YAAc,IAAIY,YAAY,GAAGb,KAAKD,sCAAsCC,KAAKS,aAGtFT,KAAKC,YAAYa,iBAAiBnB,EAAUoB,UAAWC,YACrD,IACE,MAAMC,EAAuBC,KAAKC,MAAMH,EAAMC,MAC9CjB,KAAKoB,aAAaH,EAAKI,WACN,QAAjBC,EAAAtB,KAAKuB,iBAAY,IAAAD,GAAAA,EAAAE,KAAAxB,KAAAL,EAAUoB,SAAUE,GACrC,MAAOQ,GACPC,QAAQD,MAAM,4BAA6BA,GAC3C,MAAME,EAAa,IAAIC,MAAM,wBACd,QAAfC,EAAA7B,KAAK8B,eAAU,IAAAD,GAAAA,EAAAL,KAAAxB,KAAA2B,OAKnB3B,KAAKC,YAAYa,iBAAiB,SAAUE,UAC3B,QAAfM,EAAAtB,KAAK8B,eAAU,IAAAR,GAAAA,EAAAE,KAAAxB,KAAAgB,GACfhB,KAAKY,MAAM,IAGNZ,KAAKC,aAzBgB,KAgCtB,YAAAmB,CAAaC,GACfrB,KAAKE,WACP6B,aAAa/B,KAAKE,WAIpB,MAAM8B,EAAkBX,EAAYY,KAAKC,MAAQ,IACjDlC,KAAKE,UAAYiC,YAAW,IAAMnC,KAAKY,QAAQoB,GAUjD,MAAAI,CAAOC,EAAmBC,EAAwBR,GAUhD,OATA9B,KAAKS,UAAY4B,EACjBrC,KAAKuB,UAAYe,EACjBtC,KAAK8B,QAAUA,EAGS,oBAAbvB,UACTA,SAASO,iBAAiB,mBAAoBd,KAAKG,oBAG9CH,KAAKU,QAMd,IAAAE,GACMZ,KAAKC,cACPD,KAAKC,YAAYsC,QACjBvC,KAAKC,YAAc,MAEjBD,KAAKE,YACP6B,aAAa/B,KAAKE,WAClBF,KAAKE,UAAY"}
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":["export enum EventType {\n MFASwipe = \"MFA.SWIPE\",\n Disconnect = \"DISCONNECT\",\n}\n\nexport enum StatusType {\n Pending = \"PENDING\",\n Success = \"SUCCESS\",\n Expired = \"EXPIRED\",\n}\n\nexport interface CyphlensEvent {}\n\nexport interface TwoFactorEvent extends CyphlensEvent { \n sessionId: string;\n status: StatusType;\n timestamp: number;\n expiresAt: number;\n}\n\nexport interface DisconnectEvent extends CyphlensEvent {\n message: string;\n}\n\nexport type EventCallback = (eventType: EventType, data: CyphlensEvent) => void;\nexport type CyphlensErrorCallback = (error: Event) => void;\n","import { EventCallback, TwoFactorEvent, EventType, CyphlensErrorCallback, StatusType, DisconnectEvent, CyphlensEvent } from './types';\nexport { EventCallback, TwoFactorEvent, EventType, CyphlensErrorCallback, StatusType, DisconnectEvent, CyphlensEvent }\nexport class Cyphlens {\n private baseUrl: string;\n private eventSource: EventSource | null = null;\n private sessionID?: string;\n private onSuccess?: EventCallback;\n private onError?: CyphlensErrorCallback;\n private timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n /**\n * Initializes the Cyphlens service with a base URL.\n * @param baseUrl The base API URL for connecting to the Cyphlens service.\n */\n constructor(baseUrl: string = \"https://api.cyphme.com/b2c/v1\") {\n this.baseUrl = baseUrl;\n }\n\n /**\n * Updates the base API URL.\n * @param baseUrl The new base URL.\n */\n setBaseUrl(baseUrl: string): void {\n this.baseUrl = baseUrl;\n }\n\n /**\n * Starts the Server-Sent Events (SSE) connection to listen for authentication events.\n * @returns The EventSource instance if successful, otherwise null.\n */\n private start(): EventSource | null {\n if (!this.sessionID) return null;\n\n this.stop(); // Ensure any existing connections are closed before starting a new one.\n\n this.eventSource = new EventSource(`${this.baseUrl}/cyphlens/status-events?sid=${this.sessionID}`);\n\n // Listen for MFA swipe events\n this.eventSource.addEventListener(EventType.MFASwipe, (event: MessageEvent) => {\n try {\n const data: TwoFactorEvent = JSON.parse(event.data);\n this.setupTimeout(data.expiresAt);\n this.onSuccess?.(EventType.MFASwipe, data);\n } catch (error) {\n console.error(\"Error parsing event data:\", error);\n const errorEvent = new Event('Something went wrong');\n this.onError?.(errorEvent);\n }\n });\n\n // Handle SSE errors\n this.eventSource.addEventListener(\"error\", (event: Event) => {\n this.onError?.(event);\n this.stop();\n });\n\n return this.eventSource;\n }\n\n /**\n * Sets up a timeout to automatically stop the SSE connection when the event expires.\n * @param expiresAt The expiration timestamp (milliseconds).\n */\n private setupTimeout(expiresAt: number): void {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n }\n\n // Calculate timeout duration and add a buffer (5000ms) before stopping the connection.\n const timeoutDuration = expiresAt - Date.now() + 5000;\n this.timeoutId = setTimeout(() => this.stop(), timeoutDuration);\n }\n\n /**\n * Starts listening for authentication events.\n * @param sessionId The session ID used for authentication.\n * @param onData Callback function for handling successful authentication events.\n * @param onError Callback function for handling errors.\n * @returns The EventSource instance if successfully started, otherwise null.\n */\n listen(sessionId: string, onData?: EventCallback, onError?: CyphlensErrorCallback): EventSource | null {\n this.sessionID = sessionId;\n this.onSuccess = onData;\n this.onError = onError;\n\n // Attach visibility change listener to handle browser background issues (especially for iOS Safari).\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n\n return this.start();\n }\n\n /**\n * Stops the SSE connection and clears any active timeouts.\n */\n stop(): void {\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n /**\n * Handles browser visibility changes to restart the SSE connection when the page becomes visible.\n * This is primarily to prevent connection loss in Safari when the tab goes to the background.\n * Only applies to Mobile Safari.\n */\n private readonly onVisibilityChange = (): void => {\n const isMobileSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) &&\n /iP(ad|od|hone)/i.test(navigator.userAgent);\n if (isMobileSafari && document.visibilityState === \"visible\" && this.sessionID) {\n this.start();\n }\n };\n }\n\nexport type CyphlensExports = {\n Cyphlens: typeof Cyphlens;\n EventType: typeof EventType;\n StatusType: typeof StatusType;\n TwoFactorEvent: TwoFactorEvent;\n CyphlensEvent: CyphlensEvent;\n DisconnectEvent: DisconnectEvent;\n EventCallback: EventCallback;\n CyphlensErrorCallback: CyphlensErrorCallback;\n};\n\nexport default Cyphlens;\n"],"names":["EventType","StatusType","Cyphlens","constructor","baseUrl","this","eventSource","timeoutId","onVisibilityChange","test","navigator","userAgent","document","visibilityState","sessionID","start","setBaseUrl","stop","EventSource","addEventListener","MFASwipe","event","data","JSON","parse","setupTimeout","expiresAt","_a","onSuccess","call","error","console","errorEvent","Event","_b","onError","clearTimeout","timeoutDuration","Date","now","setTimeout","listen","sessionId","onData","close"],"mappings":"aAAA,IAAYA,EAKAC,yDALAD,QAAAA,eAAAA,GAAAA,EAAAA,QAASA,YAATA,kBAGX,CAAA,IAFC,SAAA,YACAA,EAAA,WAAA,aAGUC,QAAAA,gBAAAA,GAAAA,EAAAA,QAAUA,aAAVA,mBAIX,CAAA,IAHC,QAAA,UACAA,EAAA,QAAA,UACAA,EAAA,QAAA,gBCNWC,EAYX,WAAAC,CAAYC,EAAkB,iCAVtBC,KAAWC,YAAuB,KAIlCD,KAASE,UAAyC,KAwGzCF,KAAkBG,mBAAG,KACb,iCAAiCC,KAAKC,UAAUC,YACjD,kBAAkBF,KAAKC,UAAUC,YACJ,YAA7BC,SAASC,iBAAiCR,KAAKS,WACnET,KAAKU,SArGPV,KAAKD,QAAUA,EAOjB,UAAAY,CAAWZ,GACTC,KAAKD,QAAUA,EAOT,KAAAW,GACN,OAAKV,KAAKS,WAEVT,KAAKY,OAELZ,KAAKC,YAAc,IAAIY,YAAY,GAAGb,KAAKD,sCAAsCC,KAAKS,aAGtFT,KAAKC,YAAYa,iBAAiBnB,QAASA,UAACoB,UAAWC,YACrD,IACE,MAAMC,EAAuBC,KAAKC,MAAMH,EAAMC,MAC9CjB,KAAKoB,aAAaH,EAAKI,WACN,QAAjBC,EAAAtB,KAAKuB,iBAAY,IAAAD,GAAAA,EAAAE,KAAAxB,KAAAL,QAAAA,UAAUoB,SAAUE,GACrC,MAAOQ,GACPC,QAAQD,MAAM,4BAA6BA,GAC3C,MAAME,EAAa,IAAIC,MAAM,wBACd,QAAfC,EAAA7B,KAAK8B,eAAU,IAAAD,GAAAA,EAAAL,KAAAxB,KAAA2B,OAKnB3B,KAAKC,YAAYa,iBAAiB,SAAUE,UAC3B,QAAfM,EAAAtB,KAAK8B,eAAU,IAAAR,GAAAA,EAAAE,KAAAxB,KAAAgB,GACfhB,KAAKY,MAAM,IAGNZ,KAAKC,aAzBgB,KAgCtB,YAAAmB,CAAaC,GACfrB,KAAKE,WACP6B,aAAa/B,KAAKE,WAIpB,MAAM8B,EAAkBX,EAAYY,KAAKC,MAAQ,IACjDlC,KAAKE,UAAYiC,YAAW,IAAMnC,KAAKY,QAAQoB,GAUjD,MAAAI,CAAOC,EAAmBC,EAAwBR,GAUhD,OATA9B,KAAKS,UAAY4B,EACjBrC,KAAKuB,UAAYe,EACjBtC,KAAK8B,QAAUA,EAGS,oBAAbvB,UACTA,SAASO,iBAAiB,mBAAoBd,KAAKG,oBAG9CH,KAAKU,QAMd,IAAAE,GACMZ,KAAKC,cACPD,KAAKC,YAAYsC,QACjBvC,KAAKC,YAAc,MAEjBD,KAAKE,YACP6B,aAAa/B,KAAKE,WAClBF,KAAKE,UAAY"}
1
+ {"version":3,"file":"index.js","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":[null,null],"names":["EventType","StatusType","Cyphlens","constructor","baseUrl","this","eventSource","timeoutId","onVisibilityChange","test","navigator","userAgent","document","visibilityState","sessionID","start","setBaseUrl","stop","EventSource","addEventListener","MFASwipe","event","data","JSON","parse","setupTimeout","expiresAt","_a","onSuccess","call","error","console","errorEvent","Event","_b","onError","clearTimeout","timeoutDuration","Date","now","setTimeout","listen","sessionId","onData","close"],"mappings":"aAAA,IAAYA,EAKAC,yDALAD,QAAAA,eAAAA,GAAAA,EAAAA,QAASA,YAATA,kBAGX,CAAA,IAFC,SAAA,YACAA,EAAA,WAAA,aAGUC,QAAAA,gBAAAA,GAAAA,EAAAA,QAAUA,aAAVA,mBAIX,CAAA,IAHC,QAAA,UACAA,EAAA,QAAA,UACAA,EAAA,QAAA,gBCNWC,EAYX,WAAAC,CAAYC,EAAkB,iCAVtBC,KAAWC,YAAuB,KAIlCD,KAASE,UAAyC,KAwGzCF,KAAkBG,mBAAG,KACb,iCAAiCC,KAAKC,UAAUC,YACjD,kBAAkBF,KAAKC,UAAUC,YACJ,YAA7BC,SAASC,iBAAiCR,KAAKS,WACnET,KAAKU,SArGPV,KAAKD,QAAUA,EAOjB,UAAAY,CAAWZ,GACTC,KAAKD,QAAUA,EAOT,KAAAW,GACN,OAAKV,KAAKS,WAEVT,KAAKY,OAELZ,KAAKC,YAAc,IAAIY,YAAY,GAAGb,KAAKD,sCAAsCC,KAAKS,aAGtFT,KAAKC,YAAYa,iBAAiBnB,QAASA,UAACoB,UAAWC,YACrD,IACE,MAAMC,EAAuBC,KAAKC,MAAMH,EAAMC,MAC9CjB,KAAKoB,aAAaH,EAAKI,WACN,QAAjBC,EAAAtB,KAAKuB,iBAAY,IAAAD,GAAAA,EAAAE,KAAAxB,KAAAL,QAAAA,UAAUoB,SAAUE,GACrC,MAAOQ,GACPC,QAAQD,MAAM,4BAA6BA,GAC3C,MAAME,EAAa,IAAIC,MAAM,wBACd,QAAfC,EAAA7B,KAAK8B,eAAU,IAAAD,GAAAA,EAAAL,KAAAxB,KAAA2B,OAKnB3B,KAAKC,YAAYa,iBAAiB,SAAUE,UAC3B,QAAfM,EAAAtB,KAAK8B,eAAU,IAAAR,GAAAA,EAAAE,KAAAxB,KAAAgB,GACfhB,KAAKY,MAAM,IAGNZ,KAAKC,aAzBgB,KAgCtB,YAAAmB,CAAaC,GACfrB,KAAKE,WACP6B,aAAa/B,KAAKE,WAIpB,MAAM8B,EAAkBX,EAAYY,KAAKC,MAAQ,IACjDlC,KAAKE,UAAYiC,YAAW,IAAMnC,KAAKY,QAAQoB,GAUjD,MAAAI,CAAOC,EAAmBC,EAAwBR,GAUhD,OATA9B,KAAKS,UAAY4B,EACjBrC,KAAKuB,UAAYe,EACjBtC,KAAK8B,QAAUA,EAGS,oBAAbvB,UACTA,SAASO,iBAAiB,mBAAoBd,KAAKG,oBAG9CH,KAAKU,QAMd,IAAAE,GACMZ,KAAKC,cACPD,KAAKC,YAAYsC,QACjBvC,KAAKC,YAAc,MAEjBD,KAAKE,YACP6B,aAAa/B,KAAKE,WAClBF,KAAKE,UAAY"}
package/dist/index.umd.js CHANGED
@@ -1,2 +1,2 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CyphlensSSE={})}(this,(function(e){"use strict";var t,s;e.EventType=void 0,(t=e.EventType||(e.EventType={})).MFASwipe="MFA.SWIPE",t.Disconnect="DISCONNECT",e.StatusType=void 0,(s=e.StatusType||(e.StatusType={})).Pending="PENDING",s.Success="SUCCESS",s.Expired="EXPIRED";class i{constructor(e="https://api.cyphme.com/b2c/v1"){this.eventSource=null,this.timeoutId=null,this.onVisibilityChange=()=>{/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&/iP(ad|od|hone)/i.test(navigator.userAgent)&&"visible"===document.visibilityState&&this.sessionID&&this.start()},this.baseUrl=e}setBaseUrl(e){this.baseUrl=e}start(){return this.sessionID?(this.stop(),this.eventSource=new EventSource(`${this.baseUrl}/cyphlens/status-events?sid=${this.sessionID}`),this.eventSource.addEventListener(e.EventType.MFASwipe,(t=>{var s,i;try{const i=JSON.parse(t.data);this.setupTimeout(i.expiresAt),null===(s=this.onSuccess)||void 0===s||s.call(this,e.EventType.MFASwipe,i)}catch(e){console.error("Error parsing event data:",e);const t=new Event("Something went wrong");null===(i=this.onError)||void 0===i||i.call(this,t)}})),this.eventSource.addEventListener("error",(e=>{var t;null===(t=this.onError)||void 0===t||t.call(this,e),this.stop()})),this.eventSource):null}setupTimeout(e){this.timeoutId&&clearTimeout(this.timeoutId);const t=e-Date.now()+5e3;this.timeoutId=setTimeout((()=>this.stop()),t)}listen(e,t,s){return this.sessionID=e,this.onSuccess=t,this.onError=s,"undefined"!=typeof document&&document.addEventListener("visibilitychange",this.onVisibilityChange),this.start()}stop(){this.eventSource&&(this.eventSource.close(),this.eventSource=null),this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null)}}e.Cyphlens=i,e.default=i,Object.defineProperty(e,"__esModule",{value:!0})}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Cyphlens={})}(this,(function(e){"use strict";var t,s;e.EventType=void 0,(t=e.EventType||(e.EventType={})).MFASwipe="MFA.SWIPE",t.Disconnect="DISCONNECT",e.StatusType=void 0,(s=e.StatusType||(e.StatusType={})).Pending="PENDING",s.Success="SUCCESS",s.Expired="EXPIRED";class i{constructor(e="https://api.cyphme.com/b2c/v1"){this.eventSource=null,this.timeoutId=null,this.onVisibilityChange=()=>{/^((?!chrome|android).)*safari/i.test(navigator.userAgent)&&/iP(ad|od|hone)/i.test(navigator.userAgent)&&"visible"===document.visibilityState&&this.sessionID&&this.start()},this.baseUrl=e}setBaseUrl(e){this.baseUrl=e}start(){return this.sessionID?(this.stop(),this.eventSource=new EventSource(`${this.baseUrl}/cyphlens/status-events?sid=${this.sessionID}`),this.eventSource.addEventListener(e.EventType.MFASwipe,(t=>{var s,i;try{const i=JSON.parse(t.data);this.setupTimeout(i.expiresAt),null===(s=this.onSuccess)||void 0===s||s.call(this,e.EventType.MFASwipe,i)}catch(e){console.error("Error parsing event data:",e);const t=new Event("Something went wrong");null===(i=this.onError)||void 0===i||i.call(this,t)}})),this.eventSource.addEventListener("error",(e=>{var t;null===(t=this.onError)||void 0===t||t.call(this,e),this.stop()})),this.eventSource):null}setupTimeout(e){this.timeoutId&&clearTimeout(this.timeoutId);const t=e-Date.now()+5e3;this.timeoutId=setTimeout((()=>this.stop()),t)}listen(e,t,s){return this.sessionID=e,this.onSuccess=t,this.onError=s,"undefined"!=typeof document&&document.addEventListener("visibilitychange",this.onVisibilityChange),this.start()}stop(){this.eventSource&&(this.eventSource.close(),this.eventSource=null),this.timeoutId&&(clearTimeout(this.timeoutId),this.timeoutId=null)}}e.Cyphlens=i,e.default=i,Object.defineProperty(e,"__esModule",{value:!0})}));
2
2
  //# sourceMappingURL=index.umd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.umd.js","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":["export enum EventType {\n MFASwipe = \"MFA.SWIPE\",\n Disconnect = \"DISCONNECT\",\n}\n\nexport enum StatusType {\n Pending = \"PENDING\",\n Success = \"SUCCESS\",\n Expired = \"EXPIRED\",\n}\n\nexport interface CyphlensEvent {}\n\nexport interface TwoFactorEvent extends CyphlensEvent { \n sessionId: string;\n status: StatusType;\n timestamp: number;\n expiresAt: number;\n}\n\nexport interface DisconnectEvent extends CyphlensEvent {\n message: string;\n}\n\nexport type EventCallback = (eventType: EventType, data: CyphlensEvent) => void;\nexport type CyphlensErrorCallback = (error: Event) => void;\n","import { EventCallback, TwoFactorEvent, EventType, CyphlensErrorCallback, StatusType, DisconnectEvent, CyphlensEvent } from './types';\nexport { EventCallback, TwoFactorEvent, EventType, CyphlensErrorCallback, StatusType, DisconnectEvent, CyphlensEvent }\nexport class Cyphlens {\n private baseUrl: string;\n private eventSource: EventSource | null = null;\n private sessionID?: string;\n private onSuccess?: EventCallback;\n private onError?: CyphlensErrorCallback;\n private timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n /**\n * Initializes the Cyphlens service with a base URL.\n * @param baseUrl The base API URL for connecting to the Cyphlens service.\n */\n constructor(baseUrl: string = \"https://api.cyphme.com/b2c/v1\") {\n this.baseUrl = baseUrl;\n }\n\n /**\n * Updates the base API URL.\n * @param baseUrl The new base URL.\n */\n setBaseUrl(baseUrl: string): void {\n this.baseUrl = baseUrl;\n }\n\n /**\n * Starts the Server-Sent Events (SSE) connection to listen for authentication events.\n * @returns The EventSource instance if successful, otherwise null.\n */\n private start(): EventSource | null {\n if (!this.sessionID) return null;\n\n this.stop(); // Ensure any existing connections are closed before starting a new one.\n\n this.eventSource = new EventSource(`${this.baseUrl}/cyphlens/status-events?sid=${this.sessionID}`);\n\n // Listen for MFA swipe events\n this.eventSource.addEventListener(EventType.MFASwipe, (event: MessageEvent) => {\n try {\n const data: TwoFactorEvent = JSON.parse(event.data);\n this.setupTimeout(data.expiresAt);\n this.onSuccess?.(EventType.MFASwipe, data);\n } catch (error) {\n console.error(\"Error parsing event data:\", error);\n const errorEvent = new Event('Something went wrong');\n this.onError?.(errorEvent);\n }\n });\n\n // Handle SSE errors\n this.eventSource.addEventListener(\"error\", (event: Event) => {\n this.onError?.(event);\n this.stop();\n });\n\n return this.eventSource;\n }\n\n /**\n * Sets up a timeout to automatically stop the SSE connection when the event expires.\n * @param expiresAt The expiration timestamp (milliseconds).\n */\n private setupTimeout(expiresAt: number): void {\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n }\n\n // Calculate timeout duration and add a buffer (5000ms) before stopping the connection.\n const timeoutDuration = expiresAt - Date.now() + 5000;\n this.timeoutId = setTimeout(() => this.stop(), timeoutDuration);\n }\n\n /**\n * Starts listening for authentication events.\n * @param sessionId The session ID used for authentication.\n * @param onData Callback function for handling successful authentication events.\n * @param onError Callback function for handling errors.\n * @returns The EventSource instance if successfully started, otherwise null.\n */\n listen(sessionId: string, onData?: EventCallback, onError?: CyphlensErrorCallback): EventSource | null {\n this.sessionID = sessionId;\n this.onSuccess = onData;\n this.onError = onError;\n\n // Attach visibility change listener to handle browser background issues (especially for iOS Safari).\n if (typeof document !== \"undefined\") {\n document.addEventListener(\"visibilitychange\", this.onVisibilityChange);\n }\n\n return this.start();\n }\n\n /**\n * Stops the SSE connection and clears any active timeouts.\n */\n stop(): void {\n if (this.eventSource) {\n this.eventSource.close();\n this.eventSource = null;\n }\n if (this.timeoutId) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n /**\n * Handles browser visibility changes to restart the SSE connection when the page becomes visible.\n * This is primarily to prevent connection loss in Safari when the tab goes to the background.\n * Only applies to Mobile Safari.\n */\n private readonly onVisibilityChange = (): void => {\n const isMobileSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent) &&\n /iP(ad|od|hone)/i.test(navigator.userAgent);\n if (isMobileSafari && document.visibilityState === \"visible\" && this.sessionID) {\n this.start();\n }\n };\n }\n\nexport type CyphlensExports = {\n Cyphlens: typeof Cyphlens;\n EventType: typeof EventType;\n StatusType: typeof StatusType;\n TwoFactorEvent: TwoFactorEvent;\n CyphlensEvent: CyphlensEvent;\n DisconnectEvent: DisconnectEvent;\n EventCallback: EventCallback;\n CyphlensErrorCallback: CyphlensErrorCallback;\n};\n\nexport default Cyphlens;\n"],"names":["EventType","StatusType","Cyphlens","constructor","baseUrl","this","eventSource","timeoutId","onVisibilityChange","test","navigator","userAgent","document","visibilityState","sessionID","start","setBaseUrl","stop","EventSource","addEventListener","MFASwipe","event","data","JSON","parse","setupTimeout","expiresAt","_a","onSuccess","call","error","console","errorEvent","Event","_b","onError","clearTimeout","timeoutDuration","Date","now","setTimeout","listen","sessionId","onData","close"],"mappings":"mPAAA,IAAYA,EAKAC,EALAD,EAAAA,eAAAA,GAAAA,EAAAA,EAASA,YAATA,YAGX,CAAA,IAFC,SAAA,YACAA,EAAA,WAAA,aAGUC,EAAAA,gBAAAA,GAAAA,EAAAA,EAAUA,aAAVA,aAIX,CAAA,IAHC,QAAA,UACAA,EAAA,QAAA,UACAA,EAAA,QAAA,gBCNWC,EAYX,WAAAC,CAAYC,EAAkB,iCAVtBC,KAAWC,YAAuB,KAIlCD,KAASE,UAAyC,KAwGzCF,KAAkBG,mBAAG,KACb,iCAAiCC,KAAKC,UAAUC,YACjD,kBAAkBF,KAAKC,UAAUC,YACJ,YAA7BC,SAASC,iBAAiCR,KAAKS,WACnET,KAAKU,SArGPV,KAAKD,QAAUA,EAOjB,UAAAY,CAAWZ,GACTC,KAAKD,QAAUA,EAOT,KAAAW,GACN,OAAKV,KAAKS,WAEVT,KAAKY,OAELZ,KAAKC,YAAc,IAAIY,YAAY,GAAGb,KAAKD,sCAAsCC,KAAKS,aAGtFT,KAAKC,YAAYa,iBAAiBnB,EAASA,UAACoB,UAAWC,YACrD,IACE,MAAMC,EAAuBC,KAAKC,MAAMH,EAAMC,MAC9CjB,KAAKoB,aAAaH,EAAKI,WACN,QAAjBC,EAAAtB,KAAKuB,iBAAY,IAAAD,GAAAA,EAAAE,KAAAxB,KAAAL,EAAAA,UAAUoB,SAAUE,GACrC,MAAOQ,GACPC,QAAQD,MAAM,4BAA6BA,GAC3C,MAAME,EAAa,IAAIC,MAAM,wBACd,QAAfC,EAAA7B,KAAK8B,eAAU,IAAAD,GAAAA,EAAAL,KAAAxB,KAAA2B,OAKnB3B,KAAKC,YAAYa,iBAAiB,SAAUE,UAC3B,QAAfM,EAAAtB,KAAK8B,eAAU,IAAAR,GAAAA,EAAAE,KAAAxB,KAAAgB,GACfhB,KAAKY,MAAM,IAGNZ,KAAKC,aAzBgB,KAgCtB,YAAAmB,CAAaC,GACfrB,KAAKE,WACP6B,aAAa/B,KAAKE,WAIpB,MAAM8B,EAAkBX,EAAYY,KAAKC,MAAQ,IACjDlC,KAAKE,UAAYiC,YAAW,IAAMnC,KAAKY,QAAQoB,GAUjD,MAAAI,CAAOC,EAAmBC,EAAwBR,GAUhD,OATA9B,KAAKS,UAAY4B,EACjBrC,KAAKuB,UAAYe,EACjBtC,KAAK8B,QAAUA,EAGS,oBAAbvB,UACTA,SAASO,iBAAiB,mBAAoBd,KAAKG,oBAG9CH,KAAKU,QAMd,IAAAE,GACMZ,KAAKC,cACPD,KAAKC,YAAYsC,QACjBvC,KAAKC,YAAc,MAEjBD,KAAKE,YACP6B,aAAa/B,KAAKE,WAClBF,KAAKE,UAAY"}
1
+ {"version":3,"file":"index.umd.js","sources":["../src/types.ts","../src/index.ts"],"sourcesContent":[null,null],"names":["EventType","StatusType","Cyphlens","constructor","baseUrl","this","eventSource","timeoutId","onVisibilityChange","test","navigator","userAgent","document","visibilityState","sessionID","start","setBaseUrl","stop","EventSource","addEventListener","MFASwipe","event","data","JSON","parse","setupTimeout","expiresAt","_a","onSuccess","call","error","console","errorEvent","Event","_b","onError","clearTimeout","timeoutDuration","Date","now","setTimeout","listen","sessionId","onData","close"],"mappings":"gPAAA,IAAYA,EAKAC,EALAD,EAAAA,eAAAA,GAAAA,EAAAA,EAASA,YAATA,YAGX,CAAA,IAFC,SAAA,YACAA,EAAA,WAAA,aAGUC,EAAAA,gBAAAA,GAAAA,EAAAA,EAAUA,aAAVA,aAIX,CAAA,IAHC,QAAA,UACAA,EAAA,QAAA,UACAA,EAAA,QAAA,gBCNWC,EAYX,WAAAC,CAAYC,EAAkB,iCAVtBC,KAAWC,YAAuB,KAIlCD,KAASE,UAAyC,KAwGzCF,KAAkBG,mBAAG,KACb,iCAAiCC,KAAKC,UAAUC,YACjD,kBAAkBF,KAAKC,UAAUC,YACJ,YAA7BC,SAASC,iBAAiCR,KAAKS,WACnET,KAAKU,SArGPV,KAAKD,QAAUA,EAOjB,UAAAY,CAAWZ,GACTC,KAAKD,QAAUA,EAOT,KAAAW,GACN,OAAKV,KAAKS,WAEVT,KAAKY,OAELZ,KAAKC,YAAc,IAAIY,YAAY,GAAGb,KAAKD,sCAAsCC,KAAKS,aAGtFT,KAAKC,YAAYa,iBAAiBnB,EAASA,UAACoB,UAAWC,YACrD,IACE,MAAMC,EAAuBC,KAAKC,MAAMH,EAAMC,MAC9CjB,KAAKoB,aAAaH,EAAKI,WACN,QAAjBC,EAAAtB,KAAKuB,iBAAY,IAAAD,GAAAA,EAAAE,KAAAxB,KAAAL,EAAAA,UAAUoB,SAAUE,GACrC,MAAOQ,GACPC,QAAQD,MAAM,4BAA6BA,GAC3C,MAAME,EAAa,IAAIC,MAAM,wBACd,QAAfC,EAAA7B,KAAK8B,eAAU,IAAAD,GAAAA,EAAAL,KAAAxB,KAAA2B,OAKnB3B,KAAKC,YAAYa,iBAAiB,SAAUE,UAC3B,QAAfM,EAAAtB,KAAK8B,eAAU,IAAAR,GAAAA,EAAAE,KAAAxB,KAAAgB,GACfhB,KAAKY,MAAM,IAGNZ,KAAKC,aAzBgB,KAgCtB,YAAAmB,CAAaC,GACfrB,KAAKE,WACP6B,aAAa/B,KAAKE,WAIpB,MAAM8B,EAAkBX,EAAYY,KAAKC,MAAQ,IACjDlC,KAAKE,UAAYiC,YAAW,IAAMnC,KAAKY,QAAQoB,GAUjD,MAAAI,CAAOC,EAAmBC,EAAwBR,GAUhD,OATA9B,KAAKS,UAAY4B,EACjBrC,KAAKuB,UAAYe,EACjBtC,KAAK8B,QAAUA,EAGS,oBAAbvB,UACTA,SAASO,iBAAiB,mBAAoBd,KAAKG,oBAG9CH,KAAKU,QAMd,IAAAE,GACMZ,KAAKC,cACPD,KAAKC,YAAYsC,QACjBvC,KAAKC,YAAc,MAEjBD,KAAKE,YACP6B,aAAa/B,KAAKE,WAClBF,KAAKE,UAAY"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyphlens/2fa-sse-sdk",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "private": false,
5
5
  "description": "Cyphlens SDK for 2FA SSE",
6
6
  "main": "dist/index.js",
@@ -20,14 +20,15 @@
20
20
  "devDependencies": {
21
21
  "@rollup/plugin-commonjs": "^28.0.3",
22
22
  "@rollup/plugin-node-resolve": "^16.0.1",
23
+ "@rollup/plugin-typescript": "^12.1.4",
23
24
  "@types/jest": "^29.5.14",
24
25
  "jest": "^29.7.0",
25
26
  "jest-environment-jsdom": "^29.7.0",
26
27
  "jsdom": "^25.0.1",
27
28
  "rollup": "^4.24.0",
28
29
  "rollup-plugin-terser": "^7.0.2",
29
- "rollup-plugin-typescript2": "^0.36.0",
30
30
  "ts-jest": "^29.2.5",
31
+ "tslib": "^2.8.1",
31
32
  "tsx": "^4.19.2",
32
33
  "typescript": "^5.6.3"
33
34
  },