UNPKG

vec-idp-web-sdk

Version:

VECU Identity Verification Web SDK - A secure, easy-to-integrate identity verification solution

3 lines (2 loc) 33.1 kB
"use strict";class e extends Error{constructor(t,r,s,i){super(r),this.name="VecuError",this.code=t,this.provider=s,this.details=i,Error.captureStackTrace&&Error.captureStackTrace(this,e)}toJSON(){return{name:this.name,code:this.code,message:this.message,provider:this.provider,details:this.details,stack:this.stack}}}class t extends e{constructor(e,t,r){super("PROVIDER_ERROR",t,e,r),this.name="ProviderError"}}class r extends e{constructor(e,t){super("TIMEOUT_ERROR",e,void 0,{timeout:t}),this.name="TimeoutError"}}class s{constructor(e){this.requestInterceptors=[],this.responseInterceptors=[],this.baseUrl=e.baseUrl.replace(/\/$/,""),this.timeout=e.timeout||3e4,this.maxRetries=e.maxRetries||3,this.retryDelay=e.retryDelay||1e3}useRequestInterceptor(e){e&&this.requestInterceptors.push({request:e})}useResponseInterceptor(e,t){this.responseInterceptors.push({response:e,error:t})}setSessionToken(e){this.sessionToken=e}updateBaseUrl(e){this.baseUrl=e.replace(/\/$/,"")}async request(t,r={}){const s=`${this.baseUrl}${t}`;let i={...r,headers:{"Content-Type":"application/json",...r.headers}};this.sessionToken&&(i.headers={...i.headers,Authorization:`Bearer ${this.sessionToken}`});for(const e of this.requestInterceptors)e.request&&(i=await e.request(i));const o=new AbortController,n=setTimeout(()=>o.abort(),this.timeout);i.signal=o.signal;try{let t=await this.fetchWithRetry(s,i);clearTimeout(n);for(const e of this.responseInterceptors)e.response&&(t=await e.response(t));const r=t.headers.get("content-type"),o=r?.includes("application/json");if(!t.ok){const r=o?await t.json():{message:await t.text()};throw new e(r.code||`HTTP_${t.status}`,r.message||`Request failed with status ${t.status}`)}return{success:!0,data:o?await t.json():null}}catch(e){clearTimeout(n);let t=e;for(const e of this.responseInterceptors)e.error&&(t=await e.error(t));return t instanceof Error?"AbortError"===t.name?{success:!1,error:{code:"TIMEOUT",message:`Request timed out after ${this.timeout}ms`}}:{success:!1,error:{code:t.code||"NETWORK_ERROR",message:t.message,details:t}}:{success:!1,error:{code:"UNKNOWN_ERROR",message:"An unknown error occurred",details:t}}}}async fetchWithRetry(e,t,r=0){try{const s=await fetch(e,t);if(s.status>=400&&s.status<500)return s;if(s.ok||r>=this.maxRetries)return s;throw new Error(`HTTP ${s.status}: ${s.statusText}`)}catch(s){if("AbortError"===s.name||r>=this.maxRetries)throw s;const i=this.retryDelay*Math.pow(2,r)+1e3*Math.random();return await new Promise(e=>setTimeout(e,i)),this.fetchWithRetry(e,t,r+1)}}get(e,t){return this.request(e,{...t,method:"GET"})}post(e,t,r){return this.request(e,{...r,method:"POST",body:t?JSON.stringify(t):void 0})}put(e,t,r){return this.request(e,{...r,method:"PUT",body:t?JSON.stringify(t):void 0})}delete(e,t){return this.request(e,{...t,method:"DELETE"})}}class i{constructor(){this.events=new Map}on(e,t){this.events.has(e)||this.events.set(e,new Set),this.events.get(e).add(t)}off(e,t){const r=this.events.get(e);r&&(r.delete(t),0===r.size&&this.events.delete(e))}emit(e,t){const r=this.events.get(e);if(r){const s={type:e,timestamp:new Date,data:t};r.forEach(e=>{try{e(s)}catch(e){}})}"*"!==e&&this.emit("*",{type:e,data:t})}once(e,t){const r=s=>{this.off(e,r),t(s)};this.on(e,r)}removeAllListeners(e){e?this.events.delete(e):this.events.clear()}listenerCount(e){const t=this.events.get(e);return t?t.size:0}eventNames(){return Array.from(this.events.keys())}}class o{constructor(){this.providers=new Map}register(e){if(!e.name)throw new Error("Provider must have a name");this.providers.has(e.name)&&this.unregister(e.name),this.providers.set(e.name,e)}unregister(e){const t=this.providers.get(e);t&&(t.destroy(),this.providers.delete(e))}get(e){return this.providers.get(e)}getAll(){return Array.from(this.providers.values())}has(e){return this.providers.has(e)}clear(){this.providers.forEach(e=>{e.destroy()}),this.providers.clear()}getByFeature(e){return this.getAll().filter(t=>t.supportedFeatures.includes(e))}getLoadedProviders(){return this.getAll().filter(e=>e.isLoaded)}}class n{constructor(e,t){this.registry=e,this.loadingPromises=new Map,this.eventForwardingSetup=t}async load(e){const t=this.loadingPromises.get(e);if(t)return t;const r=this.registry.get(e);if(r&&r.isLoaded){if("socure"!==e)return r;{const t=r;if(t.socureDocVSDK&&t.sdkLoader.isLoaded())return r;this.registry.unregister(e)}}const s=this.loadProvider(e);this.loadingPromises.set(e,s);try{const t=await s;return this.loadingPromises.delete(e),t}catch(t){throw this.loadingPromises.delete(e),t}}async loadProvider(e){const t=await this.importProvider(e),r=t.default||t[`${this.capitalize(e)}Provider`];if(!r)throw new Error(`Provider class not found for ${e}`);const s=new r;return await s.loadSDK(),this.eventForwardingSetup.setupProviderEventForwarding(s,`auto-${e}-${Date.now()}`),this.registry.has(e)||this.registry.register(s),s}async importProvider(e){switch(e){case"socure":return Promise.resolve().then(function(){return U});case"incode":case"jumio":case"onfido":case"veriff":throw new Error(`Provider ${e} is not yet implemented`);default:throw new Error(`Unknown provider: ${e}`)}}isLoaded(e){const t=this.registry.get(e);return!!t&&t.isLoaded}getLoadedProviders(){return this.registry.getLoadedProviders().map(e=>e.name)}capitalize(e){return e.charAt(0).toUpperCase()+e.slice(1)}}class a{constructor(e){this.listeners=new Map,this.eventEmitter=e}setupProviderEventForwarding(e,t){const r=new Map;["verification:completed","verification:failed","verification:progress","ui:ready","ui:closed"].forEach(t=>{const s=e=>{this.eventEmitter.emit(t,e)};r.set(t,s),e.on(t,s)});const s=e=>{this.eventEmitter.emit("provider:event",e)};r.set("*",s),e.on("*",s),this.listeners.set(t,r)}cleanupProviderEventForwarding(e,t){const r=this.listeners.get(t);r&&(r.forEach((t,r)=>{try{e.off(r,t)}catch(e){}}),this.listeners.delete(t))}cleanupAll(){this.listeners.clear()}getActiveProviderCount(){return this.listeners.size}getActiveProviderIds(){return Array.from(this.listeners.keys())}}class c{constructor(e="info",t=!0,r="[VecuIDV]"){this.logLevels={error:0,warn:1,info:2,debug:3},this.level=e,this.enabled=t,this.prefix=r}error(e,...t){this.log("error",e,...t)}warn(e,...t){this.log("warn",e,...t)}info(e,...t){this.log("info",e,...t)}debug(e,...t){this.log("debug",e,...t)}log(e,t,...r){if(!this.enabled||!this.shouldLog(e))return;const s=(new Date).toISOString();this.prefix,e.toUpperCase()}shouldLog(e){return this.logLevels[e]<=this.logLevels[this.level]}setLevel(e){this.level=e}setEnabled(e){this.enabled=e}createChildLogger(e){return new c(this.level,this.enabled,`${this.prefix} ${e}`)}}function d(e){const t=e.replace(/\D/g,"");return t?e.startsWith("+")?`+${t}`:10===t.length?`+1${t}`:t.length<10?t.length<=4?`+${t}`:t:`+${t}`:""}function l(e){const t=e;return{firstName:t.firstName,lastName:t.lastName,...t.middleName&&{middleName:t.middleName},...t.email&&{email:t.email},...t.phone&&{phone:d(t.phone)},address:{line_1:t.address.line1,...t.address.line2&&{line_2:t.address.line2},locality:t.address.locality,...t.address.minorAdminDivision&&{minor_admin_division:t.address.minorAdminDivision},major_admin_division:t.address.majorAdminDivision,country:t.address.country,postal_code:t.address.postalCode,type:t.address.type}}}const u={sandbox:"https://int.dev.api.coxautoinc.com/vehicle-services/wholesale/vec-identity-verification-provider-api-v1.0.2",production:"https://c0j9hytfof.execute-api.us-east-1.amazonaws.com/prod",preprod:"https://c0j9hytfof.execute-api.us-east-1.amazonaws.com/pre-prod"},h={socure:{sandbox:{key:"cnI4cTVxbnIxMzk3LXA5Mm8tc25vOS1vMHMxLTVwMzE0ODhx",url:u.sandbox},production:{key:"placeholder-obfuscated-socure-production-key",url:u.production},preprod:{key:"placeholder-obfuscated-socure-preprod-key",url:u.preprod}}};class m{static validateProvider(e,t){if(!t)throw new Error(`No configuration found for provider: ${e}`)}static validateStageConfig(e,t,r){if(!r)throw new Error(`No configuration found for provider: ${e} in deployment stage: ${t}`)}static validateKey(e,t,r){if(!r)throw new Error(`No SDK key configured for provider: ${e} in deployment stage: ${t}`)}static validateUrl(e,t,r){if(!r)throw new Error(`No URL configured for provider: ${e} in deployment stage: ${t}`)}}class p{constructor(){}static getInstance(){return p.instance||(p.instance=new p),p.instance}getProviderConfig(e){return h[e.toLowerCase()]}getStageConfig(e,t){const r=this.getProviderConfig(e);return r?.[t]}getAllConfiguredProviders(){return Object.keys(h)}getProviderStages(e){const t=this.getProviderConfig(e);return t?Object.keys(t):[]}}class v{constructor(e=p.getInstance()){this.configManager=e}resolveKey(e,t="sandbox"){const r=this.configManager.getProviderConfig(e);m.validateProvider(e,r);const s=this.configManager.getStageConfig(e,t);return m.validateStageConfig(e,t,s),m.validateKey(e,t,s.key),s.key}hasKey(e,t="sandbox"){try{return this.resolveKey(e,t),!0}catch{return!1}}}class f{static resolveApiUrl(e="sandbox"){const t=u[e];if(!t)throw new Error(`No API URL configured for deployment stage: ${e}`);return t}}const I=new v;function g(e="sandbox"){return f.resolveApiUrl(e)}function D(e,t,r,i){const c=new s({baseUrl:e.apiUrl,timeout:e.timeout,maxRetries:e.maxRetries});e.bearerToken&&c.setSessionToken(e.bearerToken),c.useRequestInterceptor(e=>({...e,headers:{...e.headers,"SDK-Key":t}}));const d=new o,l=new a(r);return{apiClient:c,eventEmitter:r,providerRegistry:d,providerLoader:new n(d,{setupProviderEventForwarding:(e,t=`auto-${e.name}-${Date.now()}`)=>{l.setupProviderEventForwarding(e,t)}}),eventForwarder:l,logger:i,keyResolver:new v,apiUrlResolver:f}}new class{constructor(e=p.getInstance()){this.configManager=e}resolveUrl(e,t="sandbox"){const r=this.configManager.getProviderConfig(e);m.validateProvider(e,r);const s=this.configManager.getStageConfig(e,t);return m.validateStageConfig(e,t,s),m.validateUrl(e,t,s.url),s.url}};class E{constructor(){this._isLoaded=!1,this.sdkInstance=null,this.activeUI=null,this.eventEmitter=new i,this.logger=new c("info",!0)}get isLoaded(){return this._isLoaded}mapEvent(e){if(!e||"object"!=typeof e)return null;const t=e;return{type:"string"==typeof t.type?t.type:"unknown",data:t.data||t,timestamp:new Date}}destroy(){this.activeUI&&(this.activeUI.destroy(),this.activeUI=null),this.sdkInstance&&(this.cleanupSDK(),this.sdkInstance=null),this.eventEmitter&&this.eventEmitter.removeAllListeners(),this._isLoaded=!1,this.logger.info(`${this.name} provider destroyed`)}async loadScript(t,r){return new Promise((s,i)=>{if(r&&window[r])return this.logger.info(`${this.name} SDK already loaded`),void s();const o=document.createElement("script");o.src=t,o.async=!0,o.crossOrigin="anonymous",o.onload=()=>{this.logger.info(`${this.name} SDK loaded successfully`),s()},o.onerror=r=>{this.logger.error(`Failed to load ${this.name} SDK`,r),i(new e("PROVIDER_SDK_LOAD_FAILED",`Failed to load ${this.name} SDK from ${t}`))},document.head.appendChild(o)})}createUIContainer(e,t){const r=document.createElement("div");r.className=`vecu-idv-${this.name}-container vecu-idv-${t}`,r.setAttribute("data-provider",this.name),r.style.cssText=`\n position: ${"modal"===t?"fixed":"relative"};\n width: 100%;\n height: 100%;\n ${"modal"===t?"top: 0; left: 0; z-index: 9999;":""}\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: ${"modal"===t?"rgba(0, 0, 0, 0.5)":"transparent"};\n `;const s=this.createLoadingSpinner();return r.appendChild(s),e.appendChild(r),r}createLoadingSpinner(){const e=document.createElement("div");return e.className="vecu-idv-loading-spinner",e.setAttribute("role","status"),e.setAttribute("aria-label","Loading verification"),e.innerHTML='\n <style>\n .vecu-idv-loading-spinner {\n text-align: center;\n padding: 20px;\n }\n .vecu-idv-spinner {\n display: inline-block;\n width: 40px;\n height: 40px;\n border: 3px solid rgba(0, 0, 0, 0.1);\n border-radius: 50%;\n border-top-color: #3498db;\n animation: vecu-idv-spin 1s ease-in-out infinite;\n }\n .vecu-idv-loading-text {\n margin-top: 12px;\n color: #666;\n font-family: -apple-system, BlinkMacSystemFont, \'Segoe UI\', Roboto, sans-serif;\n font-size: 14px;\n }\n @keyframes vecu-idv-spin {\n to { transform: rotate(360deg); }\n }\n </style>\n <div class="vecu-idv-spinner"></div>\n <div class="vecu-idv-loading-text">Initializing verification...</div>\n ',e}removeLoadingSpinner(e){const t=e.querySelector(".vecu-idv-loading-spinner");t&&t.remove(),e.style.display="block",e.style.alignItems="",e.style.justifyContent=""}removeUIContainer(e){e&&e.parentNode&&e.parentNode.removeChild(e)}emitProviderEvent(e,t){const r={type:e,data:t,timestamp:new Date};this.eventEmitter.emit(e,r),this.eventEmitter.emit("provider:event",r)}handleProviderError(t,r){const s=t instanceof e?t:new e("PROVIDER_ERROR",`${this.name} provider error in ${r}: ${t instanceof Error?t.message:String(t)}`,this.name);throw this.logger.error(`${this.name} provider error`,s),this.emitProviderEvent("provider:error",{code:s.code,message:s.message,provider:this.name,context:r}),s}on(e,t){this.eventEmitter.on(e,t)}off(e,t){this.eventEmitter.off(e,t)}validateInitOptions(t){if(!t.sessionId)throw new e("INVALID_OPTIONS","Session ID is required");if(!t.token)throw new e("INVALID_OPTIONS","Token is required");if(!(t.container&&t.container instanceof HTMLElement))throw new e("INVALID_OPTIONS","Valid HTML container element is required");if(!["modal","embedded"].includes(t.mode))throw new e("INVALID_OPTIONS",'Mode must be either "modal" or "embedded"')}}const S={socure:{scriptUrl:"https://websdk.socure.com/bundle.js",supportedFeatures:["document_verification","liveness_check","face_match","address_verification","database_check","qr_code_handoff"]}},y="ready",_="start",w="complete",R="error",O="close",A="document:front:capture",T="document:back:capture",N="document:processing",L="liveness:start",P="liveness:processing",C="liveness:complete";function k(e,t){return new Promise((r,s)=>{const i=function(e,t){const r=document.createElement(e);return t&&Object.entries(t).forEach(([e,t])=>{"className"===e?r.className=t:"style"===e?r.setAttribute("style",t):e.startsWith("data-")?r.setAttribute(e,t):r[e]=t}),r}("script",{src:e,async:"true",...t});i.onload=()=>r(),i.onerror=()=>s(new Error(`Failed to load script: ${e}`)),document.head.appendChild(i)})}class b{constructor(){this.loadPromise=null,this.sdkInstance=null,this.isDestroyed=!1}static getInstance(){return b.instance||(b.instance=new b),b.instance}async load(){if((this.isDestroyed||!this.sdkInstance&&window.SocureDocVSDK)&&(this.isDestroyed=!1,this.sdkInstance=null,this.loadPromise=null,delete window.SocureDocVSDK),this.sdkInstance)return this.sdkInstance;if(this.loadPromise)return this.loadPromise;this.loadPromise=this.loadSDK();try{return this.sdkInstance=await this.loadPromise,this.sdkInstance}catch(e){throw this.loadPromise=null,e}}preload(){this.sdkInstance||this.loadPromise||this.load().catch(e=>{})}async loadSDK(){const e=S.socure,t="SocureDocVSDK";if(window[t])return window[t];const s=3e4,i=new Promise((e,t)=>{setTimeout(()=>{t(new r("Socure SDK load timeout after 30000ms",s))},s)}),o=k(this.isDestroyed?`${e.scriptUrl}?t=${Date.now()}`:e.scriptUrl,{"data-provider":"socure",crossorigin:"anonymous"}).then(()=>new Promise((e,r)=>{setTimeout(()=>{const s=window[t];s?e(s):r(new Error(`Socure DocV SDK not found at window.${t}`))},100)}));return Promise.race([o,i])}isLoaded(){return null!==this.sdkInstance}getSDK(){return this.sdkInstance}destroy(){this.isDestroyed=!0,window.SocureDocVSDK&&delete window.SocureDocVSDK;document.querySelectorAll('script[src*="websdk.socure.com"]').forEach(e=>{e.remove()}),this.sdkInstance=null,this.loadPromise=null,b.instance=null}}b.instance=null;class V{static mapEvent(e){if(!e||"object"!=typeof e)return null;const t=e.type;return{type:this.eventMap[t]||t,data:this.mapEventData(t,e.data),timestamp:new Date(e.timestamp||Date.now())}}static mapEventData(e,t){switch(e){case"complete":return this.mapCompleteData(t);case"error":return this.mapErrorData(t);case"document_front_capture":case"document_back_capture":return this.mapDocumentCaptureData(t);case"liveness_complete":return this.mapLivenessData(t);case"qr_code_displayed":return this.mapQRCodeData(t);default:return t}}static mapCompleteData(e){if(!e||"object"!=typeof e)return{};const t=e;return{sessionId:t.referenceId||"",status:"completed",documentData:t.documentData?{type:t.documentData?.type,number:t.documentData?.documentNumber,issuingCountry:t.documentData?.issuingCountry,expirationDate:t.documentData?.expirationDate,firstName:t.documentData?.firstName,lastName:t.documentData?.lastName,dateOfBirth:t.documentData?.dateOfBirth,address:t.documentData?.address}:void 0,livenessData:t.livenessData?{passed:t.livenessData?.passed,score:t.livenessData?.score,confidence:t.livenessData?.confidence}:void 0,fraudSignals:t.fraud?{overallRisk:this.mapRiskLevel(t.fraud?.score),signals:(t.fraud?.signals||[]).map(e=>({type:e.name,risk:e.risk,description:e.description}))}:void 0}}static mapErrorData(e){if(!e||"object"!=typeof e)return{code:"UNKNOWN_ERROR",message:"Unknown error occurred"};const t=e;return{code:t.code||"SOCURE_ERROR",message:t.message||"Socure verification error",details:t.details,provider:"socure"}}static mapDocumentCaptureData(e){return{side:e?.side||"unknown",quality:e?.quality||"unknown",timestamp:(new Date).toISOString()}}static mapLivenessData(e){return{passed:e?.passed||!1,score:e?.score||0,confidence:e?.confidence||"low",timestamp:(new Date).toISOString()}}static mapQRCodeData(e){return{qrCodeUrl:e?.url,sessionUrl:e?.sessionUrl,expiresAt:e?.expiresAt}}static mapRiskLevel(e){return e<30?"low":e<70?"medium":"high"}static mapWebhookData(e){if(!e||"object"!=typeof e)return null;const t=e,r=t.documentVerification?.decision||t.selfieVerification?.decision||"review";return{sessionId:t.referenceId,provider:"socure",status:"complete"===t.status?"completed":"failed",decision:this.mapDecision(r),documentData:t.documentVerification?{type:t.documentVerification?.documentType,...t.documentVerification?.documentFields}:void 0,livenessData:t.selfieVerification?{passed:"accept"===t.selfieVerification?.decision,score:t.selfieVerification?.livenessScore,confidence:this.mapConfidence(t.selfieVerification?.livenessScore)}:void 0,fraudSignals:t.fraud?{overallRisk:this.mapRiskLevel(t.fraud?.score),signals:(t.fraud?.signals||[]).map(e=>({type:e,risk:"medium",description:e}))}:void 0,completedAt:t.updatedAt?new Date(t.updatedAt):new Date}}static mapDecision(e){switch(e){case"accept":return"approved";case"reject":return"declined";default:return"review"}}static mapConfidence(e){return e>=80?"high":e>=50?"medium":"low"}}V.eventMap={init:y,ready:y,start:_,document_front_capture:A,document_back_capture:T,document_processing:N,liveness_start:L,liveness_processing:P,liveness_complete:C,complete:w,error:R,close:O,qr_code_displayed:"qr_code:displayed",mobile_handoff:"mobile:handoff"};var U=Object.freeze({__proto__:null,SocureProvider:class extends E{getCompletionMessage(e){return e.mobileNumber?"Verification complete! Check your SMS for further instructions.":e.customerUserId?"Verification complete! Please check your email for further instructions.":"Verification completed successfully! You may now proceed."}constructor(){super(),this.name="socure",this.version="1.0.0",this.supportedFeatures=[...S.socure.supportedFeatures],this.socureDocVSDK=null,this.activeSession=null,this.sdkLoader=b.getInstance()}async loadSDK(){try{this.logger.info("Loading Socure DocV SDK..."),this.sdkLoader||(this.sdkLoader=b.getInstance()),this.socureDocVSDK=await this.sdkLoader.load(),this._isLoaded=!0,this.logger.info("Socure DocV SDK loaded successfully"),this.emitProviderEvent("provider:loaded",{provider:this.name})}catch(e){this._isLoaded=!1,this.handleProviderError(e,"loadSDK")}}async initializeVerification(e){try{if(this.validateInitOptions(e),window.SocureDocVSDK||document.querySelector('iframe[src*="socure"]')){if(this.logger.info("Detected existing Socure state, cleaning up before initialization..."),e.container instanceof HTMLElement)for(;e.container.firstChild;)e.container.removeChild(e.container.firstChild);this.clearSocureDOM(),this.clearSocureGlobals(),this._isLoaded=!1,this.socureDocVSDK=null,this.sdkLoader&&(this.sdkLoader.destroy(),this.sdkLoader=b.getInstance()),await new Promise(e=>setTimeout(e,100)),await this.loadSDK()}if(!this.socureDocVSDK)throw new t(this.name,"Socure DocV SDK not loaded");this.logger.info("Initializing Socure verification",{sessionId:e.sessionId,hasSDK:!!this.socureDocVSDK,sdkType:typeof this.socureDocVSDK,methods:this.socureDocVSDK?Object.keys(this.socureDocVSDK):[]});let r=e.config?.publicKey||e.config?.sdkKey;if(!r||"string"!=typeof r)throw new t(this.name,"Socure SDK key is required in provider config");if(/^[A-Za-z0-9+/]+=*$/.test(r)&&r.length>50)try{r=function(e){try{let t;t="undefined"!=typeof atob?atob(e):Buffer.from(e,"base64").toString();return t.split("").reverse().join("").replace(/[a-zA-Z0-9]/g,e=>{const t=e.charCodeAt(0);return t>=65&&t<=90?String.fromCharCode((t-65-13+26)%26+65):t>=97&&t<=122?String.fromCharCode((t-97-13+26)%26+97):t>=48&&t<=57?String.fromCharCode((t-48-5+10)%10+48):e})}catch{throw new Error("Invalid obfuscated key")}}(r),this.logger.info("Socure SDK key deobfuscated successfully")}catch{this.logger.warn("Failed to deobfuscate Socure SDK key, using as plain key")}const s=e.token;if(!s)throw new t(this.name,"docvTransactionToken is required");const i=this.createUIContainer(e.container,e.mode);this.emitProviderEvent("verification:progress",{sessionId:e.sessionId,step:"initializing_ui",percentage:20,message:"Preparing verification interface..."});const o={onProgress:t=>{this.logger.info("Socure progress event",t),this.handleProgressEvent(t,e.sessionId)},onSuccess:t=>{if(this.logger.info("Socure verification completed",t),"status"in t&&"DOCUMENTS_UPLOADED"===t.status)this.handleProgressEvent(t,e.sessionId);else if(!("status"in t)||"DOCUMENTS_UPLOADED"!==t.status){const r=V.mapEvent({type:"complete",data:t,timestamp:Date.now()});r&&this.emitProviderEvent(r.type,r.data);const s={sessionId:e.sessionId,message:"Verification completed successfully! You may now proceed.",result:t};this.emitProviderEvent("verification:completed",s)}},onError:t=>{if(this.logger.error("Socure verification error",t),!("status"in t)||"CONSENT_DECLINED"!==t.status&&"DOCUMENTS_UPLOAD_FAILED"!==t.status){const r=V.mapEvent({type:"error",data:t,timestamp:Date.now()});r&&this.emitProviderEvent(r.type,r.data),"code"in t&&"USER_CANCELLED"===t.code&&this.emitProviderEvent("ui:closed",{sessionId:e.sessionId})}else{const r="CONSENT_DECLINED"===t.status?"USER_CANCELLED":"UPLOAD_FAILED";this.emitProviderEvent("verification:failed",{sessionId:e.sessionId,error:{code:r,message:t.status.replace(/_/g," ").toLowerCase(),docvTransactionToken:t.docvTransactionToken}}),"CONSENT_DECLINED"===t.status&&this.emitProviderEvent("ui:closed",{sessionId:e.sessionId})}},qrCodeNeeded:Boolean(e.config?.qrCode)||!1},n=`socure-container-${Date.now()}`;i.id=n;const a=`#${n}`;let c;try{this.emitProviderEvent("verification:progress",{sessionId:e.sessionId,step:"loading_provider",percentage:40,message:"Loading identity verification..."}),c=this.socureDocVSDK.launch(r,s,a,o),this.removeLoadingSpinner(i)}catch(e){throw this.removeLoadingSpinner(i),e}this.activeSession=c&&"object"==typeof c?c:{id:e.sessionId,status:"active",destroy:()=>{this.logger.info("Destroying Socure session")}};const d={container:i,sessionId:e.sessionId,provider:this.name,destroy:()=>{this.destroySession(),this.removeUIContainer(i)}};return this.activeUI=d,this.emitProviderEvent("ui:created",{sessionId:e.sessionId}),setTimeout(()=>{this.emitProviderEvent("ui:ready",{sessionId:e.sessionId}),this.emitProviderEvent("verification:progress",{sessionId:e.sessionId,step:"ready",percentage:60,message:"Verification interface ready"})},100),d}catch(e){this.handleProviderError(e,"initializeVerification")}}processWebhookData(e){try{const r=V.mapWebhookData(e);if(!r)throw new t(this.name,"No mapped data returned from webhook");return{status:r.status||"unknown",decision:r.decision,data:{documentData:r.documentData||void 0,livenessData:r.livenessData||void 0,fraudSignals:r.fraudSignals||void 0},metadata:{provider:this.name,processedAt:(new Date).toISOString()}}}catch(e){throw this.logger.error("Failed to process webhook data",e),new t(this.name,"Failed to process webhook data")}}mapEvent(e){return V.mapEvent(e)}cleanupSDK(){this.destroySession(),this.clearSocureDOM(),this.clearSocureGlobals(),this.sdkLoader.destroy(),this.socureDocVSDK=null}clearSocureDOM(){['iframe[src*="socure"], iframe[id*="socure"]','[id*="socure-container"], .socure-sdk-container','script[src*="websdk.socure.com"]'].forEach(e=>{document.querySelectorAll(e).forEach(e=>{this.logger.info(`Removing Socure element: ${e.tagName}`),e.remove()})})}clearSocureGlobals(){["SocureDocVSDK","Socure","socure","SOCURE"].forEach(e=>{window[e]&&(this.logger.info(`Clearing global ${e}`),delete window[e])})}handleProgressEvent(e,t){if(e.status){const r={WAITING_FOR_USER_TO_REDIRECT:"qr_code_displayed",WAITING_FOR_UPLOAD:"verification:started",DOCUMENTS_UPLOADED:"verification:completed"}[e.status]||"verification:progress";if("DOCUMENTS_UPLOADED"===e.status){const r={sessionId:t,message:this.getCompletionMessage(e),result:{status:"completed",docvTransactionToken:e.docvTransactionToken,deviceSessionToken:e.deviceSessionToken,customerUserId:e.customerUserId}};this.emitProviderEvent("verification:completed",r)}else this.emitProviderEvent(r,{sessionId:t,status:e.status,docvTransactionToken:e.docvTransactionToken,customerUserId:e.customerUserId,mobileNumber:e.mobileNumber}),this.emitProviderEvent("verification:progress",{sessionId:t,step:e.status,percentage:"WAITING_FOR_USER_TO_REDIRECT"===e.status?10:30,message:e.status.replace(/_/g," ").toLowerCase()})}else this.logger.warn("Received unexpected progress event structure from Socure",e)}destroySession(){if(this.activeSession){try{this.activeSession.destroy()}catch(e){this.logger.error("Error destroying Socure session",e)}this.activeSession=null}}}});exports.APIClient=s,exports.EVENTS={SDK_INIT:"sdk:init",SDK_READY:"sdk:ready",SDK_ERROR:"sdk:error",SDK_DESTROY:"sdk:destroy",PROVIDER_LOADED:"provider:loaded",PROVIDER_READY:"provider:ready",PROVIDER_ERROR:"provider:error",PROVIDER_EVENT:"provider:event",VERIFICATION_CREATED:"verification:created",VERIFICATION_STARTED:"verification:started",VERIFICATION_PROGRESS:"verification:progress",VERIFICATION_COMPLETED:"verification:completed",VERIFICATION_FAILED:"verification:failed",VERIFICATION_CANCELLED:"verification:cancelled",VERIFICATION_EXPIRED:"verification:expired",UI_CREATED:"ui:created",UI_READY:"ui:ready",UI_ERROR:"ui:error",UI_CLOSED:"ui:closed",UI_DESTROYED:"ui:destroyed"},exports.ErrorCodes={INVALID_API_KEY:"INVALID_API_KEY",MISSING_CONFIG:"MISSING_CONFIG",INVALID_CONFIG:"INVALID_CONFIG",SDK_NOT_INITIALIZED:"SDK_NOT_INITIALIZED",SDK_INIT_FAILED:"SDK_INIT_FAILED",SDK_ALREADY_INITIALIZED:"SDK_ALREADY_INITIALIZED",PROVIDER_NOT_FOUND:"PROVIDER_NOT_FOUND",PROVIDER_LOAD_FAILED:"PROVIDER_LOAD_FAILED",PROVIDER_SDK_LOAD_FAILED:"PROVIDER_SDK_LOAD_FAILED",PROVIDER_INIT_FAILED:"PROVIDER_INIT_FAILED",PROVIDER_NOT_SUPPORTED:"PROVIDER_NOT_SUPPORTED",SESSION_NOT_FOUND:"SESSION_NOT_FOUND",SESSION_EXPIRED:"SESSION_EXPIRED",SESSION_CREATE_FAILED:"SESSION_CREATE_FAILED",SESSION_ALREADY_EXISTS:"SESSION_ALREADY_EXISTS",VERIFICATION_FAILED:"VERIFICATION_FAILED",VERIFICATION_CANCELLED:"VERIFICATION_CANCELLED",VERIFICATION_TIMEOUT:"VERIFICATION_TIMEOUT",INVALID_CONTAINER:"INVALID_CONTAINER",UI_INIT_FAILED:"UI_INIT_FAILED",UI_DESTROYED:"UI_DESTROYED",NETWORK_ERROR:"NETWORK_ERROR",TIMEOUT_ERROR:"TIMEOUT_ERROR",API_ERROR:"API_ERROR",INVALID_OPTIONS:"INVALID_OPTIONS",INVALID_USER_DATA:"INVALID_USER_DATA",MISSING_REQUIRED_FIELD:"MISSING_REQUIRED_FIELD"},exports.EventEmitter=i,exports.Logger=c,exports.PROVIDER_FEATURES={DOCUMENT_VERIFICATION:"document_verification",LIVENESS_CHECK:"liveness_check",FACE_MATCH:"face_match",ADDRESS_VERIFICATION:"address_verification",DATABASE_CHECK:"database_check",PHONE_VERIFICATION:"phone_verification",EMAIL_VERIFICATION:"email_verification",QR_CODE_HANDOFF:"qr_code_handoff",VIDEO_VERIFICATION:"video_verification"},exports.ProviderError=t,exports.SDK_NAME="@vecu-idv-web-sdk",exports.SDK_VERSION="1.0.0",exports.SUPPORTED_PROVIDERS=["socure","incode","jumio","onfido","veriff"],exports.TimeoutError=r,exports.VecuError=e,exports.createVecuIDVSDK=function(t,r,s){if(!t||"string"!=typeof t||t.length<10)throw new e("INVALID_SDK_KEY","Invalid SDK key provided");const o=t;let n=!1;const a=r?.deploymentStage||"sandbox",d={apiUrl:g(a),timeout:3e4,maxRetries:3,logLevel:"info",debug:!1,enableDirectAPI:!1,deploymentStage:a,apiEndpoints:{startVerification:"/identity/verify/start"},...r},u=s?.eventEmitter||new i,h=s?.logger||new c(d.logLevel,d.debug),m=s?{...D(d,o,u,h),...s}:D(d,o,u,h),{apiClient:p,providerRegistry:v,providerLoader:f,eventForwarder:E,apiUrlResolver:S}=m;function y(){if(n)h.warn("SDK already initialized");else try{u.emit("sdk:init"),n=!0,u.emit("sdk:ready"),h.info("SDK initialized successfully")}catch(e){throw h.error("Failed to initialize SDK",e),u.emit("sdk:error",{code:"SDK_INIT_FAILED",message:e instanceof Error?e.message:"Unknown error",details:e}),e}}async function _(t,r,s={}){n||y();try{h.info("Launching verification",{token:t});const i="string"==typeof r?document.querySelector(r):r;if(!i)throw new e("INVALID_CONTAINER","Container element not found");const o=s.provider||"socure",n=await f.load(o),a=`verification-${o}-${Date.now()}`;let c;s.onSuccess&&u.once("verification:completed",()=>{const e={sessionId:t,provider:o,status:"completed",completedAt:new Date};s.onSuccess(e)}),s.onError&&u.on("verification:failed",e=>{const t=new Error(e.data&&"object"==typeof e.data&&"error"in e.data?e.data.error:"Verification failed");s.onError(t)}),s.onProgress&&u.on("verification:progress",e=>{e.data&&"object"==typeof e.data&&s.onProgress(e.data)});const d=s.deploymentStage||"sandbox";try{c=function(e,t="sandbox"){return I.resolveKey(e,t)}(o,d),h.info(`Using configured SDK key for provider: ${o} in deployment stage: ${d}`)}catch(t){throw h.error(`Failed to get SDK key for provider ${o} in deployment stage: ${d}:`,t),new e("PROVIDER_KEY_NOT_FOUND",`No SDK key configured for provider: ${o} in deployment stage: ${d}`)}const l={...s.config,sdkKey:c},m=await n.initializeVerification({sessionId:t,token:t,container:i,mode:s.mode||"embedded",theme:s.theme,language:s.language,config:l});return E.setupProviderEventForwarding(n,a),u.emit("verification:started",{provider:o,token:t,ui:m}),()=>{h.info("Cleaning up verification"),m&&"function"==typeof m.destroy&&m.destroy(),E.cleanupProviderEventForwarding(n,a),u.removeAllListeners("verification:completed"),u.removeAllListeners("verification:failed"),u.removeAllListeners("verification:progress")}}catch(e){throw h.error("Failed to launch verification",e),u.emit("verification:failed",{error:e instanceof Error?e.message:"Unknown error"}),e}}return{launch:_,startVerificationWithCustomer:async function(t,r){if(!d.enableDirectAPI)throw new e("DIRECT_API_DISABLED","Direct API calls are not enabled. Use launch() with a transaction token instead.");n||y();try{h.info("Starting verification with customer info");const s={referenceId:r.referenceId||`customer_${Date.now()}`,config:{webhookUrl:"https://vecu-idv.emulator_idvp.com",...r.config},customerInfo:l(r.customerInfo)},i=d.apiEndpoints?.startVerification??"/identity/verify/start",o=await p.post(i,s);if(!o.success||!o.data)throw new e("VERIFICATION_START_FAILED",o.error&&"object"==typeof o.error&&"message"in o.error?o.error.message:"Failed to start verification");const n=o.data.provider_document_id||o.data.providerDocumentId;if(!n)throw new e("NO_PROVIDER_DOCUMENT_ID","No provider document ID received from API");const a=o.data.provider||"socure";return h.info(`API returned provider: ${a}`),_(n,t,{...r,provider:a,deploymentStage:r.deploymentStage})}catch(e){throw h.error("Failed to start verification with customer info",e),e}},updateConfig:function(e){if(e.deploymentStage&&e.deploymentStage!==d.deploymentStage){const t=S.resolveApiUrl(e.deploymentStage);e.apiUrl=t,p.updateBaseUrl(t),h.info(`Updated API URL for deployment stage: ${e.deploymentStage} -> ${t}`)}void 0!==e.bearerToken&&e.bearerToken&&(p.setSessionToken(e.bearerToken),h.info("Bearer token updated on APIClient")),Object.assign(d,e),h.info("SDK configuration updated",e)},on:(e,t)=>u.on(e,t),off:(e,t)=>u.off(e,t),once:(e,t)=>u.once(e,t),destroy:()=>{E.cleanupAll(),u.removeAllListeners(),v.clear(),h.info("SDK destroyed")}}}; //# sourceMappingURL=index.js.map