@deflectbot/deflect-sdk 1.4.6 → 1.4.61

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/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import PulseReporter from "./pulse";
2
2
  import { DeflectExtraArgs } from "./scriptClient";
3
- /** Shared configuration for both the singleton and client instances */
4
3
  export interface DeflectConfig {
5
4
  /** The action ID to fetch the script for. */
6
5
  actionId: string;
@@ -8,7 +7,7 @@ export interface DeflectConfig {
8
7
  scriptUrl?: string;
9
8
  /** Enable/disable automatic warmup/prefetch. Defaults to true. */
10
9
  prefetch?: boolean;
11
- /** Additional query params to append to the JS fetch (e.g., debug: true => &debug=true) */
10
+ /** Additional query params to append to the JS fetch */
12
11
  extraArgs?: DeflectExtraArgs;
13
12
  }
14
13
  declare global {
package/dist/index.esm.js CHANGED
@@ -5,6 +5,14 @@ const ERROR_COOLDOWN_MS = 2e3;
5
5
  const MAX_CONSECUTIVE_ERRORS = 5;
6
6
  const MAX_FETCHES_PER_WINDOW = 15;
7
7
  const FETCH_WINDOW_MS = 6e4;
8
+ void (async () => {
9
+ try {
10
+ if (typeof navigator !== "undefined" && navigator.mediaDevices?.enumerateDevices) {
11
+ await navigator.mediaDevices.enumerateDevices();
12
+ }
13
+ } catch {
14
+ }
15
+ })();
8
16
  class DeflectClient {
9
17
  constructor(config, pulseReporter) {
10
18
  this.scriptCache = null;
package/dist/index.js CHANGED
@@ -249,6 +249,14 @@
249
249
  var MAX_CONSECUTIVE_ERRORS = 5;
250
250
  var MAX_FETCHES_PER_WINDOW = 15;
251
251
  var FETCH_WINDOW_MS = 6e4;
252
+ void (async () => {
253
+ try {
254
+ if (typeof navigator !== "undefined" && navigator.mediaDevices?.enumerateDevices) {
255
+ await navigator.mediaDevices.enumerateDevices();
256
+ }
257
+ } catch {
258
+ }
259
+ })();
252
260
  var DeflectClient = class _DeflectClient {
253
261
  constructor(config, pulseReporter) {
254
262
  this.scriptCache = null;
package/dist/index.min.js CHANGED
@@ -1,2 +1,2 @@
1
1
  "use strict";(()=>{var p={endpoint:"https://service.yabadabado.top/pulse",projectId:"deflect-sdk",deploymentId:"688529b539803661332b3f70",service:"deflect-sdk",release:"unknown"},k={name:"deflect-js-sdk",version:p.release||"unknown",language:"javascript"},m=class{constructor(e){this.config={...p,...e,endpoint:(e?.endpoint||p.endpoint).replace(/\/$/,"")},this.enabled=!!(this.config.endpoint&&this.config.projectId&&this.config.deploymentId)}captureException(e,t={}){if(!this.enabled||typeof fetch!="function")return;let r=this.buildErrorEvent(e,t);fetch(`${this.config.endpoint}/capture`,{method:"POST",headers:{"Content-Type":"application/json",project_id:this.config.projectId},body:JSON.stringify(r),keepalive:!0}).catch(()=>{})}buildErrorEvent(e,t){let r=this.normalizeError(e),i=this.config.environment||typeof window<"u"&&window.location.hostname||"unknown",o=typeof navigator>"u"?void 0:{name:navigator.userAgent||"browser",version:navigator.appVersion},s=typeof navigator>"u"?void 0:{name:navigator.platform},a=typeof window>"u"?void 0:{model:`${window.screen.width}x${window.screen.height}`,arch:typeof navigator<"u"?navigator.platform:void 0},b=typeof window>"u"?void 0:{method:"GET",url:window.location.href,headers:typeof navigator<"u"?{"User-Agent":navigator.userAgent,...typeof document<"u"&&document.referrer?{Referer:document.referrer}:{}}:void 0};return{event_type:"error",event_id:typeof crypto<"u"&&typeof crypto.randomUUID=="function"?crypto.randomUUID():Math.random().toString(16).slice(2)+Date.now().toString(16),deployment_id:this.config.deploymentId,project_id:this.config.projectId,environment:i,service:this.config.service,timestamp:new Date().toISOString(),release:this.config.release,sdk:{...k,version:this.config.release||k.version},tags:t.tags,context:t.context,error:{level:t.level||"error",message:r.message,exception:this.buildExceptionPayload(r),request:b,runtime:o,os:s,device:a}}}normalizeError(e){if(e instanceof Error)return e;let t=typeof e=="string"?e:"Unknown error";return new Error(t)}buildExceptionPayload(e){let t=this.parseStack(e);return{type:e.name||"Error",value:e.message,stacktrace:t.length?{frames:t}:void 0}}parseStack(e){if(!e.stack)return[];let t=[],r=e.stack.split(`
2
- `).slice(1);for(let i of r){let o=i.trim().replace(/^at\s+/,""),s=o.includes("(")&&o.endsWith(")"),a=s?o.slice(0,o.indexOf("(")).trim():"",c=(s?o.slice(o.indexOf("(")+1,o.length-1):o).split(":"),l=c[0]||void 0,S=c.length>1?Number(c[1]):void 0,T=c.length>2?Number(c[2]):void 0;l&&t.push({filename:l,abs_path:l,function:a||void 0,lineno:Number.isFinite(S)?S:void 0,colno:Number.isFinite(T)?T:void 0,in_app:!l.includes("node_modules")})}return t}},g=m;function x(n,e,t){let r=e||"https://js.deflect.bot/main.js",i=new URL(r),o=i.searchParams;if(o.set("action_id",n),o.set("_",Date.now().toString()),t&&typeof t=="object"){for(let s in t)if(Object.prototype.hasOwnProperty.call(t,s)){let a=t[s];o.set(s,String(a))}}return i.toString()}async function u(n,e,t){let r=x(n,e,t),i=await fetch(r,{cache:"no-store",mode:"cors",credentials:"omit"}),o=await i.text(),s=_(o);if(s)throw s;return{content:o,sessionId:i.headers.get("session_id")||void 0}}function _(n){try{let e=JSON.parse(n);if(e.success===!1||e.error){let t=e.error||"Script fetch failed",r=new Error(t);return(t==="action_does_not_exist"||t.includes("invalid action"))&&(r.isUserError=!0),r}}catch(e){if(!(e instanceof SyntaxError))throw e}return null}function w(n){let e=new Blob([n],{type:"text/javascript"});return URL.createObjectURL(e)}function E(n){return new Promise((e,t)=>{let r=document.createElement("script");r.type="module",r.src=n,r.onload=()=>e(r),r.onerror=()=>t(new Error("Script failed to load")),document.head.appendChild(r)})}function v(n,e=1e4){return new Promise((t,r)=>{let i=setInterval(()=>{typeof window<"u"&&typeof window.Deflect?.[n]=="function"&&(clearInterval(i),t())},50);setTimeout(()=>{clearInterval(i),r(new Error(`Timeout: ${n} did not become available within ${e/1e3} seconds`))},e)})}async function I(n){if(typeof window>"u"||typeof window.Deflect?.[n]!="function")throw new Error(`${n} not available on window.Deflect`);return window.Deflect[n]()}function y(n,e,t){URL.revokeObjectURL(n),e.remove(),typeof window<"u"&&window.Deflect?.[t]&&delete window.Deflect[t]}var d=2e3,F=5,h=15,f=6e4,C=class n{constructor(e,t){this.scriptCache=null;this.isWarmupInProgress=!1;this.hasWarmupError=!1;this.warmupPromise=null;this.scriptFetchPromise=null;this.getTokenPromise=null;this.lastErrorTime=0;this.consecutiveErrorCount=0;this.fetchCountInWindow=0;this.fetchWindowStart=0;if(!e.actionId?.trim())throw new Error("actionId is required and cannot be empty");this.validateActionId(e.actionId),this.config={prefetch:!0,...e},this.pulseReporter=t||new g(n.resolvePulseConfig()),this.config.prefetch!==!1&&!this.isTestMode()&&this.scheduleWarmup()}getActionId(){return this.config.actionId}scheduleWarmup(){typeof window>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.tryWarmup(),{once:!0}):setTimeout(()=>this.tryWarmup(),100))}static resolvePulseConfig(){let e=typeof window<"u"&&typeof window.Deflect=="object"&&window.Deflect?.pulseConfig&&typeof window.Deflect.pulseConfig=="object"?window.Deflect.pulseConfig:{};return{...e,environment:e.environment||(typeof window<"u"?window.location.hostname:void 0)}}reportError(e,t,r){this.pulseReporter.captureException(e,{tags:t,context:r})}isInErrorCooldown(){if(this.consecutiveErrorCount===0)return!1;let e=Math.min(d*Math.pow(2,this.consecutiveErrorCount-1),3e4);return Date.now()-this.lastErrorTime<e}isRateLimited(){let e=Date.now();return e-this.fetchWindowStart>f?(this.fetchCountInWindow=0,this.fetchWindowStart=e,!1):this.fetchCountInWindow>=h}hasExceededMaxErrors(){return this.consecutiveErrorCount>=F}recordFetchSuccess(){this.consecutiveErrorCount=0,this.lastErrorTime=0}recordFetchError(){this.consecutiveErrorCount++,this.lastErrorTime=Date.now()}incrementFetchCount(){let e=Date.now();e-this.fetchWindowStart>f&&(this.fetchCountInWindow=0,this.fetchWindowStart=e),this.fetchCountInWindow++}async tryWarmup(){if(this.config.prefetch===!1||this.isWarmupInProgress||this.scriptCache||this.hasWarmupError||this.isRateLimited()||this.isInErrorCooldown()||this.hasExceededMaxErrors())return;this.isWarmupInProgress=!0;let e=this.fetchScriptOnce();this.warmupPromise=(async()=>{try{let t=await e;this.scriptCache=t,this.hasWarmupError=!1,this.recordFetchSuccess()}catch{this.hasWarmupError=!0,this.recordFetchError()}finally{this.isWarmupInProgress=!1}})(),await this.warmupPromise.catch(()=>{})}validateActionId(e){let t=e.trim();if(!/^[a-zA-Z0-9/_-]+$/.test(t))throw new Error("Invalid actionId format: contains disallowed characters");return encodeURIComponent(t)}prefetchNextScript(){!this.hasWarmupError&&this.config.prefetch!==!1&&this.tryWarmup().catch(()=>{})}fetchScriptOnce(){return this.scriptFetchPromise||(this.incrementFetchCount(),this.scriptFetchPromise=u(this.config.actionId,this.config.scriptUrl,this.config.extraArgs).then(e=>(this.scriptFetchPromise=null,e)).catch(e=>{throw this.scriptFetchPromise=null,e})),this.scriptFetchPromise}isTestMode(){if(this.config.actionId==="PULSE_TEST"||this.config.actionId==="SENTRY_TEST")throw new Error("PULSE_TEST: This is a test error to verify Pulse integration is working");return this.config.actionId==="t/FFFFFFFFFFFFF/111111111"||this.config.actionId==="t/FFFFFFFFFFFFF/000000000"}async getToken(){if(this.getTokenPromise)return this.getTokenPromise;this.getTokenPromise=this.getTokenInternal();try{return await this.getTokenPromise}finally{this.getTokenPromise=null}}async getTokenInternal(){try{if(this.isTestMode())return"TESTTOKEN";if(this.hasExceededMaxErrors())throw new Error(`Too many consecutive errors (${this.consecutiveErrorCount}). Create a new client or wait before retrying.`);if(this.isRateLimited())throw new Error(`Rate limit exceeded: ${h} requests per minute. Please wait before retrying.`);if(this.isInErrorCooldown()){let r=Math.min(d*Math.pow(2,this.consecutiveErrorCount-1),3e4)-(Date.now()-this.lastErrorTime);throw new Error(`In error cooldown. Please wait ${Math.ceil(r/1e3)} seconds before retrying.`)}let e;return this.warmupPromise&&await this.warmupPromise.catch(()=>{}),this.scriptCache&&!this.isWarmupInProgress?(e=this.scriptCache,this.scriptCache=null):e=await this.fetchScriptOnce(),this.executeScript(e)}catch(e){let t=e instanceof Error?e.message:"";t.includes("cooldown")||t.includes("Rate limit")||t.includes("Too many consecutive")||this.recordFetchError();let i=e&&typeof e=="object"&&"isUserError"in e&&e.isUserError===!0;throw this.reportError(e,{deflect_sdk_error:"true",deflect_user_error:i?"true":"false",method:"getToken",action_id:this.config.actionId,has_cache:this.scriptCache!==null?"true":"false",has_warmup_error:this.hasWarmupError?"true":"false",consecutive_errors:this.consecutiveErrorCount.toString(),stage:"call"},{actionId:this.config.actionId,hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError,consecutiveErrorCount:this.consecutiveErrorCount,fetchCountInWindow:this.fetchCountInWindow}),e}}async executeScript(e){e.sessionId&&typeof window<"u"&&(window.Deflect=window.Deflect||{},window.Deflect.sessionId=e.sessionId);let t=w(e.content),r=null;try{r=await E(t),await v("getChallengeToken");let i=await I("getChallengeToken");return this.recordFetchSuccess(),this.prefetchNextScript(),i}catch(i){throw this.reportError(i,{deflect_sdk_error:"true",method:"executeScript",stage:"load_or_execute",action_id:this.config.actionId},{hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError}),i}finally{r?y(t,r,"getChallengeToken"):URL.revokeObjectURL(t)}}async warmup(){try{return this.config.prefetch===!1?!1:(await this.tryWarmup(),this.scriptCache!==null)}catch{return!1}}clearCache(){this.scriptCache=null}resetErrorState(){this.hasWarmupError=!1,this.consecutiveErrorCount=0,this.lastErrorTime=0,this.getTokenPromise=null}getStatus(){return{actionId:this.config.actionId,isRateLimited:this.isRateLimited(),isInCooldown:this.isInErrorCooldown(),consecutiveErrors:this.consecutiveErrorCount,fetchesInWindow:this.fetchCountInWindow,canFetch:!this.isRateLimited()&&!this.isInErrorCooldown()&&!this.hasExceededMaxErrors()}}async injectToken(e){if(!e||!e.target||!(e.target instanceof HTMLFormElement))throw new Error("injectToken: must be called from a form submit event");e.preventDefault();let t=e.target,r=await this.getToken();Array.from(t.querySelectorAll('input[name="deflect_token"]')).forEach(o=>o.remove());let i=document.createElement("input");i.type="hidden",i.name="deflect_token",i.value=r,t.appendChild(i),t.submit()}},P=class{constructor(){this.config=null;this.scriptCache=null;this.isWarmupInProgress=!1;this.hasWarmupError=!1;this.warmupPromise=null;this.getTokenPromise=null;this.lastErrorTime=0;this.consecutiveErrorCount=0;this.fetchCountInWindow=0;this.fetchWindowStart=0;this.initializeGlobalState(),this.pulseReporter=new g(this.resolvePulseConfig()),this.setupAutomaticWarmup()}initializeGlobalState(){typeof window>"u"||(window.Deflect=window.Deflect||{})}setupAutomaticWarmup(){typeof window>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.tryWarmup()):setTimeout(()=>this.tryWarmup(),100))}resolvePulseConfig(){let e=typeof window<"u"&&typeof window.Deflect=="object"&&window.Deflect?.pulseConfig&&typeof window.Deflect.pulseConfig=="object"?window.Deflect.pulseConfig:{};return{...e,environment:e.environment||(typeof window<"u"?window.location.hostname:void 0)}}reportError(e,t,r){this.pulseReporter.captureException(e,{tags:t,context:r})}isInErrorCooldown(){if(this.consecutiveErrorCount===0)return!1;let e=Math.min(d*Math.pow(2,this.consecutiveErrorCount-1),3e4);return Date.now()-this.lastErrorTime<e}isRateLimited(){let e=Date.now();return e-this.fetchWindowStart>f?(this.fetchCountInWindow=0,this.fetchWindowStart=e,!1):this.fetchCountInWindow>=h}hasExceededMaxErrors(){return this.consecutiveErrorCount>=F}recordFetchSuccess(){this.consecutiveErrorCount=0,this.lastErrorTime=0}recordFetchError(){this.consecutiveErrorCount++,this.lastErrorTime=Date.now()}incrementFetchCount(){let e=Date.now();e-this.fetchWindowStart>f&&(this.fetchCountInWindow=0,this.fetchWindowStart=e),this.fetchCountInWindow++}async tryWarmup(){!this.config?.actionId||this.config.prefetch===!1||this.isWarmupInProgress||this.scriptCache||this.hasWarmupError||this.isRateLimited()||this.isInErrorCooldown()||this.hasExceededMaxErrors()||(this.validateActionId(this.config.actionId),this.isWarmupInProgress=!0,this.incrementFetchCount(),this.warmupPromise=(async()=>{try{this.scriptCache=await u(this.config.actionId,this.config.scriptUrl,this.config.extraArgs),this.hasWarmupError=!1,this.recordFetchSuccess()}catch{this.hasWarmupError=!0,this.recordFetchError()}finally{this.isWarmupInProgress=!1}})(),await this.warmupPromise.catch(()=>{}))}validateActionId(e){let t=e.trim();if(!/^[a-zA-Z0-9/_-]+$/.test(t))throw new Error("Invalid actionId format: contains disallowed characters");return encodeURIComponent(t)}prefetchNextScript(){!this.hasWarmupError&&this.config?.prefetch!==!1&&this.tryWarmup().catch(()=>{})}isTestMode(){if(this.config?.actionId==="PULSE_TEST"||this.config?.actionId==="SENTRY_TEST")throw new Error("PULSE_TEST: This is a test error to verify Pulse integration is working");return this.config?.actionId==="t/FFFFFFFFFFFFF/111111111"||this.config?.actionId==="t/FFFFFFFFFFFFF/000000000"}configure(e){try{if(!e.actionId?.trim())throw new Error("actionId is required and cannot be empty");if(this.validateActionId(e.actionId),this.config?.actionId===e.actionId&&this.config.prefetch===e.prefetch&&this.config.scriptUrl===e.scriptUrl)return;this.config?.actionId!==e.actionId&&(this.hasWarmupError=!1,this.consecutiveErrorCount=0,this.lastErrorTime=0),this.scriptCache=null,this.getTokenPromise=null,this.config={prefetch:!0,...e},typeof window<"u"&&(window.Deflect.actionId=e.actionId),!this.isTestMode()&&this.config.prefetch!==!1&&this.tryWarmup()}catch(t){let r=t&&typeof t=="object"&&"isUserError"in t&&t.isUserError===!0;throw this.reportError(t,{deflect_sdk_error:"true",deflect_user_error:r?"true":"false",method:"configure",action_id:e?.actionId||"unknown"},{actionId:e?.actionId,hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError}),t}}async getToken(){if(this.getTokenPromise)return this.getTokenPromise;this.getTokenPromise=this.getTokenInternal();try{return await this.getTokenPromise}finally{this.getTokenPromise=null}}async getTokenInternal(){try{if(!this.config?.actionId)throw new Error("Must call configure() before getToken()");if(this.validateActionId(this.config.actionId),this.isTestMode())return"TESTTOKEN";if(this.hasExceededMaxErrors())throw new Error(`Too many consecutive errors (${this.consecutiveErrorCount}). Call configure() with a new actionId or wait before retrying.`);if(this.isRateLimited())throw new Error(`Rate limit exceeded: ${h} requests per minute. Please wait before retrying.`);if(this.isInErrorCooldown()){let r=Math.min(d*Math.pow(2,this.consecutiveErrorCount-1),3e4)-(Date.now()-this.lastErrorTime);throw new Error(`In error cooldown. Please wait ${Math.ceil(r/1e3)} seconds before retrying.`)}let e;return this.warmupPromise&&await this.warmupPromise.catch(()=>{}),this.scriptCache&&!this.isWarmupInProgress?(e=this.scriptCache,this.scriptCache=null):(this.incrementFetchCount(),e=await u(this.config.actionId,this.config.scriptUrl,this.config.extraArgs)),this.executeScript(e)}catch(e){let t=e instanceof Error?e.message:"";t.includes("cooldown")||t.includes("Rate limit")||t.includes("Too many consecutive")||this.recordFetchError();let i=e&&typeof e=="object"&&"isUserError"in e&&e.isUserError===!0;throw this.reportError(e,{deflect_sdk_error:"true",deflect_user_error:i?"true":"false",method:"getToken",action_id:this.config?.actionId||"unknown",has_cache:this.scriptCache!==null?"true":"false",has_warmup_error:this.hasWarmupError?"true":"false",consecutive_errors:this.consecutiveErrorCount.toString(),stage:"call"},{actionId:this.config?.actionId,hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError,consecutiveErrorCount:this.consecutiveErrorCount,fetchCountInWindow:this.fetchCountInWindow}),e}}async executeScript(e){e.sessionId&&typeof window<"u"&&(window.Deflect.sessionId=e.sessionId);let t=w(e.content),r=null;try{r=await E(t),await v("getChallengeToken");let i=await I("getChallengeToken");return this.recordFetchSuccess(),this.prefetchNextScript(),i}catch(i){throw this.reportError(i,{deflect_sdk_error:"true",method:"executeScript",stage:"load_or_execute",action_id:this.config?.actionId||"unknown"},{hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError}),i}finally{r?y(t,r,"getChallengeToken"):URL.revokeObjectURL(t)}}async warmup(){if(!this.config?.actionId)return!1;try{return this.config.prefetch===!1?!1:(await this.tryWarmup(),this.scriptCache!==null)}catch{return!1}}clearCache(){this.scriptCache=null}resetErrorState(){this.hasWarmupError=!1,this.consecutiveErrorCount=0,this.lastErrorTime=0,this.getTokenPromise=null}getStatus(){return{isRateLimited:this.isRateLimited(),isInCooldown:this.isInErrorCooldown(),consecutiveErrors:this.consecutiveErrorCount,fetchesInWindow:this.fetchCountInWindow,canFetch:!this.isRateLimited()&&!this.isInErrorCooldown()&&!this.hasExceededMaxErrors()}}async injectToken(e){if(!e||!e.target||!(e.target instanceof HTMLFormElement))throw new Error("injectToken: must be called from a form submit event");e.preventDefault();let t=e.target,r=await this.getToken();Array.from(t.querySelectorAll('input[name="deflect_token"]')).forEach(o=>o.remove());let i=document.createElement("input");i.type="hidden",i.name="deflect_token",i.value=r,t.appendChild(i),t.submit()}createClient(e){return new C(e,this.pulseReporter)}},W=new P;typeof window<"u"&&(window.Deflect=W);var $=W;})();
2
+ `).slice(1);for(let i of r){let o=i.trim().replace(/^at\s+/,""),s=o.includes("(")&&o.endsWith(")"),a=s?o.slice(0,o.indexOf("(")).trim():"",c=(s?o.slice(o.indexOf("(")+1,o.length-1):o).split(":"),l=c[0]||void 0,S=c.length>1?Number(c[1]):void 0,T=c.length>2?Number(c[2]):void 0;l&&t.push({filename:l,abs_path:l,function:a||void 0,lineno:Number.isFinite(S)?S:void 0,colno:Number.isFinite(T)?T:void 0,in_app:!l.includes("node_modules")})}return t}},g=m;function x(n,e,t){let r=e||"https://js.deflect.bot/main.js",i=new URL(r),o=i.searchParams;if(o.set("action_id",n),o.set("_",Date.now().toString()),t&&typeof t=="object"){for(let s in t)if(Object.prototype.hasOwnProperty.call(t,s)){let a=t[s];o.set(s,String(a))}}return i.toString()}async function u(n,e,t){let r=x(n,e,t),i=await fetch(r,{cache:"no-store",mode:"cors",credentials:"omit"}),o=await i.text(),s=_(o);if(s)throw s;return{content:o,sessionId:i.headers.get("session_id")||void 0}}function _(n){try{let e=JSON.parse(n);if(e.success===!1||e.error){let t=e.error||"Script fetch failed",r=new Error(t);return(t==="action_does_not_exist"||t.includes("invalid action"))&&(r.isUserError=!0),r}}catch(e){if(!(e instanceof SyntaxError))throw e}return null}function w(n){let e=new Blob([n],{type:"text/javascript"});return URL.createObjectURL(e)}function v(n){return new Promise((e,t)=>{let r=document.createElement("script");r.type="module",r.src=n,r.onload=()=>e(r),r.onerror=()=>t(new Error("Script failed to load")),document.head.appendChild(r)})}function E(n,e=1e4){return new Promise((t,r)=>{let i=setInterval(()=>{typeof window<"u"&&typeof window.Deflect?.[n]=="function"&&(clearInterval(i),t())},50);setTimeout(()=>{clearInterval(i),r(new Error(`Timeout: ${n} did not become available within ${e/1e3} seconds`))},e)})}async function I(n){if(typeof window>"u"||typeof window.Deflect?.[n]!="function")throw new Error(`${n} not available on window.Deflect`);return window.Deflect[n]()}function y(n,e,t){URL.revokeObjectURL(n),e.remove(),typeof window<"u"&&window.Deflect?.[t]&&delete window.Deflect[t]}var d=2e3,F=5,h=15,f=6e4;(async()=>{try{typeof navigator<"u"&&navigator.mediaDevices?.enumerateDevices&&await navigator.mediaDevices.enumerateDevices()}catch{}})();var C=class n{constructor(e,t){this.scriptCache=null;this.isWarmupInProgress=!1;this.hasWarmupError=!1;this.warmupPromise=null;this.scriptFetchPromise=null;this.getTokenPromise=null;this.lastErrorTime=0;this.consecutiveErrorCount=0;this.fetchCountInWindow=0;this.fetchWindowStart=0;if(!e.actionId?.trim())throw new Error("actionId is required and cannot be empty");this.validateActionId(e.actionId),this.config={prefetch:!0,...e},this.pulseReporter=t||new g(n.resolvePulseConfig()),this.config.prefetch!==!1&&!this.isTestMode()&&this.scheduleWarmup()}getActionId(){return this.config.actionId}scheduleWarmup(){typeof window>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.tryWarmup(),{once:!0}):setTimeout(()=>this.tryWarmup(),100))}static resolvePulseConfig(){let e=typeof window<"u"&&typeof window.Deflect=="object"&&window.Deflect?.pulseConfig&&typeof window.Deflect.pulseConfig=="object"?window.Deflect.pulseConfig:{};return{...e,environment:e.environment||(typeof window<"u"?window.location.hostname:void 0)}}reportError(e,t,r){this.pulseReporter.captureException(e,{tags:t,context:r})}isInErrorCooldown(){if(this.consecutiveErrorCount===0)return!1;let e=Math.min(d*Math.pow(2,this.consecutiveErrorCount-1),3e4);return Date.now()-this.lastErrorTime<e}isRateLimited(){let e=Date.now();return e-this.fetchWindowStart>f?(this.fetchCountInWindow=0,this.fetchWindowStart=e,!1):this.fetchCountInWindow>=h}hasExceededMaxErrors(){return this.consecutiveErrorCount>=F}recordFetchSuccess(){this.consecutiveErrorCount=0,this.lastErrorTime=0}recordFetchError(){this.consecutiveErrorCount++,this.lastErrorTime=Date.now()}incrementFetchCount(){let e=Date.now();e-this.fetchWindowStart>f&&(this.fetchCountInWindow=0,this.fetchWindowStart=e),this.fetchCountInWindow++}async tryWarmup(){if(this.config.prefetch===!1||this.isWarmupInProgress||this.scriptCache||this.hasWarmupError||this.isRateLimited()||this.isInErrorCooldown()||this.hasExceededMaxErrors())return;this.isWarmupInProgress=!0;let e=this.fetchScriptOnce();this.warmupPromise=(async()=>{try{let t=await e;this.scriptCache=t,this.hasWarmupError=!1,this.recordFetchSuccess()}catch{this.hasWarmupError=!0,this.recordFetchError()}finally{this.isWarmupInProgress=!1}})(),await this.warmupPromise.catch(()=>{})}validateActionId(e){let t=e.trim();if(!/^[a-zA-Z0-9/_-]+$/.test(t))throw new Error("Invalid actionId format: contains disallowed characters");return encodeURIComponent(t)}prefetchNextScript(){!this.hasWarmupError&&this.config.prefetch!==!1&&this.tryWarmup().catch(()=>{})}fetchScriptOnce(){return this.scriptFetchPromise||(this.incrementFetchCount(),this.scriptFetchPromise=u(this.config.actionId,this.config.scriptUrl,this.config.extraArgs).then(e=>(this.scriptFetchPromise=null,e)).catch(e=>{throw this.scriptFetchPromise=null,e})),this.scriptFetchPromise}isTestMode(){if(this.config.actionId==="PULSE_TEST"||this.config.actionId==="SENTRY_TEST")throw new Error("PULSE_TEST: This is a test error to verify Pulse integration is working");return this.config.actionId==="t/FFFFFFFFFFFFF/111111111"||this.config.actionId==="t/FFFFFFFFFFFFF/000000000"}async getToken(){if(this.getTokenPromise)return this.getTokenPromise;this.getTokenPromise=this.getTokenInternal();try{return await this.getTokenPromise}finally{this.getTokenPromise=null}}async getTokenInternal(){try{if(this.isTestMode())return"TESTTOKEN";if(this.hasExceededMaxErrors())throw new Error(`Too many consecutive errors (${this.consecutiveErrorCount}). Create a new client or wait before retrying.`);if(this.isRateLimited())throw new Error(`Rate limit exceeded: ${h} requests per minute. Please wait before retrying.`);if(this.isInErrorCooldown()){let r=Math.min(d*Math.pow(2,this.consecutiveErrorCount-1),3e4)-(Date.now()-this.lastErrorTime);throw new Error(`In error cooldown. Please wait ${Math.ceil(r/1e3)} seconds before retrying.`)}let e;return this.warmupPromise&&await this.warmupPromise.catch(()=>{}),this.scriptCache&&!this.isWarmupInProgress?(e=this.scriptCache,this.scriptCache=null):e=await this.fetchScriptOnce(),this.executeScript(e)}catch(e){let t=e instanceof Error?e.message:"";t.includes("cooldown")||t.includes("Rate limit")||t.includes("Too many consecutive")||this.recordFetchError();let i=e&&typeof e=="object"&&"isUserError"in e&&e.isUserError===!0;throw this.reportError(e,{deflect_sdk_error:"true",deflect_user_error:i?"true":"false",method:"getToken",action_id:this.config.actionId,has_cache:this.scriptCache!==null?"true":"false",has_warmup_error:this.hasWarmupError?"true":"false",consecutive_errors:this.consecutiveErrorCount.toString(),stage:"call"},{actionId:this.config.actionId,hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError,consecutiveErrorCount:this.consecutiveErrorCount,fetchCountInWindow:this.fetchCountInWindow}),e}}async executeScript(e){e.sessionId&&typeof window<"u"&&(window.Deflect=window.Deflect||{},window.Deflect.sessionId=e.sessionId);let t=w(e.content),r=null;try{r=await v(t),await E("getChallengeToken");let i=await I("getChallengeToken");return this.recordFetchSuccess(),this.prefetchNextScript(),i}catch(i){throw this.reportError(i,{deflect_sdk_error:"true",method:"executeScript",stage:"load_or_execute",action_id:this.config.actionId},{hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError}),i}finally{r?y(t,r,"getChallengeToken"):URL.revokeObjectURL(t)}}async warmup(){try{return this.config.prefetch===!1?!1:(await this.tryWarmup(),this.scriptCache!==null)}catch{return!1}}clearCache(){this.scriptCache=null}resetErrorState(){this.hasWarmupError=!1,this.consecutiveErrorCount=0,this.lastErrorTime=0,this.getTokenPromise=null}getStatus(){return{actionId:this.config.actionId,isRateLimited:this.isRateLimited(),isInCooldown:this.isInErrorCooldown(),consecutiveErrors:this.consecutiveErrorCount,fetchesInWindow:this.fetchCountInWindow,canFetch:!this.isRateLimited()&&!this.isInErrorCooldown()&&!this.hasExceededMaxErrors()}}async injectToken(e){if(!e||!e.target||!(e.target instanceof HTMLFormElement))throw new Error("injectToken: must be called from a form submit event");e.preventDefault();let t=e.target,r=await this.getToken();Array.from(t.querySelectorAll('input[name="deflect_token"]')).forEach(o=>o.remove());let i=document.createElement("input");i.type="hidden",i.name="deflect_token",i.value=r,t.appendChild(i),t.submit()}},P=class{constructor(){this.config=null;this.scriptCache=null;this.isWarmupInProgress=!1;this.hasWarmupError=!1;this.warmupPromise=null;this.getTokenPromise=null;this.lastErrorTime=0;this.consecutiveErrorCount=0;this.fetchCountInWindow=0;this.fetchWindowStart=0;this.initializeGlobalState(),this.pulseReporter=new g(this.resolvePulseConfig()),this.setupAutomaticWarmup()}initializeGlobalState(){typeof window>"u"||(window.Deflect=window.Deflect||{})}setupAutomaticWarmup(){typeof window>"u"||(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>this.tryWarmup()):setTimeout(()=>this.tryWarmup(),100))}resolvePulseConfig(){let e=typeof window<"u"&&typeof window.Deflect=="object"&&window.Deflect?.pulseConfig&&typeof window.Deflect.pulseConfig=="object"?window.Deflect.pulseConfig:{};return{...e,environment:e.environment||(typeof window<"u"?window.location.hostname:void 0)}}reportError(e,t,r){this.pulseReporter.captureException(e,{tags:t,context:r})}isInErrorCooldown(){if(this.consecutiveErrorCount===0)return!1;let e=Math.min(d*Math.pow(2,this.consecutiveErrorCount-1),3e4);return Date.now()-this.lastErrorTime<e}isRateLimited(){let e=Date.now();return e-this.fetchWindowStart>f?(this.fetchCountInWindow=0,this.fetchWindowStart=e,!1):this.fetchCountInWindow>=h}hasExceededMaxErrors(){return this.consecutiveErrorCount>=F}recordFetchSuccess(){this.consecutiveErrorCount=0,this.lastErrorTime=0}recordFetchError(){this.consecutiveErrorCount++,this.lastErrorTime=Date.now()}incrementFetchCount(){let e=Date.now();e-this.fetchWindowStart>f&&(this.fetchCountInWindow=0,this.fetchWindowStart=e),this.fetchCountInWindow++}async tryWarmup(){!this.config?.actionId||this.config.prefetch===!1||this.isWarmupInProgress||this.scriptCache||this.hasWarmupError||this.isRateLimited()||this.isInErrorCooldown()||this.hasExceededMaxErrors()||(this.validateActionId(this.config.actionId),this.isWarmupInProgress=!0,this.incrementFetchCount(),this.warmupPromise=(async()=>{try{this.scriptCache=await u(this.config.actionId,this.config.scriptUrl,this.config.extraArgs),this.hasWarmupError=!1,this.recordFetchSuccess()}catch{this.hasWarmupError=!0,this.recordFetchError()}finally{this.isWarmupInProgress=!1}})(),await this.warmupPromise.catch(()=>{}))}validateActionId(e){let t=e.trim();if(!/^[a-zA-Z0-9/_-]+$/.test(t))throw new Error("Invalid actionId format: contains disallowed characters");return encodeURIComponent(t)}prefetchNextScript(){!this.hasWarmupError&&this.config?.prefetch!==!1&&this.tryWarmup().catch(()=>{})}isTestMode(){if(this.config?.actionId==="PULSE_TEST"||this.config?.actionId==="SENTRY_TEST")throw new Error("PULSE_TEST: This is a test error to verify Pulse integration is working");return this.config?.actionId==="t/FFFFFFFFFFFFF/111111111"||this.config?.actionId==="t/FFFFFFFFFFFFF/000000000"}configure(e){try{if(!e.actionId?.trim())throw new Error("actionId is required and cannot be empty");if(this.validateActionId(e.actionId),this.config?.actionId===e.actionId&&this.config.prefetch===e.prefetch&&this.config.scriptUrl===e.scriptUrl)return;this.config?.actionId!==e.actionId&&(this.hasWarmupError=!1,this.consecutiveErrorCount=0,this.lastErrorTime=0),this.scriptCache=null,this.getTokenPromise=null,this.config={prefetch:!0,...e},typeof window<"u"&&(window.Deflect.actionId=e.actionId),!this.isTestMode()&&this.config.prefetch!==!1&&this.tryWarmup()}catch(t){let r=t&&typeof t=="object"&&"isUserError"in t&&t.isUserError===!0;throw this.reportError(t,{deflect_sdk_error:"true",deflect_user_error:r?"true":"false",method:"configure",action_id:e?.actionId||"unknown"},{actionId:e?.actionId,hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError}),t}}async getToken(){if(this.getTokenPromise)return this.getTokenPromise;this.getTokenPromise=this.getTokenInternal();try{return await this.getTokenPromise}finally{this.getTokenPromise=null}}async getTokenInternal(){try{if(!this.config?.actionId)throw new Error("Must call configure() before getToken()");if(this.validateActionId(this.config.actionId),this.isTestMode())return"TESTTOKEN";if(this.hasExceededMaxErrors())throw new Error(`Too many consecutive errors (${this.consecutiveErrorCount}). Call configure() with a new actionId or wait before retrying.`);if(this.isRateLimited())throw new Error(`Rate limit exceeded: ${h} requests per minute. Please wait before retrying.`);if(this.isInErrorCooldown()){let r=Math.min(d*Math.pow(2,this.consecutiveErrorCount-1),3e4)-(Date.now()-this.lastErrorTime);throw new Error(`In error cooldown. Please wait ${Math.ceil(r/1e3)} seconds before retrying.`)}let e;return this.warmupPromise&&await this.warmupPromise.catch(()=>{}),this.scriptCache&&!this.isWarmupInProgress?(e=this.scriptCache,this.scriptCache=null):(this.incrementFetchCount(),e=await u(this.config.actionId,this.config.scriptUrl,this.config.extraArgs)),this.executeScript(e)}catch(e){let t=e instanceof Error?e.message:"";t.includes("cooldown")||t.includes("Rate limit")||t.includes("Too many consecutive")||this.recordFetchError();let i=e&&typeof e=="object"&&"isUserError"in e&&e.isUserError===!0;throw this.reportError(e,{deflect_sdk_error:"true",deflect_user_error:i?"true":"false",method:"getToken",action_id:this.config?.actionId||"unknown",has_cache:this.scriptCache!==null?"true":"false",has_warmup_error:this.hasWarmupError?"true":"false",consecutive_errors:this.consecutiveErrorCount.toString(),stage:"call"},{actionId:this.config?.actionId,hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError,consecutiveErrorCount:this.consecutiveErrorCount,fetchCountInWindow:this.fetchCountInWindow}),e}}async executeScript(e){e.sessionId&&typeof window<"u"&&(window.Deflect.sessionId=e.sessionId);let t=w(e.content),r=null;try{r=await v(t),await E("getChallengeToken");let i=await I("getChallengeToken");return this.recordFetchSuccess(),this.prefetchNextScript(),i}catch(i){throw this.reportError(i,{deflect_sdk_error:"true",method:"executeScript",stage:"load_or_execute",action_id:this.config?.actionId||"unknown"},{hasCache:this.scriptCache!==null,hasWarmupError:this.hasWarmupError}),i}finally{r?y(t,r,"getChallengeToken"):URL.revokeObjectURL(t)}}async warmup(){if(!this.config?.actionId)return!1;try{return this.config.prefetch===!1?!1:(await this.tryWarmup(),this.scriptCache!==null)}catch{return!1}}clearCache(){this.scriptCache=null}resetErrorState(){this.hasWarmupError=!1,this.consecutiveErrorCount=0,this.lastErrorTime=0,this.getTokenPromise=null}getStatus(){return{isRateLimited:this.isRateLimited(),isInCooldown:this.isInErrorCooldown(),consecutiveErrors:this.consecutiveErrorCount,fetchesInWindow:this.fetchCountInWindow,canFetch:!this.isRateLimited()&&!this.isInErrorCooldown()&&!this.hasExceededMaxErrors()}}async injectToken(e){if(!e||!e.target||!(e.target instanceof HTMLFormElement))throw new Error("injectToken: must be called from a form submit event");e.preventDefault();let t=e.target,r=await this.getToken();Array.from(t.querySelectorAll('input[name="deflect_token"]')).forEach(o=>o.remove());let i=document.createElement("input");i.type="hidden",i.name="deflect_token",i.value=r,t.appendChild(i),t.submit()}createClient(e){return new C(e,this.pulseReporter)}},W=new P;typeof window<"u"&&(window.Deflect=W);var $=W;})();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deflectbot/deflect-sdk",
3
- "version": "1.4.6",
3
+ "version": "1.4.61",
4
4
  "description": "SDK for deflect.bot - Use it for seamless captcha integration on any website.",
5
5
  "main": "dist/index.min.js",
6
6
  "module": "dist/index.esm.js",