@encatch/web-sdk 1.2.1-beta.0 → 1.2.1-beta.2

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.
@@ -1,2 +1,2 @@
1
- const e="encatch-sdk-script";let t=!1,n=!1,i=null;function r(r){return n?Promise.resolve():i?Promise.reject(i):t?new Promise((e,t)=>{const r=setInterval(()=>{n?(clearInterval(r),e()):i&&(clearInterval(r),t(i))},50)}):(t=!0,new Promise((o,a)=>{if(document.getElementById(e))return t=!1,n=!0,void o();const s=(r.webHost||"https://app.encatch.com")+"/s/sdk/v1/encatch.js?dt="+function(){const e=/* @__PURE__ */new Date,t=String(e.getUTCFullYear()).slice(-2),n=String(e.getUTCMonth()+1).padStart(2,"0"),i=String(e.getUTCDate()).padStart(2,"0"),r=String(e.getUTCHours()).padStart(2,"0"),o=30*Math.floor(e.getUTCMinutes()/30);return`${t}${n}${i}${r}${String(o).padStart(2,"0")}`}(),c=document.createElement("script");c.id=e,c.src=s,c.type="module",c.async=!0,c.onload=()=>{t=!1,n=!0,o()},c.onerror=e=>{t=!1,i=new Error(`[Encatch] Failed to load SDK from ${s}. Please check your network connection and web host configuration.`),console.error(i.message,e),a(i)};const l=document.getElementsByTagName("script")[0];l&&l.parentNode?l.parentNode.insertBefore(c,l):document.head.appendChild(c)}))}function o(e,t){return function(...n){e.push([t,...n])}}const a=["init","identifyUser","setLocale","setCountry","setTheme","trackEvent","trackScreen","startSession","resetUser","showForm","dismissForm","addToResponse","submitForm","emitEvent","clearAll","addSourceTracking"];function s(){const e=[],t=[],n={_q:e,_eventCallbacks:t,_initialized:!1,_apiKey:null,_config:{},init(t,i){n._initialized?console.warn("[Encatch] SDK already initialized. Ignoring init call."):(n._apiKey=t,n._config=i||{},n._initialized=!0,e.push(["init",t,i]),"undefined"!=typeof window&&"undefined"!=typeof document&&r(n._config).catch(e=>{console.error("[Encatch] Failed to initialize SDK:",e)}))},on:e=>(t.push(e),()=>{const n=t.indexOf(e);n>-1&&t.splice(n,1)}),identifyUser:()=>{},setLocale:()=>{},setCountry:()=>{},setTheme:()=>{},trackEvent:()=>{},trackScreen:()=>{},startSession:()=>{},resetUser:()=>{},showForm:()=>{},dismissForm:()=>{},addToResponse:()=>{},submitForm:()=>{},emitEvent:()=>{},refineText:()=>Promise.resolve({}),qnaWithAi:()=>Promise.resolve({answer:""}),uploadFile:()=>Promise.reject(new Error("[Encatch] uploadFile is not available before SDK initialization")),clearAll:()=>{},addSourceTracking:()=>{}},i=a.filter(e=>"init"!==e);for(const r of i)n[r]=o(e,r);return n}const c=function(){if("undefined"!=typeof window){const e=window._encatch;if(e&&Array.isArray(e._q)){const t=s();return t._q.push(...e._q),Array.isArray(e._eventCallbacks)&&t._eventCallbacks.push(...e._eventCallbacks),e._initialized&&(t._initialized=e._initialized,t._apiKey=e._apiKey,t._config=e._config||{}),window._encatch=t,t}const t=s();return window._encatch=t,t}return s()}();export{c as _encatch,c as default};
2
- //# sourceMappingURL=encatch.es.js.map
1
+ var e="encatch-sdk-script";var t=!1,n=!1,i=null;function r(r){return n?Promise.resolve():i?Promise.reject(i):t?new Promise((e,t)=>{const r=setInterval(()=>{n?(clearInterval(r),e()):i&&(clearInterval(r),t(i))},50)}):(t=!0,new Promise((o,a)=>{if(document.getElementById(e))return t=!1,n=!0,void o();const s=(r.webHost||"https://app.encatch.com")+"/s/sdk/v1/encatch.js?dt="+function(){const e=/* @__PURE__ */new Date,t=String(e.getUTCFullYear()).slice(-2),n=String(e.getUTCMonth()+1).padStart(2,"0"),i=String(e.getUTCDate()).padStart(2,"0"),r=String(e.getUTCHours()).padStart(2,"0"),o=30*Math.floor(e.getUTCMinutes()/30);return`${t}${n}${i}${r}${String(o).padStart(2,"0")}`}(),c=document.createElement("script");c.id=e,c.src=s,c.type="module",c.async=!0,c.onload=()=>{t=!1,n=!0,o()},c.onerror=e=>{t=!1,i=/* @__PURE__ */new Error(`[Encatch] Failed to load SDK from ${s}. Please check your network connection and web host configuration.`),console.error(i.message,e),a(i)};const l=document.getElementsByTagName("script")[0];l&&l.parentNode?l.parentNode.insertBefore(c,l):document.head.appendChild(c)}))}function o(e,t){return function(...n){e.push([t,...n])}}var a=["init","identifyUser","setLocale","setCountry","setTheme","trackEvent","trackScreen","startSession","resetUser","showForm","dismissForm","addToResponse","submitForm","emitEvent","clearAll","addSourceTracking"];function s(){const e=[],t=[],n={_q:e,_eventCallbacks:t,_initialized:!1,_apiKey:null,_config:{},init(t,i){n._initialized?console.warn("[Encatch] SDK already initialized. Ignoring init call."):(n._apiKey=t,n._config=i||{},n._initialized=!0,e.push(["init",t,i]),"undefined"!=typeof window&&"undefined"!=typeof document&&r(n._config).catch(e=>{console.error("[Encatch] Failed to initialize SDK:",e)}))},on:e=>(t.push(e),()=>{const n=t.indexOf(e);n>-1&&t.splice(n,1)}),identifyUser:()=>{},setLocale:()=>{},setCountry:()=>{},setTheme:()=>{},trackEvent:()=>{},trackScreen:()=>{},startSession:()=>{},resetUser:()=>{},showForm:()=>{},dismissForm:()=>{},addToResponse:()=>{},submitForm:()=>{},emitEvent:()=>{},refineText:()=>Promise.resolve({}),qnaWithAi:()=>Promise.resolve({answer:""}),streamQnaWithAi:()=>Promise.resolve(),uploadFile:()=>Promise.reject(/* @__PURE__ */new Error("[Encatch] uploadFile is not available before SDK initialization")),clearAll:()=>{},addSourceTracking:()=>{}},i=a.filter(e=>"init"!==e);for(const r of i)n[r]=o(e,r);return n}var c=function(){if("undefined"!=typeof window){const e=window._encatch;if(e&&Array.isArray(e._q)){const t=s();return t._q.push(...e._q),Array.isArray(e._eventCallbacks)&&t._eventCallbacks.push(...e._eventCallbacks),e._initialized&&(t._initialized=e._initialized,t._apiKey=e._apiKey,t._config=e._config||{}),window._encatch=t,t}const t=s();return window._encatch=t,t}return s()}();export{c as _encatch,c as default};
2
+ //# sourceMappingURL=encatch.es.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"encatch.es.js","sources":["../src/loader.ts","../src/queue.ts","../src/index.ts"],"sourcesContent":["/**\n * Script Loader Utility\n * \n * Handles the dynamic loading of the remote SDK implementation script.\n * Provides error handling and prevents duplicate script injection.\n */\n\nimport type { EncatchConfig } from './types';\n\n/** Default web host for the remote implementation script */\nconst DEFAULT_WEB_HOST = 'https://app.encatch.com';\n\n/** Fixed path for the SDK script */\nconst SDK_SCRIPT_PATH = '/s/sdk/v1/encatch.js';\n\n/** Script element ID to prevent duplicate injections */\nconst SCRIPT_ID = 'encatch-sdk-script';\n\n/**\n * Returns a cache-bust string that changes at most every 30 minutes (YYMMDDHHmm, mm is 00 or 30).\n * Allows the script to be cached for up to 30 minutes before a new URL triggers a fresh fetch.\n */\nfunction getCacheBustParam(): string {\n const d = new Date();\n const yy = String(d.getUTCFullYear()).slice(-2);\n const mm = String(d.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(d.getUTCDate()).padStart(2, '0');\n const hh = String(d.getUTCHours()).padStart(2, '0');\n const min30 = Math.floor(d.getUTCMinutes() / 30) * 30;\n const minStr = String(min30).padStart(2, '0');\n return `${yy}${mm}${dd}${hh}${minStr}`;\n}\n\n/** Track loading state */\nlet isLoading = false;\nlet isLoaded = false;\nlet loadError: Error | null = null;\n\n/**\n * Load the remote SDK implementation script\n * \n * @param config - Configuration containing optional custom web host\n * @returns Promise that resolves when script loads, rejects on error\n */\nexport function loadRemoteScript(config: EncatchConfig): Promise<void> {\n // Return early if already loaded\n if (isLoaded) {\n return Promise.resolve();\n }\n\n // Return error if previous load failed\n if (loadError) {\n return Promise.reject(loadError);\n }\n\n // Return existing promise if already loading\n if (isLoading) {\n return new Promise((resolve, reject) => {\n const checkInterval = setInterval(() => {\n if (isLoaded) {\n clearInterval(checkInterval);\n resolve();\n } else if (loadError) {\n clearInterval(checkInterval);\n reject(loadError);\n }\n }, 50);\n });\n }\n\n isLoading = true;\n\n return new Promise((resolve, reject) => {\n // Check if script already exists in DOM\n const existingScript = document.getElementById(SCRIPT_ID);\n if (existingScript) {\n isLoading = false;\n isLoaded = true;\n resolve();\n return;\n }\n\n // Determine script URL from webHost (with 30-min cache-bust so script is cached at most 30 min)\n const webHost = config.webHost || DEFAULT_WEB_HOST;\n const scriptUrl = webHost + SDK_SCRIPT_PATH + '?dt=' + getCacheBustParam();\n\n // Create and configure script element\n const script = document.createElement('script');\n script.id = SCRIPT_ID;\n script.src = scriptUrl;\n script.type = 'module';\n script.async = true;\n\n // Handle successful load\n script.onload = () => {\n isLoading = false;\n isLoaded = true;\n resolve();\n };\n\n // Handle load error\n script.onerror = (event) => {\n isLoading = false;\n loadError = new Error(\n `[Encatch] Failed to load SDK from ${scriptUrl}. ` +\n `Please check your network connection and web host configuration.`\n );\n console.error(loadError.message, event);\n reject(loadError);\n };\n\n // Inject script into document head\n const firstScript = document.getElementsByTagName('script')[0];\n if (firstScript && firstScript.parentNode) {\n firstScript.parentNode.insertBefore(script, firstScript);\n } else {\n document.head.appendChild(script);\n }\n });\n}\n\n/**\n * Check if the remote script has been loaded\n */\nexport function isScriptLoaded(): boolean {\n return isLoaded;\n}\n\n/**\n * Reset loader state (useful for testing)\n */\nexport function resetLoaderState(): void {\n isLoading = false;\n isLoaded = false;\n loadError = null;\n}\n\n/**\n * Get the default script URL (includes current 30-min cache-bust param)\n */\nexport function getDefaultScriptUrl(): string {\n return DEFAULT_WEB_HOST + SDK_SCRIPT_PATH + '?dt=' + getCacheBustParam();\n}\n","/**\n * Command Queue Implementation\n * \n * Manages the queue of SDK method calls that occur before the remote\n * implementation script has loaded. Commands are stored as tuples\n * and processed FIFO when the remote script becomes available.\n */\n\nimport type { Command, EncatchSDK } from './types';\n\n/**\n * Process all queued commands by calling the corresponding methods\n * on the SDK instance. This is called by the remote script once loaded.\n * \n * @param sdk - The SDK instance with real implementations\n * @param queue - Array of queued commands to process\n */\nexport function processQueue(sdk: EncatchSDK, queue: Command[]): void {\n while (queue.length > 0) {\n const command = queue.shift();\n if (!command) continue;\n\n const [method, ...args] = command;\n \n // Skip internal properties\n if (method.startsWith('_')) continue;\n\n // Get the method from the SDK\n const fn = sdk[method as keyof EncatchSDK];\n \n if (typeof fn === 'function') {\n try {\n (fn as (...args: unknown[]) => void).apply(sdk, args);\n } catch (error) {\n console.error(`[Encatch] Error processing queued command \"${method}\":`, error);\n }\n } else {\n console.warn(`[Encatch] Unknown method in queue: \"${method}\"`);\n }\n }\n}\n\n/**\n * Creates a stub method that queues calls for later processing\n * \n * @param queue - The command queue array\n * @param methodName - Name of the method being stubbed\n * @returns A function that pushes calls to the queue\n */\nexport function createQueuedMethod(\n queue: Command[],\n methodName: string\n): (...args: unknown[]) => void {\n return function (...args: unknown[]): void {\n queue.push([methodName, ...args]);\n };\n}\n\n/**\n * List of SDK methods that should be queued before initialization\n */\nexport const QUEUED_METHODS = [\n 'init',\n 'identifyUser',\n 'setLocale',\n 'setCountry',\n 'setTheme',\n 'trackEvent',\n 'trackScreen',\n 'startSession',\n 'resetUser',\n 'showForm',\n 'dismissForm',\n 'addToResponse',\n 'submitForm',\n 'emitEvent',\n 'clearAll',\n 'addSourceTracking',\n] as const;\n\nexport type QueuedMethodName = typeof QUEUED_METHODS[number];\n","/**\n * Encatch Web SDK\n * \n * A lightweight, type-safe SDK for integrating Encatch forms and surveys.\n * This module creates the _encatch global object that queues commands\n * until the remote implementation script loads.\n */\n\nimport type {\n EncatchSDK,\n EncatchConfig,\n UserTraits,\n IdentifyOptions,\n EventCallback,\n Command,\n} from './types';\nimport { loadRemoteScript } from './loader';\nimport { createQueuedMethod, QUEUED_METHODS } from './queue';\n\n// Re-export types for consumers\nexport type {\n EncatchSDK,\n EncatchConfig,\n UserTraits,\n IdentifyOptions,\n StartSessionOptions,\n EventType,\n EventCallback,\n EventPayload,\n Theme,\n ResetMode,\n ShowFormOptions,\n ShowFormInterceptorPayload,\n SubmitFormRequest,\n FormDetails,\n QuestionResponse,\n QuestionAnswer,\n RefineTextRequest,\n RefineTextResponse,\n QnaWithAiConversationTurn,\n QnaWithAiRequest,\n QnaWithAiResponse,\n UploadFileRequest,\n UploadFileResponse,\n} from './types';\n\n/**\n * Creates the Encatch SDK stub instance\n * All method calls are queued until setProject() is called and the\n * remote implementation script loads.\n */\nfunction createEncatchStub(): EncatchSDK {\n // Command queue for calls made before remote script loads\n const queue: Command[] = [];\n \n // Event callbacks - all callbacks receive all form events\n const eventCallbacks: EventCallback[] = [];\n\n // Create the SDK object\n const sdk: EncatchSDK = {\n // Internal state\n _q: queue,\n _eventCallbacks: eventCallbacks,\n _initialized: false,\n _apiKey: null,\n _config: {},\n\n // init is special - it triggers script loading\n init(apiKey: string, config?: EncatchConfig): void {\n if (sdk._initialized) {\n console.warn('[Encatch] SDK already initialized. Ignoring init call.');\n return;\n }\n\n sdk._apiKey = apiKey;\n sdk._config = config || {};\n sdk._initialized = true;\n\n // Queue this call for the remote implementation\n queue.push(['init', apiKey, config]);\n\n // Load the remote script\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n loadRemoteScript(sdk._config).catch((error) => {\n console.error('[Encatch] Failed to initialize SDK:', error);\n });\n }\n },\n\n // Event subscription - receives all form events\n on(callback: EventCallback): () => void {\n eventCallbacks.push(callback);\n\n // Return unsubscribe function\n return () => {\n const index = eventCallbacks.indexOf(callback);\n if (index > -1) {\n eventCallbacks.splice(index, 1);\n }\n };\n },\n\n // Stub implementations - will be replaced by remote script\n identifyUser: () => {},\n setLocale: () => {},\n setCountry: () => {},\n setTheme: () => {},\n trackEvent: () => {},\n trackScreen: () => {},\n startSession: () => {},\n resetUser: () => {},\n showForm: () => {},\n dismissForm: () => {},\n addToResponse: () => {},\n submitForm: () => {},\n emitEvent: () => {},\n refineText: () => Promise.resolve({}),\n qnaWithAi: () => Promise.resolve({ answer: '' }),\n uploadFile: () => Promise.reject(new Error('[Encatch] uploadFile is not available before SDK initialization')),\n clearAll: () => {},\n addSourceTracking: () => {},\n };\n\n // Replace stub methods with queue-based versions\n // Skip init (handled specially above) and on (handled locally)\n const methodsToQueue = QUEUED_METHODS.filter(m => m !== 'init');\n \n for (const method of methodsToQueue) {\n // Use type assertion to assign queued methods\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (sdk as any)[method] = createQueuedMethod(queue, method);\n }\n\n return sdk;\n}\n\n/**\n * Initialize the global _encatch object\n * This runs immediately when the script loads\n */\nfunction initGlobal(): EncatchSDK {\n // Check for existing instance (may have been created by snippet)\n if (typeof window !== 'undefined') {\n // If _encatch already exists with a queue, preserve it\n const existing = window._encatch;\n if (existing && Array.isArray(existing._q)) {\n // Merge existing queue into new instance\n const sdk = createEncatchStub();\n sdk._q.push(...existing._q);\n \n // Copy over any existing callbacks\n if (Array.isArray(existing._eventCallbacks)) {\n sdk._eventCallbacks.push(...existing._eventCallbacks);\n }\n \n // Copy initialization state\n if (existing._initialized) {\n sdk._initialized = existing._initialized;\n sdk._apiKey = existing._apiKey;\n sdk._config = existing._config || {};\n }\n \n window._encatch = sdk;\n return sdk;\n }\n\n // Create fresh instance\n const sdk = createEncatchStub();\n window._encatch = sdk;\n return sdk;\n }\n\n // Non-browser environment\n return createEncatchStub();\n}\n\n// Initialize and export\nexport const _encatch = initGlobal();\n\n// Default export for convenience\nexport default _encatch;\n"],"names":["SCRIPT_ID","isLoading","isLoaded","loadError","loadRemoteScript","config","Promise","resolve","reject","checkInterval","setInterval","clearInterval","document","getElementById","scriptUrl","webHost","d","Date","yy","String","getUTCFullYear","slice","mm","getUTCMonth","padStart","dd","getUTCDate","hh","getUTCHours","min30","Math","floor","getUTCMinutes","getCacheBustParam","script","createElement","id","src","type","async","onload","onerror","event","Error","console","error","message","firstScript","getElementsByTagName","parentNode","insertBefore","head","appendChild","createQueuedMethod","queue","methodName","args","push","QUEUED_METHODS","createEncatchStub","eventCallbacks","sdk","_q","_eventCallbacks","_initialized","_apiKey","_config","init","apiKey","warn","window","catch","on","callback","index","indexOf","splice","identifyUser","setLocale","setCountry","setTheme","trackEvent","trackScreen","startSession","resetUser","showForm","dismissForm","addToResponse","submitForm","emitEvent","refineText","qnaWithAi","answer","uploadFile","clearAll","addSourceTracking","methodsToQueue","filter","m","method","_encatch","existing","Array","isArray","initGlobal"],"mappings":"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"}
1
+ {"version":3,"file":"encatch.es.js","names":[],"sources":["../src/loader.ts","../src/queue.ts","../src/index.ts"],"sourcesContent":["/**\n * Script Loader Utility\n * \n * Handles the dynamic loading of the remote SDK implementation script.\n * Provides error handling and prevents duplicate script injection.\n */\n\nimport type { EncatchConfig } from './types';\n\n/** Default web host for the remote implementation script */\nconst DEFAULT_WEB_HOST = 'https://app.encatch.com';\n\n/** Fixed path for the SDK script */\nconst SDK_SCRIPT_PATH = '/s/sdk/v1/encatch.js';\n\n/** Script element ID to prevent duplicate injections */\nconst SCRIPT_ID = 'encatch-sdk-script';\n\n/**\n * Returns a cache-bust string that changes at most every 30 minutes (YYMMDDHHmm, mm is 00 or 30).\n * Allows the script to be cached for up to 30 minutes before a new URL triggers a fresh fetch.\n */\nfunction getCacheBustParam(): string {\n const d = new Date();\n const yy = String(d.getUTCFullYear()).slice(-2);\n const mm = String(d.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(d.getUTCDate()).padStart(2, '0');\n const hh = String(d.getUTCHours()).padStart(2, '0');\n const min30 = Math.floor(d.getUTCMinutes() / 30) * 30;\n const minStr = String(min30).padStart(2, '0');\n return `${yy}${mm}${dd}${hh}${minStr}`;\n}\n\n/** Track loading state */\nlet isLoading = false;\nlet isLoaded = false;\nlet loadError: Error | null = null;\n\n/**\n * Load the remote SDK implementation script\n * \n * @param config - Configuration containing optional custom web host\n * @returns Promise that resolves when script loads, rejects on error\n */\nexport function loadRemoteScript(config: EncatchConfig): Promise<void> {\n // Return early if already loaded\n if (isLoaded) {\n return Promise.resolve();\n }\n\n // Return error if previous load failed\n if (loadError) {\n return Promise.reject(loadError);\n }\n\n // Return existing promise if already loading\n if (isLoading) {\n return new Promise((resolve, reject) => {\n const checkInterval = setInterval(() => {\n if (isLoaded) {\n clearInterval(checkInterval);\n resolve();\n } else if (loadError) {\n clearInterval(checkInterval);\n reject(loadError);\n }\n }, 50);\n });\n }\n\n isLoading = true;\n\n return new Promise((resolve, reject) => {\n // Check if script already exists in DOM\n const existingScript = document.getElementById(SCRIPT_ID);\n if (existingScript) {\n isLoading = false;\n isLoaded = true;\n resolve();\n return;\n }\n\n // Determine script URL from webHost (with 30-min cache-bust so script is cached at most 30 min)\n const webHost = config.webHost || DEFAULT_WEB_HOST;\n const scriptUrl = webHost + SDK_SCRIPT_PATH + '?dt=' + getCacheBustParam();\n\n // Create and configure script element\n const script = document.createElement('script');\n script.id = SCRIPT_ID;\n script.src = scriptUrl;\n script.type = 'module';\n script.async = true;\n\n // Handle successful load\n script.onload = () => {\n isLoading = false;\n isLoaded = true;\n resolve();\n };\n\n // Handle load error\n script.onerror = (event) => {\n isLoading = false;\n loadError = new Error(\n `[Encatch] Failed to load SDK from ${scriptUrl}. ` +\n `Please check your network connection and web host configuration.`\n );\n console.error(loadError.message, event);\n reject(loadError);\n };\n\n // Inject script into document head\n const firstScript = document.getElementsByTagName('script')[0];\n if (firstScript && firstScript.parentNode) {\n firstScript.parentNode.insertBefore(script, firstScript);\n } else {\n document.head.appendChild(script);\n }\n });\n}\n\n/**\n * Check if the remote script has been loaded\n */\nexport function isScriptLoaded(): boolean {\n return isLoaded;\n}\n\n/**\n * Reset loader state (useful for testing)\n */\nexport function resetLoaderState(): void {\n isLoading = false;\n isLoaded = false;\n loadError = null;\n}\n\n/**\n * Get the default script URL (includes current 30-min cache-bust param)\n */\nexport function getDefaultScriptUrl(): string {\n return DEFAULT_WEB_HOST + SDK_SCRIPT_PATH + '?dt=' + getCacheBustParam();\n}\n","/**\n * Command Queue Implementation\n * \n * Manages the queue of SDK method calls that occur before the remote\n * implementation script has loaded. Commands are stored as tuples\n * and processed FIFO when the remote script becomes available.\n */\n\nimport type { Command, EncatchSDK } from './types';\n\n/**\n * Process all queued commands by calling the corresponding methods\n * on the SDK instance. This is called by the remote script once loaded.\n * \n * @param sdk - The SDK instance with real implementations\n * @param queue - Array of queued commands to process\n */\nexport function processQueue(sdk: EncatchSDK, queue: Command[]): void {\n while (queue.length > 0) {\n const command = queue.shift();\n if (!command) continue;\n\n const [method, ...args] = command;\n \n // Skip internal properties\n if (method.startsWith('_')) continue;\n\n // Get the method from the SDK\n const fn = sdk[method as keyof EncatchSDK];\n \n if (typeof fn === 'function') {\n try {\n (fn as (...args: unknown[]) => void).apply(sdk, args);\n } catch (error) {\n console.error(`[Encatch] Error processing queued command \"${method}\":`, error);\n }\n } else {\n console.warn(`[Encatch] Unknown method in queue: \"${method}\"`);\n }\n }\n}\n\n/**\n * Creates a stub method that queues calls for later processing\n * \n * @param queue - The command queue array\n * @param methodName - Name of the method being stubbed\n * @returns A function that pushes calls to the queue\n */\nexport function createQueuedMethod(\n queue: Command[],\n methodName: string\n): (...args: unknown[]) => void {\n return function (...args: unknown[]): void {\n queue.push([methodName, ...args]);\n };\n}\n\n/**\n * List of SDK methods that should be queued before initialization\n */\nexport const QUEUED_METHODS = [\n 'init',\n 'identifyUser',\n 'setLocale',\n 'setCountry',\n 'setTheme',\n 'trackEvent',\n 'trackScreen',\n 'startSession',\n 'resetUser',\n 'showForm',\n 'dismissForm',\n 'addToResponse',\n 'submitForm',\n 'emitEvent',\n 'clearAll',\n 'addSourceTracking',\n] as const;\n\nexport type QueuedMethodName = typeof QUEUED_METHODS[number];\n","/**\n * Encatch Web SDK\n * \n * A lightweight, type-safe SDK for integrating Encatch forms and surveys.\n * This module creates the _encatch global object that queues commands\n * until the remote implementation script loads.\n */\n\nimport type {\n EncatchSDK,\n EncatchConfig,\n UserTraits,\n IdentifyOptions,\n EventCallback,\n Command,\n} from './types';\nimport { loadRemoteScript } from './loader';\nimport { createQueuedMethod, QUEUED_METHODS } from './queue';\n\n// Re-export types for consumers\nexport type {\n EncatchSDK,\n EncatchConfig,\n UserTraits,\n IdentifyOptions,\n StartSessionOptions,\n EventType,\n EventCallback,\n EventPayload,\n Theme,\n ResetMode,\n ShowFormOptions,\n ShowFormInterceptorPayload,\n SubmitFormRequest,\n FormDetails,\n QuestionResponse,\n QuestionAnswer,\n RefineTextRequest,\n RefineTextResponse,\n QnaWithAiConversationTurn,\n QnaWithAiRequest,\n QnaWithAiResponse,\n UploadFileRequest,\n UploadFileResponse,\n} from './types';\n\n/**\n * Creates the Encatch SDK stub instance\n * All method calls are queued until setProject() is called and the\n * remote implementation script loads.\n */\nfunction createEncatchStub(): EncatchSDK {\n // Command queue for calls made before remote script loads\n const queue: Command[] = [];\n \n // Event callbacks - all callbacks receive all form events\n const eventCallbacks: EventCallback[] = [];\n\n // Create the SDK object\n const sdk: EncatchSDK = {\n // Internal state\n _q: queue,\n _eventCallbacks: eventCallbacks,\n _initialized: false,\n _apiKey: null,\n _config: {},\n\n // init is special - it triggers script loading\n init(apiKey: string, config?: EncatchConfig): void {\n if (sdk._initialized) {\n console.warn('[Encatch] SDK already initialized. Ignoring init call.');\n return;\n }\n\n sdk._apiKey = apiKey;\n sdk._config = config || {};\n sdk._initialized = true;\n\n // Queue this call for the remote implementation\n queue.push(['init', apiKey, config]);\n\n // Load the remote script\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n loadRemoteScript(sdk._config).catch((error) => {\n console.error('[Encatch] Failed to initialize SDK:', error);\n });\n }\n },\n\n // Event subscription - receives all form events\n on(callback: EventCallback): () => void {\n eventCallbacks.push(callback);\n\n // Return unsubscribe function\n return () => {\n const index = eventCallbacks.indexOf(callback);\n if (index > -1) {\n eventCallbacks.splice(index, 1);\n }\n };\n },\n\n // Stub implementations - will be replaced by remote script\n identifyUser: () => {},\n setLocale: () => {},\n setCountry: () => {},\n setTheme: () => {},\n trackEvent: () => {},\n trackScreen: () => {},\n startSession: () => {},\n resetUser: () => {},\n showForm: () => {},\n dismissForm: () => {},\n addToResponse: () => {},\n submitForm: () => {},\n emitEvent: () => {},\n refineText: () => Promise.resolve({}),\n qnaWithAi: () => Promise.resolve({ answer: '' }),\n streamQnaWithAi: () => Promise.resolve(),\n uploadFile: () => Promise.reject(new Error('[Encatch] uploadFile is not available before SDK initialization')),\n clearAll: () => {},\n addSourceTracking: () => {},\n };\n\n // Replace stub methods with queue-based versions\n // Skip init (handled specially above) and on (handled locally)\n const methodsToQueue = QUEUED_METHODS.filter(m => m !== 'init');\n \n for (const method of methodsToQueue) {\n // Use type assertion to assign queued methods\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (sdk as any)[method] = createQueuedMethod(queue, method);\n }\n\n return sdk;\n}\n\n/**\n * Initialize the global _encatch object\n * This runs immediately when the script loads\n */\nfunction initGlobal(): EncatchSDK {\n // Check for existing instance (may have been created by snippet)\n if (typeof window !== 'undefined') {\n // If _encatch already exists with a queue, preserve it\n const existing = window._encatch;\n if (existing && Array.isArray(existing._q)) {\n // Merge existing queue into new instance\n const sdk = createEncatchStub();\n sdk._q.push(...existing._q);\n \n // Copy over any existing callbacks\n if (Array.isArray(existing._eventCallbacks)) {\n sdk._eventCallbacks.push(...existing._eventCallbacks);\n }\n \n // Copy initialization state\n if (existing._initialized) {\n sdk._initialized = existing._initialized;\n sdk._apiKey = existing._apiKey;\n sdk._config = existing._config || {};\n }\n \n window._encatch = sdk;\n return sdk;\n }\n\n // Create fresh instance\n const sdk = createEncatchStub();\n window._encatch = sdk;\n return sdk;\n }\n\n // Non-browser environment\n return createEncatchStub();\n}\n\n// Initialize and export\nexport const _encatch = initGlobal();\n\n// Default export for convenience\nexport default _encatch;\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- !function(e){"use strict";const t="encatch-sdk-script";let n=!1,i=!1,r=null;function o(e){return i?Promise.resolve():r?Promise.reject(r):n?new Promise((e,t)=>{const n=setInterval(()=>{i?(clearInterval(n),e()):r&&(clearInterval(n),t(r))},50)}):(n=!0,new Promise((o,a)=>{if(document.getElementById(t))return n=!1,i=!0,void o();const c=(e.webHost||"https://app.encatch.com")+"/s/sdk/v1/encatch.js?dt="+function(){const e=new Date,t=String(e.getUTCFullYear()).slice(-2),n=String(e.getUTCMonth()+1).padStart(2,"0"),i=String(e.getUTCDate()).padStart(2,"0"),r=String(e.getUTCHours()).padStart(2,"0"),o=30*Math.floor(e.getUTCMinutes()/30);return`${t}${n}${i}${r}${String(o).padStart(2,"0")}`}(),s=document.createElement("script");s.id=t,s.src=c,s.type="module",s.async=!0,s.onload=()=>{n=!1,i=!0,o()},s.onerror=e=>{n=!1,r=new Error(`[Encatch] Failed to load SDK from ${c}. Please check your network connection and web host configuration.`),console.error(r.message,e),a(r)};const l=document.getElementsByTagName("script")[0];l&&l.parentNode?l.parentNode.insertBefore(s,l):document.head.appendChild(s)}))}function a(e,t){return function(...n){e.push([t,...n])}}const c=["init","identifyUser","setLocale","setCountry","setTheme","trackEvent","trackScreen","startSession","resetUser","showForm","dismissForm","addToResponse","submitForm","emitEvent","clearAll","addSourceTracking"];function s(){const e=[],t=[],n={_q:e,_eventCallbacks:t,_initialized:!1,_apiKey:null,_config:{},init(t,i){n._initialized?console.warn("[Encatch] SDK already initialized. Ignoring init call."):(n._apiKey=t,n._config=i||{},n._initialized=!0,e.push(["init",t,i]),"undefined"!=typeof window&&"undefined"!=typeof document&&o(n._config).catch(e=>{console.error("[Encatch] Failed to initialize SDK:",e)}))},on:e=>(t.push(e),()=>{const n=t.indexOf(e);n>-1&&t.splice(n,1)}),identifyUser:()=>{},setLocale:()=>{},setCountry:()=>{},setTheme:()=>{},trackEvent:()=>{},trackScreen:()=>{},startSession:()=>{},resetUser:()=>{},showForm:()=>{},dismissForm:()=>{},addToResponse:()=>{},submitForm:()=>{},emitEvent:()=>{},refineText:()=>Promise.resolve({}),qnaWithAi:()=>Promise.resolve({answer:""}),uploadFile:()=>Promise.reject(new Error("[Encatch] uploadFile is not available before SDK initialization")),clearAll:()=>{},addSourceTracking:()=>{}},i=c.filter(e=>"init"!==e);for(const r of i)n[r]=a(e,r);return n}const l=function(){if("undefined"!=typeof window){const e=window._encatch;if(e&&Array.isArray(e._q)){const t=s();return t._q.push(...e._q),Array.isArray(e._eventCallbacks)&&t._eventCallbacks.push(...e._eventCallbacks),e._initialized&&(t._initialized=e._initialized,t._apiKey=e._apiKey,t._config=e._config||{}),window._encatch=t,t}const t=s();return window._encatch=t,t}return s()}();e._encatch=l,e.default=l,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})}(this._encatch=this._encatch||{});
2
- //# sourceMappingURL=encatch.iife.js.map
1
+ !function(e){Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});var t="encatch-sdk-script";var n=!1,i=!1,r=null;function o(e){return i?Promise.resolve():r?Promise.reject(r):n?new Promise((e,t)=>{const n=setInterval(()=>{i?(clearInterval(n),e()):r&&(clearInterval(n),t(r))},50)}):(n=!0,new Promise((o,a)=>{if(document.getElementById(t))return n=!1,i=!0,void o();const s=(e.webHost||"https://app.encatch.com")+"/s/sdk/v1/encatch.js?dt="+function(){const e=new Date,t=String(e.getUTCFullYear()).slice(-2),n=String(e.getUTCMonth()+1).padStart(2,"0"),i=String(e.getUTCDate()).padStart(2,"0"),r=String(e.getUTCHours()).padStart(2,"0"),o=30*Math.floor(e.getUTCMinutes()/30);return`${t}${n}${i}${r}${String(o).padStart(2,"0")}`}(),c=document.createElement("script");c.id=t,c.src=s,c.type="module",c.async=!0,c.onload=()=>{n=!1,i=!0,o()},c.onerror=e=>{n=!1,r=new Error(`[Encatch] Failed to load SDK from ${s}. Please check your network connection and web host configuration.`),console.error(r.message,e),a(r)};const l=document.getElementsByTagName("script")[0];l&&l.parentNode?l.parentNode.insertBefore(c,l):document.head.appendChild(c)}))}function a(e,t){return function(...n){e.push([t,...n])}}var s=["init","identifyUser","setLocale","setCountry","setTheme","trackEvent","trackScreen","startSession","resetUser","showForm","dismissForm","addToResponse","submitForm","emitEvent","clearAll","addSourceTracking"];function c(){const e=[],t=[],n={_q:e,_eventCallbacks:t,_initialized:!1,_apiKey:null,_config:{},init(t,i){n._initialized?console.warn("[Encatch] SDK already initialized. Ignoring init call."):(n._apiKey=t,n._config=i||{},n._initialized=!0,e.push(["init",t,i]),"undefined"!=typeof window&&"undefined"!=typeof document&&o(n._config).catch(e=>{console.error("[Encatch] Failed to initialize SDK:",e)}))},on:e=>(t.push(e),()=>{const n=t.indexOf(e);n>-1&&t.splice(n,1)}),identifyUser:()=>{},setLocale:()=>{},setCountry:()=>{},setTheme:()=>{},trackEvent:()=>{},trackScreen:()=>{},startSession:()=>{},resetUser:()=>{},showForm:()=>{},dismissForm:()=>{},addToResponse:()=>{},submitForm:()=>{},emitEvent:()=>{},refineText:()=>Promise.resolve({}),qnaWithAi:()=>Promise.resolve({answer:""}),streamQnaWithAi:()=>Promise.resolve(),uploadFile:()=>Promise.reject(new Error("[Encatch] uploadFile is not available before SDK initialization")),clearAll:()=>{},addSourceTracking:()=>{}},i=s.filter(e=>"init"!==e);for(const r of i)n[r]=a(e,r);return n}var l=function(){if("undefined"!=typeof window){const e=window._encatch;if(e&&Array.isArray(e._q)){const t=c();return t._q.push(...e._q),Array.isArray(e._eventCallbacks)&&t._eventCallbacks.push(...e._eventCallbacks),e._initialized&&(t._initialized=e._initialized,t._apiKey=e._apiKey,t._config=e._config||{}),window._encatch=t,t}const t=c();return window._encatch=t,t}return c()}();e._encatch=l,e.default=l}(this._encatch=this._encatch||{});
2
+ //# sourceMappingURL=encatch.iife.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"encatch.iife.js","sources":["../src/loader.ts","../src/queue.ts","../src/index.ts"],"sourcesContent":["/**\n * Script Loader Utility\n * \n * Handles the dynamic loading of the remote SDK implementation script.\n * Provides error handling and prevents duplicate script injection.\n */\n\nimport type { EncatchConfig } from './types';\n\n/** Default web host for the remote implementation script */\nconst DEFAULT_WEB_HOST = 'https://app.encatch.com';\n\n/** Fixed path for the SDK script */\nconst SDK_SCRIPT_PATH = '/s/sdk/v1/encatch.js';\n\n/** Script element ID to prevent duplicate injections */\nconst SCRIPT_ID = 'encatch-sdk-script';\n\n/**\n * Returns a cache-bust string that changes at most every 30 minutes (YYMMDDHHmm, mm is 00 or 30).\n * Allows the script to be cached for up to 30 minutes before a new URL triggers a fresh fetch.\n */\nfunction getCacheBustParam(): string {\n const d = new Date();\n const yy = String(d.getUTCFullYear()).slice(-2);\n const mm = String(d.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(d.getUTCDate()).padStart(2, '0');\n const hh = String(d.getUTCHours()).padStart(2, '0');\n const min30 = Math.floor(d.getUTCMinutes() / 30) * 30;\n const minStr = String(min30).padStart(2, '0');\n return `${yy}${mm}${dd}${hh}${minStr}`;\n}\n\n/** Track loading state */\nlet isLoading = false;\nlet isLoaded = false;\nlet loadError: Error | null = null;\n\n/**\n * Load the remote SDK implementation script\n * \n * @param config - Configuration containing optional custom web host\n * @returns Promise that resolves when script loads, rejects on error\n */\nexport function loadRemoteScript(config: EncatchConfig): Promise<void> {\n // Return early if already loaded\n if (isLoaded) {\n return Promise.resolve();\n }\n\n // Return error if previous load failed\n if (loadError) {\n return Promise.reject(loadError);\n }\n\n // Return existing promise if already loading\n if (isLoading) {\n return new Promise((resolve, reject) => {\n const checkInterval = setInterval(() => {\n if (isLoaded) {\n clearInterval(checkInterval);\n resolve();\n } else if (loadError) {\n clearInterval(checkInterval);\n reject(loadError);\n }\n }, 50);\n });\n }\n\n isLoading = true;\n\n return new Promise((resolve, reject) => {\n // Check if script already exists in DOM\n const existingScript = document.getElementById(SCRIPT_ID);\n if (existingScript) {\n isLoading = false;\n isLoaded = true;\n resolve();\n return;\n }\n\n // Determine script URL from webHost (with 30-min cache-bust so script is cached at most 30 min)\n const webHost = config.webHost || DEFAULT_WEB_HOST;\n const scriptUrl = webHost + SDK_SCRIPT_PATH + '?dt=' + getCacheBustParam();\n\n // Create and configure script element\n const script = document.createElement('script');\n script.id = SCRIPT_ID;\n script.src = scriptUrl;\n script.type = 'module';\n script.async = true;\n\n // Handle successful load\n script.onload = () => {\n isLoading = false;\n isLoaded = true;\n resolve();\n };\n\n // Handle load error\n script.onerror = (event) => {\n isLoading = false;\n loadError = new Error(\n `[Encatch] Failed to load SDK from ${scriptUrl}. ` +\n `Please check your network connection and web host configuration.`\n );\n console.error(loadError.message, event);\n reject(loadError);\n };\n\n // Inject script into document head\n const firstScript = document.getElementsByTagName('script')[0];\n if (firstScript && firstScript.parentNode) {\n firstScript.parentNode.insertBefore(script, firstScript);\n } else {\n document.head.appendChild(script);\n }\n });\n}\n\n/**\n * Check if the remote script has been loaded\n */\nexport function isScriptLoaded(): boolean {\n return isLoaded;\n}\n\n/**\n * Reset loader state (useful for testing)\n */\nexport function resetLoaderState(): void {\n isLoading = false;\n isLoaded = false;\n loadError = null;\n}\n\n/**\n * Get the default script URL (includes current 30-min cache-bust param)\n */\nexport function getDefaultScriptUrl(): string {\n return DEFAULT_WEB_HOST + SDK_SCRIPT_PATH + '?dt=' + getCacheBustParam();\n}\n","/**\n * Command Queue Implementation\n * \n * Manages the queue of SDK method calls that occur before the remote\n * implementation script has loaded. Commands are stored as tuples\n * and processed FIFO when the remote script becomes available.\n */\n\nimport type { Command, EncatchSDK } from './types';\n\n/**\n * Process all queued commands by calling the corresponding methods\n * on the SDK instance. This is called by the remote script once loaded.\n * \n * @param sdk - The SDK instance with real implementations\n * @param queue - Array of queued commands to process\n */\nexport function processQueue(sdk: EncatchSDK, queue: Command[]): void {\n while (queue.length > 0) {\n const command = queue.shift();\n if (!command) continue;\n\n const [method, ...args] = command;\n \n // Skip internal properties\n if (method.startsWith('_')) continue;\n\n // Get the method from the SDK\n const fn = sdk[method as keyof EncatchSDK];\n \n if (typeof fn === 'function') {\n try {\n (fn as (...args: unknown[]) => void).apply(sdk, args);\n } catch (error) {\n console.error(`[Encatch] Error processing queued command \"${method}\":`, error);\n }\n } else {\n console.warn(`[Encatch] Unknown method in queue: \"${method}\"`);\n }\n }\n}\n\n/**\n * Creates a stub method that queues calls for later processing\n * \n * @param queue - The command queue array\n * @param methodName - Name of the method being stubbed\n * @returns A function that pushes calls to the queue\n */\nexport function createQueuedMethod(\n queue: Command[],\n methodName: string\n): (...args: unknown[]) => void {\n return function (...args: unknown[]): void {\n queue.push([methodName, ...args]);\n };\n}\n\n/**\n * List of SDK methods that should be queued before initialization\n */\nexport const QUEUED_METHODS = [\n 'init',\n 'identifyUser',\n 'setLocale',\n 'setCountry',\n 'setTheme',\n 'trackEvent',\n 'trackScreen',\n 'startSession',\n 'resetUser',\n 'showForm',\n 'dismissForm',\n 'addToResponse',\n 'submitForm',\n 'emitEvent',\n 'clearAll',\n 'addSourceTracking',\n] as const;\n\nexport type QueuedMethodName = typeof QUEUED_METHODS[number];\n","/**\n * Encatch Web SDK\n * \n * A lightweight, type-safe SDK for integrating Encatch forms and surveys.\n * This module creates the _encatch global object that queues commands\n * until the remote implementation script loads.\n */\n\nimport type {\n EncatchSDK,\n EncatchConfig,\n UserTraits,\n IdentifyOptions,\n EventCallback,\n Command,\n} from './types';\nimport { loadRemoteScript } from './loader';\nimport { createQueuedMethod, QUEUED_METHODS } from './queue';\n\n// Re-export types for consumers\nexport type {\n EncatchSDK,\n EncatchConfig,\n UserTraits,\n IdentifyOptions,\n StartSessionOptions,\n EventType,\n EventCallback,\n EventPayload,\n Theme,\n ResetMode,\n ShowFormOptions,\n ShowFormInterceptorPayload,\n SubmitFormRequest,\n FormDetails,\n QuestionResponse,\n QuestionAnswer,\n RefineTextRequest,\n RefineTextResponse,\n QnaWithAiConversationTurn,\n QnaWithAiRequest,\n QnaWithAiResponse,\n UploadFileRequest,\n UploadFileResponse,\n} from './types';\n\n/**\n * Creates the Encatch SDK stub instance\n * All method calls are queued until setProject() is called and the\n * remote implementation script loads.\n */\nfunction createEncatchStub(): EncatchSDK {\n // Command queue for calls made before remote script loads\n const queue: Command[] = [];\n \n // Event callbacks - all callbacks receive all form events\n const eventCallbacks: EventCallback[] = [];\n\n // Create the SDK object\n const sdk: EncatchSDK = {\n // Internal state\n _q: queue,\n _eventCallbacks: eventCallbacks,\n _initialized: false,\n _apiKey: null,\n _config: {},\n\n // init is special - it triggers script loading\n init(apiKey: string, config?: EncatchConfig): void {\n if (sdk._initialized) {\n console.warn('[Encatch] SDK already initialized. Ignoring init call.');\n return;\n }\n\n sdk._apiKey = apiKey;\n sdk._config = config || {};\n sdk._initialized = true;\n\n // Queue this call for the remote implementation\n queue.push(['init', apiKey, config]);\n\n // Load the remote script\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n loadRemoteScript(sdk._config).catch((error) => {\n console.error('[Encatch] Failed to initialize SDK:', error);\n });\n }\n },\n\n // Event subscription - receives all form events\n on(callback: EventCallback): () => void {\n eventCallbacks.push(callback);\n\n // Return unsubscribe function\n return () => {\n const index = eventCallbacks.indexOf(callback);\n if (index > -1) {\n eventCallbacks.splice(index, 1);\n }\n };\n },\n\n // Stub implementations - will be replaced by remote script\n identifyUser: () => {},\n setLocale: () => {},\n setCountry: () => {},\n setTheme: () => {},\n trackEvent: () => {},\n trackScreen: () => {},\n startSession: () => {},\n resetUser: () => {},\n showForm: () => {},\n dismissForm: () => {},\n addToResponse: () => {},\n submitForm: () => {},\n emitEvent: () => {},\n refineText: () => Promise.resolve({}),\n qnaWithAi: () => Promise.resolve({ answer: '' }),\n uploadFile: () => Promise.reject(new Error('[Encatch] uploadFile is not available before SDK initialization')),\n clearAll: () => {},\n addSourceTracking: () => {},\n };\n\n // Replace stub methods with queue-based versions\n // Skip init (handled specially above) and on (handled locally)\n const methodsToQueue = QUEUED_METHODS.filter(m => m !== 'init');\n \n for (const method of methodsToQueue) {\n // Use type assertion to assign queued methods\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (sdk as any)[method] = createQueuedMethod(queue, method);\n }\n\n return sdk;\n}\n\n/**\n * Initialize the global _encatch object\n * This runs immediately when the script loads\n */\nfunction initGlobal(): EncatchSDK {\n // Check for existing instance (may have been created by snippet)\n if (typeof window !== 'undefined') {\n // If _encatch already exists with a queue, preserve it\n const existing = window._encatch;\n if (existing && Array.isArray(existing._q)) {\n // Merge existing queue into new instance\n const sdk = createEncatchStub();\n sdk._q.push(...existing._q);\n \n // Copy over any existing callbacks\n if (Array.isArray(existing._eventCallbacks)) {\n sdk._eventCallbacks.push(...existing._eventCallbacks);\n }\n \n // Copy initialization state\n if (existing._initialized) {\n sdk._initialized = existing._initialized;\n sdk._apiKey = existing._apiKey;\n sdk._config = existing._config || {};\n }\n \n window._encatch = sdk;\n return sdk;\n }\n\n // Create fresh instance\n const sdk = createEncatchStub();\n window._encatch = sdk;\n return sdk;\n }\n\n // Non-browser environment\n return createEncatchStub();\n}\n\n// Initialize and export\nexport const _encatch = initGlobal();\n\n// Default export for convenience\nexport default _encatch;\n"],"names":["SCRIPT_ID","isLoading","isLoaded","loadError","loadRemoteScript","config","Promise","resolve","reject","checkInterval","setInterval","clearInterval","document","getElementById","scriptUrl","webHost","d","Date","yy","String","getUTCFullYear","slice","mm","getUTCMonth","padStart","dd","getUTCDate","hh","getUTCHours","min30","Math","floor","getUTCMinutes","getCacheBustParam","script","createElement","id","src","type","async","onload","onerror","event","Error","console","error","message","firstScript","getElementsByTagName","parentNode","insertBefore","head","appendChild","createQueuedMethod","queue","methodName","args","push","QUEUED_METHODS","createEncatchStub","eventCallbacks","sdk","_q","_eventCallbacks","_initialized","_apiKey","_config","init","apiKey","warn","window","catch","on","callback","index","indexOf","splice","identifyUser","setLocale","setCountry","setTheme","trackEvent","trackScreen","startSession","resetUser","showForm","dismissForm","addToResponse","submitForm","emitEvent","refineText","qnaWithAi","answer","uploadFile","clearAll","addSourceTracking","methodsToQueue","filter","m","method","_encatch","existing","Array","isArray","initGlobal"],"mappings":"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"}
1
+ {"version":3,"file":"encatch.iife.js","names":[],"sources":["../src/loader.ts","../src/queue.ts","../src/index.ts"],"sourcesContent":["/**\n * Script Loader Utility\n * \n * Handles the dynamic loading of the remote SDK implementation script.\n * Provides error handling and prevents duplicate script injection.\n */\n\nimport type { EncatchConfig } from './types';\n\n/** Default web host for the remote implementation script */\nconst DEFAULT_WEB_HOST = 'https://app.encatch.com';\n\n/** Fixed path for the SDK script */\nconst SDK_SCRIPT_PATH = '/s/sdk/v1/encatch.js';\n\n/** Script element ID to prevent duplicate injections */\nconst SCRIPT_ID = 'encatch-sdk-script';\n\n/**\n * Returns a cache-bust string that changes at most every 30 minutes (YYMMDDHHmm, mm is 00 or 30).\n * Allows the script to be cached for up to 30 minutes before a new URL triggers a fresh fetch.\n */\nfunction getCacheBustParam(): string {\n const d = new Date();\n const yy = String(d.getUTCFullYear()).slice(-2);\n const mm = String(d.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(d.getUTCDate()).padStart(2, '0');\n const hh = String(d.getUTCHours()).padStart(2, '0');\n const min30 = Math.floor(d.getUTCMinutes() / 30) * 30;\n const minStr = String(min30).padStart(2, '0');\n return `${yy}${mm}${dd}${hh}${minStr}`;\n}\n\n/** Track loading state */\nlet isLoading = false;\nlet isLoaded = false;\nlet loadError: Error | null = null;\n\n/**\n * Load the remote SDK implementation script\n * \n * @param config - Configuration containing optional custom web host\n * @returns Promise that resolves when script loads, rejects on error\n */\nexport function loadRemoteScript(config: EncatchConfig): Promise<void> {\n // Return early if already loaded\n if (isLoaded) {\n return Promise.resolve();\n }\n\n // Return error if previous load failed\n if (loadError) {\n return Promise.reject(loadError);\n }\n\n // Return existing promise if already loading\n if (isLoading) {\n return new Promise((resolve, reject) => {\n const checkInterval = setInterval(() => {\n if (isLoaded) {\n clearInterval(checkInterval);\n resolve();\n } else if (loadError) {\n clearInterval(checkInterval);\n reject(loadError);\n }\n }, 50);\n });\n }\n\n isLoading = true;\n\n return new Promise((resolve, reject) => {\n // Check if script already exists in DOM\n const existingScript = document.getElementById(SCRIPT_ID);\n if (existingScript) {\n isLoading = false;\n isLoaded = true;\n resolve();\n return;\n }\n\n // Determine script URL from webHost (with 30-min cache-bust so script is cached at most 30 min)\n const webHost = config.webHost || DEFAULT_WEB_HOST;\n const scriptUrl = webHost + SDK_SCRIPT_PATH + '?dt=' + getCacheBustParam();\n\n // Create and configure script element\n const script = document.createElement('script');\n script.id = SCRIPT_ID;\n script.src = scriptUrl;\n script.type = 'module';\n script.async = true;\n\n // Handle successful load\n script.onload = () => {\n isLoading = false;\n isLoaded = true;\n resolve();\n };\n\n // Handle load error\n script.onerror = (event) => {\n isLoading = false;\n loadError = new Error(\n `[Encatch] Failed to load SDK from ${scriptUrl}. ` +\n `Please check your network connection and web host configuration.`\n );\n console.error(loadError.message, event);\n reject(loadError);\n };\n\n // Inject script into document head\n const firstScript = document.getElementsByTagName('script')[0];\n if (firstScript && firstScript.parentNode) {\n firstScript.parentNode.insertBefore(script, firstScript);\n } else {\n document.head.appendChild(script);\n }\n });\n}\n\n/**\n * Check if the remote script has been loaded\n */\nexport function isScriptLoaded(): boolean {\n return isLoaded;\n}\n\n/**\n * Reset loader state (useful for testing)\n */\nexport function resetLoaderState(): void {\n isLoading = false;\n isLoaded = false;\n loadError = null;\n}\n\n/**\n * Get the default script URL (includes current 30-min cache-bust param)\n */\nexport function getDefaultScriptUrl(): string {\n return DEFAULT_WEB_HOST + SDK_SCRIPT_PATH + '?dt=' + getCacheBustParam();\n}\n","/**\n * Command Queue Implementation\n * \n * Manages the queue of SDK method calls that occur before the remote\n * implementation script has loaded. Commands are stored as tuples\n * and processed FIFO when the remote script becomes available.\n */\n\nimport type { Command, EncatchSDK } from './types';\n\n/**\n * Process all queued commands by calling the corresponding methods\n * on the SDK instance. This is called by the remote script once loaded.\n * \n * @param sdk - The SDK instance with real implementations\n * @param queue - Array of queued commands to process\n */\nexport function processQueue(sdk: EncatchSDK, queue: Command[]): void {\n while (queue.length > 0) {\n const command = queue.shift();\n if (!command) continue;\n\n const [method, ...args] = command;\n \n // Skip internal properties\n if (method.startsWith('_')) continue;\n\n // Get the method from the SDK\n const fn = sdk[method as keyof EncatchSDK];\n \n if (typeof fn === 'function') {\n try {\n (fn as (...args: unknown[]) => void).apply(sdk, args);\n } catch (error) {\n console.error(`[Encatch] Error processing queued command \"${method}\":`, error);\n }\n } else {\n console.warn(`[Encatch] Unknown method in queue: \"${method}\"`);\n }\n }\n}\n\n/**\n * Creates a stub method that queues calls for later processing\n * \n * @param queue - The command queue array\n * @param methodName - Name of the method being stubbed\n * @returns A function that pushes calls to the queue\n */\nexport function createQueuedMethod(\n queue: Command[],\n methodName: string\n): (...args: unknown[]) => void {\n return function (...args: unknown[]): void {\n queue.push([methodName, ...args]);\n };\n}\n\n/**\n * List of SDK methods that should be queued before initialization\n */\nexport const QUEUED_METHODS = [\n 'init',\n 'identifyUser',\n 'setLocale',\n 'setCountry',\n 'setTheme',\n 'trackEvent',\n 'trackScreen',\n 'startSession',\n 'resetUser',\n 'showForm',\n 'dismissForm',\n 'addToResponse',\n 'submitForm',\n 'emitEvent',\n 'clearAll',\n 'addSourceTracking',\n] as const;\n\nexport type QueuedMethodName = typeof QUEUED_METHODS[number];\n","/**\n * Encatch Web SDK\n * \n * A lightweight, type-safe SDK for integrating Encatch forms and surveys.\n * This module creates the _encatch global object that queues commands\n * until the remote implementation script loads.\n */\n\nimport type {\n EncatchSDK,\n EncatchConfig,\n UserTraits,\n IdentifyOptions,\n EventCallback,\n Command,\n} from './types';\nimport { loadRemoteScript } from './loader';\nimport { createQueuedMethod, QUEUED_METHODS } from './queue';\n\n// Re-export types for consumers\nexport type {\n EncatchSDK,\n EncatchConfig,\n UserTraits,\n IdentifyOptions,\n StartSessionOptions,\n EventType,\n EventCallback,\n EventPayload,\n Theme,\n ResetMode,\n ShowFormOptions,\n ShowFormInterceptorPayload,\n SubmitFormRequest,\n FormDetails,\n QuestionResponse,\n QuestionAnswer,\n RefineTextRequest,\n RefineTextResponse,\n QnaWithAiConversationTurn,\n QnaWithAiRequest,\n QnaWithAiResponse,\n UploadFileRequest,\n UploadFileResponse,\n} from './types';\n\n/**\n * Creates the Encatch SDK stub instance\n * All method calls are queued until setProject() is called and the\n * remote implementation script loads.\n */\nfunction createEncatchStub(): EncatchSDK {\n // Command queue for calls made before remote script loads\n const queue: Command[] = [];\n \n // Event callbacks - all callbacks receive all form events\n const eventCallbacks: EventCallback[] = [];\n\n // Create the SDK object\n const sdk: EncatchSDK = {\n // Internal state\n _q: queue,\n _eventCallbacks: eventCallbacks,\n _initialized: false,\n _apiKey: null,\n _config: {},\n\n // init is special - it triggers script loading\n init(apiKey: string, config?: EncatchConfig): void {\n if (sdk._initialized) {\n console.warn('[Encatch] SDK already initialized. Ignoring init call.');\n return;\n }\n\n sdk._apiKey = apiKey;\n sdk._config = config || {};\n sdk._initialized = true;\n\n // Queue this call for the remote implementation\n queue.push(['init', apiKey, config]);\n\n // Load the remote script\n if (typeof window !== 'undefined' && typeof document !== 'undefined') {\n loadRemoteScript(sdk._config).catch((error) => {\n console.error('[Encatch] Failed to initialize SDK:', error);\n });\n }\n },\n\n // Event subscription - receives all form events\n on(callback: EventCallback): () => void {\n eventCallbacks.push(callback);\n\n // Return unsubscribe function\n return () => {\n const index = eventCallbacks.indexOf(callback);\n if (index > -1) {\n eventCallbacks.splice(index, 1);\n }\n };\n },\n\n // Stub implementations - will be replaced by remote script\n identifyUser: () => {},\n setLocale: () => {},\n setCountry: () => {},\n setTheme: () => {},\n trackEvent: () => {},\n trackScreen: () => {},\n startSession: () => {},\n resetUser: () => {},\n showForm: () => {},\n dismissForm: () => {},\n addToResponse: () => {},\n submitForm: () => {},\n emitEvent: () => {},\n refineText: () => Promise.resolve({}),\n qnaWithAi: () => Promise.resolve({ answer: '' }),\n streamQnaWithAi: () => Promise.resolve(),\n uploadFile: () => Promise.reject(new Error('[Encatch] uploadFile is not available before SDK initialization')),\n clearAll: () => {},\n addSourceTracking: () => {},\n };\n\n // Replace stub methods with queue-based versions\n // Skip init (handled specially above) and on (handled locally)\n const methodsToQueue = QUEUED_METHODS.filter(m => m !== 'init');\n \n for (const method of methodsToQueue) {\n // Use type assertion to assign queued methods\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (sdk as any)[method] = createQueuedMethod(queue, method);\n }\n\n return sdk;\n}\n\n/**\n * Initialize the global _encatch object\n * This runs immediately when the script loads\n */\nfunction initGlobal(): EncatchSDK {\n // Check for existing instance (may have been created by snippet)\n if (typeof window !== 'undefined') {\n // If _encatch already exists with a queue, preserve it\n const existing = window._encatch;\n if (existing && Array.isArray(existing._q)) {\n // Merge existing queue into new instance\n const sdk = createEncatchStub();\n sdk._q.push(...existing._q);\n \n // Copy over any existing callbacks\n if (Array.isArray(existing._eventCallbacks)) {\n sdk._eventCallbacks.push(...existing._eventCallbacks);\n }\n \n // Copy initialization state\n if (existing._initialized) {\n sdk._initialized = existing._initialized;\n sdk._apiKey = existing._apiKey;\n sdk._config = existing._config || {};\n }\n \n window._encatch = sdk;\n return sdk;\n }\n\n // Create fresh instance\n const sdk = createEncatchStub();\n window._encatch = sdk;\n return sdk;\n }\n\n // Non-browser environment\n return createEncatchStub();\n}\n\n// Initialize and export\nexport const _encatch = initGlobal();\n\n// Default export for convenience\nexport default _encatch;\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { EncatchSDK } from './types';
2
+ export type { EncatchSDK, EncatchConfig, UserTraits, IdentifyOptions, StartSessionOptions, EventType, EventCallback, EventPayload, Theme, ResetMode, ShowFormOptions, ShowFormInterceptorPayload, SubmitFormRequest, FormDetails, QuestionResponse, QuestionAnswer, RefineTextRequest, RefineTextResponse, QnaWithAiConversationTurn, QnaWithAiRequest, QnaWithAiResponse, UploadFileRequest, UploadFileResponse, } from './types';
3
+ export declare const _encatch: EncatchSDK;
4
+ export default _encatch;
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EACV,UAAU,EAMX,MAAM,SAAS,CAAC;AAKjB,YAAY,EACV,UAAU,EACV,aAAa,EACb,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,aAAa,EACb,YAAY,EACZ,KAAK,EACL,SAAS,EACT,eAAe,EACf,0BAA0B,EAC1B,iBAAiB,EACjB,WAAW,EACX,gBAAgB,EAChB,cAAc,EACd,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAsIjB,eAAO,MAAM,QAAQ,YAAe,CAAC;AAGrC,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { EncatchConfig } from './types';
2
+ /**
3
+ * Load the remote SDK implementation script
4
+ *
5
+ * @param config - Configuration containing optional custom web host
6
+ * @returns Promise that resolves when script loads, rejects on error
7
+ */
8
+ export declare function loadRemoteScript(config: EncatchConfig): Promise<void>;
9
+ /**
10
+ * Check if the remote script has been loaded
11
+ */
12
+ export declare function isScriptLoaded(): boolean;
13
+ /**
14
+ * Reset loader state (useful for testing)
15
+ */
16
+ export declare function resetLoaderState(): void;
17
+ /**
18
+ * Get the default script URL (includes current 30-min cache-bust param)
19
+ */
20
+ export declare function getDefaultScriptUrl(): string;
21
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/loader.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AA+B7C;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CA2ErE;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAExC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
@@ -0,0 +1,23 @@
1
+ import { Command, EncatchSDK } from './types';
2
+ /**
3
+ * Process all queued commands by calling the corresponding methods
4
+ * on the SDK instance. This is called by the remote script once loaded.
5
+ *
6
+ * @param sdk - The SDK instance with real implementations
7
+ * @param queue - Array of queued commands to process
8
+ */
9
+ export declare function processQueue(sdk: EncatchSDK, queue: Command[]): void;
10
+ /**
11
+ * Creates a stub method that queues calls for later processing
12
+ *
13
+ * @param queue - The command queue array
14
+ * @param methodName - Name of the method being stubbed
15
+ * @returns A function that pushes calls to the queue
16
+ */
17
+ export declare function createQueuedMethod(queue: Command[], methodName: string): (...args: unknown[]) => void;
18
+ /**
19
+ * List of SDK methods that should be queued before initialization
20
+ */
21
+ export declare const QUEUED_METHODS: readonly ["init", "identifyUser", "setLocale", "setCountry", "setTheme", "trackEvent", "trackScreen", "startSession", "resetUser", "showForm", "dismissForm", "addToResponse", "submitForm", "emitEvent", "clearAll", "addSourceTracking"];
22
+ export type QueuedMethodName = typeof QUEUED_METHODS[number];
23
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/queue.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEnD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,IAAI,CAuBpE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EAAE,EAChB,UAAU,EAAE,MAAM,GACjB,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAI9B;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,4OAiBjB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC"}
@@ -1,450 +1,443 @@
1
- /**
2
- * Internal command tuple type for the queue
3
- */
4
- declare type Command = [string, ...unknown[]];
5
-
6
- /**
7
- * Context values that can be attached to a form submission.
8
- * Date values are automatically serialized to ISO strings before being sent.
9
- */
10
- declare type ContextValue = string | number | Date | boolean;
11
-
12
- declare const _encatch: EncatchSDK;
13
- export { _encatch }
14
- export default _encatch;
15
-
16
- /**
17
- * Configuration options for the SDK
18
- */
19
- export declare interface EncatchConfig {
20
- /** Override the default web host for loading the SDK script */
21
- webHost?: string;
22
- /** Theme setting - defaults to 'system' */
23
- theme?: Theme;
24
- /** API base URL - defaults to 'https://app.encatch.com' */
25
- apiBaseUrl?: string;
26
- /** When true, displays the form inline at full height without modal overlay */
27
- isFullScreen?: boolean;
28
- /**
29
- * Optional interceptor called before any form is shown (manual or automatic).
30
- * Receives the form configuration payload. If it returns false (or Promise<false>),
31
- * the SDK will not display its built-in iframe form; the app can instead render a
32
- * custom UI and use submitForm / emitEvent / refineText to complete the flow.
33
- * Pending responses from addToResponse() are cleared when false is returned.
34
- */
35
- onBeforeShowForm?: (payload: ShowFormInterceptorPayload) => boolean | Promise<boolean>;
36
- }
37
-
38
- /**
39
- * The Encatch SDK interface
40
- */
41
- export declare interface EncatchSDK {
42
- /**
43
- * Initialize the SDK with an API key
44
- * This triggers the loading of the remote implementation script
45
- * @param apiKey - Your Encatch API key
46
- * @param config - Optional configuration options
47
- */
48
- init(apiKey: string, config?: EncatchConfig): void;
49
- /**
50
- * Identify the current user
51
- * @param userName - User name or unique identifier (e.g. username, email) (required)
52
- * @param traits - Optional user traits with nested operations ($set, $setOnce, $increment, $decrement, $unset)
53
- * @param options - Optional settings like locale, country, and secure signature
54
- */
55
- identifyUser(userName: string, traits?: UserTraits, options?: IdentifyOptions): void;
56
- /**
57
- * Set the user's preferred locale
58
- * @param locale - Comma-separated ISO 639-1 language codes (e.g., 'fr,en,es')
59
- */
60
- setLocale(locale: string): void;
61
- /**
62
- * Set the user's country
63
- * @param country - ISO 3166 country code (e.g., 'US', 'FR')
64
- */
65
- setCountry(country: string): void;
66
- /**
67
- * Set the theme
68
- * @param theme - Theme value ('light', 'dark', or 'system')
69
- */
70
- setTheme(theme: Theme): void;
71
- /**
72
- * Track a custom event
73
- * @param eventName - Name of the event to track
74
- */
75
- trackEvent(eventName: string): void;
76
- /**
77
- * Track a screen view
78
- * @param screenName - Name of the screen to track
79
- */
80
- trackScreen(screenName: string): void;
81
- /**
82
- * Manually start a new session
83
- * Useful after user login to reset session timing
84
- * @param options - Optional flags to skip immediate ping and/or immediate trackScreen
85
- */
86
- startSession(options?: StartSessionOptions): void;
87
- /**
88
- * Reset the current user (logout)
89
- * Reverts the SDK to anonymous mode
90
- */
91
- resetUser(): void;
92
- /**
93
- * Show a specific form by ID
94
- * @param formId - The ID of the form to display
95
- * @param options - Optional settings for form display behavior
96
- */
97
- showForm(formId: string, options?: ShowFormOptions): void;
98
- /**
99
- * Dismiss a form and report to the server
100
- * Closes the iframe if open and calls the dismiss-form endpoint
101
- * @param formConfigurationId - The form configuration ID to dismiss (required for API call)
102
- */
103
- dismissForm(formConfigurationId?: string): void;
104
- /**
105
- * Prepopulate a form response.
106
- * @param questionId - The ID or slug of the question to prepopulate. When a slug
107
- * is provided the form engine resolves it to the matching question ID automatically.
108
- * @param value - The value to set
109
- */
110
- addToResponse(questionId: string, value: unknown): void;
111
- /**
112
- * Manually submit a form to the Encatch API.
113
- * Use this when onBeforeShowForm returns false and you render a custom UI —
114
- * call submitForm once the user completes your custom form.
115
- * @param params - Submission details including formConfigurationId and question responses
116
- */
117
- submitForm(params: SubmitFormRequest): void;
118
- /**
119
- * Emit a form lifecycle event to all on() subscribers.
120
- * Use this when onBeforeShowForm returns false to mirror the events that the
121
- * built-in iframe form would normally fire (e.g. form:show, form:started,
122
- * form:answered, form:submit, form:complete, form:close).
123
- * @param eventType - The event type to emit
124
- * @param payload - Event payload (timestamp is added automatically)
125
- */
126
- emitEvent(eventType: EventType, payload: Omit<EventPayload, 'timestamp'>): void;
127
- /**
128
- * Request AI text refinement for a long-text answer.
129
- * Use this when onBeforeShowForm returns false and your custom UI includes
130
- * an AI-enhance feature.
131
- * @param params - The question ID, form configuration ID, and user text to refine
132
- * @returns Promise resolving to the refined text response
133
- */
134
- refineText(params: RefineTextRequest): Promise<RefineTextResponse>;
135
- /**
136
- * Call the Q&A with AI endpoint for a qna_with_ai question.
137
- * Sends the full conversation history (including the current unanswered turn) and
138
- * returns the AI-generated answer.
139
- * @param params - feedbackConfigurationId, questionId, and full conversation array
140
- * @returns Promise resolving to { answer: string }
141
- */
142
- qnaWithAi(params: QnaWithAiRequest): Promise<QnaWithAiResponse>;
143
- /**
144
- * Upload a file to the Encatch file storage.
145
- * Use this when onBeforeShowForm returns false and your custom UI contains a
146
- * file, image, signature, or media question — call uploadFile for each selected
147
- * file and store the returned fileUrl in your answer payload.
148
- * @param params - feedbackConfigurationId, questionId, file, optional fileName and onProgress
149
- * @returns Promise resolving to { fileUrl: string }
150
- */
151
- uploadFile(params: UploadFileRequest): Promise<UploadFileResponse>;
152
- /**
153
- * Subscribe to all form events
154
- * The callback receives all form events (show, submit, close, complete, error)
155
- * @param callback - Function to call when any form event occurs
156
- * @returns Unsubscribe function
157
- */
158
- on(callback: EventCallback): () => void;
159
- /**
160
- * Clear all SDK state and stored data, reverting to a brand-new visitor state.
161
- * Stops the ping interval and URL change listeners, clears all localStorage and
162
- * IndexedDB data written by the SDK, and resets all in-memory identity state.
163
- * showForm() and submitForm() continue to work after this call (with NIL UUIDs),
164
- * but no tracking fires until startSession() or identifyUser() is called again.
165
- * Use this to implement a "forget me" / consent withdrawal flow.
166
- */
167
- clearAll(): void;
168
- /**
169
- * Merge additional source tracking key-value pairs into the SDK's in-memory
170
- * source tracking store. These values are combined with auto-parsed URL params
171
- * whenever showForm() is called. Values set here take precedence over URL params
172
- * on key collision. Persists in memory for the lifetime of the page session.
173
- * Supported on the web SDK only.
174
- * @param values - Key-value pairs to merge into the source tracking store
175
- */
176
- addSourceTracking(values: Record<string, string>): void;
177
- /** Internal: Command queue for calls made before script loads */
178
- _q: Command[];
179
- /** Internal: Event callbacks */
180
- _eventCallbacks: EventCallback[];
181
- /** Internal: Whether the SDK has been initialized */
182
- _initialized: boolean;
183
- /** Internal: The API key */
184
- _apiKey: string | null;
185
- /** Internal: Configuration */
186
- _config: EncatchConfig;
187
- }
188
-
189
- /**
190
- * Event callback function type
191
- * Receives all form events with the event type and payload
192
- */
193
- export declare type EventCallback = (eventType: EventType, payload: EventPayload) => void;
194
-
195
- /**
196
- * Event payload structure
197
- */
198
- export declare interface EventPayload {
199
- /** The form ID related to the event */
200
- formId?: string;
201
- /** Timestamp of the event */
202
- timestamp: number;
203
- /** Additional event-specific data */
204
- data?: Record<string, unknown>;
205
- }
206
-
207
- /**
208
- * Event types that can be subscribed to
209
- */
210
- export declare type EventType = 'form:show' | 'form:started' | 'form:submit' | 'form:complete' | 'form:close' | 'form:dismissed' | 'form:error' | 'form:section:change' | 'form:answered';
211
-
212
- /**
213
- * Form details for a manual form submission
214
- */
215
- export declare interface FormDetails {
216
- /** The server-issued configuration ID for this form */
217
- formConfigurationId: string;
218
- /** When true, marks this as a partial (mid-journey) submission */
219
- isPartialSubmit?: boolean;
220
- feedbackIdentifier?: string;
221
- responseLanguageCode?: string;
222
- response?: {
223
- questions?: QuestionResponse[];
224
- };
225
- completionTimeInSeconds?: number;
226
- /** Caller-provided metadata attached to this submission (Dates already serialized to ISO strings) */
227
- context?: Record<string, string | number | boolean>;
228
- /** IDs of questions the user actually visited, in order */
229
- visitedQuestionIds?: string[];
230
- }
231
-
232
- /**
233
- * Options for the identifyUser method
234
- */
235
- export declare interface IdentifyOptions {
236
- /** User's preferred locale (ISO 639-1 codes, comma-separated) */
237
- locale?: string;
238
- /** User's country (ISO 3166 country code) */
239
- country?: string;
240
- /** Secure identification options with signature */
241
- secure?: SecureOptions;
242
- }
243
-
244
- /**
245
- * A single turn in a Q&A with AI conversation
246
- */
247
- export declare interface QnaWithAiConversationTurn {
248
- /** The question asked by the respondent */
249
- question: string;
250
- /** The AI's answer; empty string for the current unanswered turn */
251
- answer: string;
252
- }
253
-
254
- /**
255
- * Parameters for the qnaWithAi endpoint
256
- */
257
- export declare interface QnaWithAiRequest {
258
- feedbackConfigurationId: string;
259
- questionId: string;
260
- /** Full conversation including the current unanswered turn as the last entry */
261
- conversation: QnaWithAiConversationTurn[];
262
- }
263
-
264
- /**
265
- * Response from the qnaWithAi endpoint
266
- */
267
- export declare interface QnaWithAiResponse {
268
- answer: string;
269
- }
270
-
271
- /**
272
- * An individual question answer within a form submission
273
- */
274
- export declare interface QuestionAnswer {
275
- nps?: number;
276
- csat?: number;
277
- starRating?: number;
278
- singleChoice?: string;
279
- singleChoiceOther?: string;
280
- multipleChoiceMultiple?: string[];
281
- multipleChoiceMultipleOther?: string;
282
- nestedSelection?: string[];
283
- shortAnswer?: string;
284
- longText?: string;
285
- }
286
-
287
- /**
288
- * A single question response within a form submission
289
- */
290
- export declare interface QuestionResponse {
291
- questionId: string;
292
- type?: string;
293
- answer?: QuestionAnswer;
294
- /** Present on engine-built submits: whether this question was on the respondent's path */
295
- isOnPath?: boolean;
296
- }
297
-
298
- /**
299
- * Parameters for the refineText AI enhancement endpoint
300
- */
301
- export declare interface RefineTextRequest {
302
- questionId: string;
303
- feedbackConfigurationId: string;
304
- userText: string;
305
- }
306
-
307
- /**
308
- * Response from the refineText endpoint
309
- */
310
- export declare interface RefineTextResponse {
311
- message?: string;
312
- refinedText?: string;
313
- status?: number;
314
- error?: string;
315
- code?: string;
316
- }
317
-
318
- /**
319
- * Reset mode for form data when showing a form
320
- * - 'always': Clear form data every time showForm is called (default)
321
- * - 'on-complete': Clear form data only if form was previously completed
322
- * - 'never': Never clear form data (preserve user's previous answers)
323
- */
324
- export declare type ResetMode = 'always' | 'on-complete' | 'never';
325
-
326
- /**
327
- * Secure options for user identification
328
- */
329
- declare interface SecureOptions {
330
- /** User signature (required when secure is set) */
331
- signature: string;
332
- /** Optional datetime in UTC when the signature was generated */
333
- generatedDateTimeinUTC?: string;
334
- }
335
-
336
- /**
337
- * Payload passed to the onBeforeShowForm interceptor.
338
- * Contains the full form configuration returned by the server along with
339
- * context values the SDK resolved at call time.
340
- */
341
- export declare interface ShowFormInterceptorPayload {
342
- /** The form slug or ID that was requested */
343
- formId: string;
344
- /** Raw form configuration returned by the show-form API */
345
- formConfig: Record<string, unknown>;
346
- /** Reset mode in effect for this show call */
347
- resetMode: ResetMode;
348
- /** Whether the form was triggered automatically (server-side) or manually (developer call) */
349
- triggerType: 'automatic' | 'manual';
350
- /** Pre-filled responses staged via addToResponse() */
351
- prefillResponses: Record<string, unknown>;
352
- /** Active locale, if set */
353
- locale?: string;
354
- /** Active theme */
355
- theme?: Theme;
356
- /** Serialized context values (Dates already converted to ISO strings) */
357
- context?: Record<string, string | number | boolean>;
358
- }
359
-
360
- /**
361
- * Options for the showForm method
362
- */
363
- export declare interface ShowFormOptions {
364
- /**
365
- * Controls when form data should be cleared
366
- * @default 'always'
367
- */
368
- reset?: ResetMode;
369
- /**
370
- * Arbitrary key-value pairs attached to the form submission.
371
- * Useful for passing caller-side metadata (e.g. plan tier, feature flag states).
372
- * Date values are automatically serialized to ISO 8601 strings.
373
- */
374
- context?: Record<string, ContextValue>;
375
- }
376
-
377
- /**
378
- * Options for the startSession method
379
- */
380
- export declare interface StartSessionOptions {
381
- /** When true, do not call the immediate ping (30s ping interval still runs) */
382
- skipImmediatePing?: boolean;
383
- /** When true, do not send the initial trackScreen for the current URL (URL change listeners still run) */
384
- skipImmediateTrackScreen?: boolean;
385
- }
386
-
387
- /**
388
- * Parameters for manually submitting a form (used with onBeforeShowForm interceptor)
389
- */
390
- export declare interface SubmitFormRequest {
391
- triggerType?: 'automatic' | 'manual';
392
- formDetails: FormDetails;
393
- }
394
-
395
- /**
396
- * Theme options
397
- */
398
- export declare type Theme = 'light' | 'dark' | 'system';
399
-
400
- /**
401
- * Parameters for the uploadFile method
402
- */
403
- export declare interface UploadFileRequest {
404
- /** The form's server-issued configuration ID */
405
- feedbackConfigurationId: string;
406
- /** The question ID the file belongs to */
407
- questionId: string;
408
- /** The file or blob to upload */
409
- file: File | Blob;
410
- /**
411
- * File name to send to the server (e.g. "signature.png").
412
- * Defaults to "upload" when omitted.
413
- */
414
- fileName?: string;
415
- /**
416
- * Optional progress callback receives upload percentage (0–100).
417
- * Useful for driving a progress bar in custom UIs.
418
- */
419
- onProgress?: (percent: number) => void;
420
- }
421
-
422
- /**
423
- * Response from the uploadFile endpoint
424
- */
425
- export declare interface UploadFileResponse {
426
- /** Permanent URL of the uploaded file */
427
- fileUrl: string;
428
- }
429
-
430
- /**
431
- * Encatch Web SDK Type Definitions
432
- */
433
- /**
434
- * User traits for identifying users
435
- * Supports nested operations: $set, $setOnce, $increment, $decrement, $unset
436
- */
437
- export declare interface UserTraits {
438
- /** Set user attributes (overwrites existing values) */
439
- $set?: Record<string, any>;
440
- /** Set user attributes only if they don't already exist */
441
- $setOnce?: Record<string, any>;
442
- /** Increment numeric user attributes */
443
- $increment?: Record<string, number>;
444
- /** Decrement numeric user attributes */
445
- $decrement?: Record<string, number>;
446
- /** Remove user attributes */
447
- $unset?: string[];
448
- }
449
-
450
- export { }
1
+ /**
2
+ * Encatch Web SDK Type Definitions
3
+ */
4
+ /**
5
+ * User traits for identifying users
6
+ * Supports nested operations: $set, $setOnce, $increment, $decrement, $unset
7
+ */
8
+ export interface UserTraits {
9
+ /** Set user attributes (overwrites existing values) */
10
+ $set?: Record<string, any>;
11
+ /** Set user attributes only if they don't already exist */
12
+ $setOnce?: Record<string, any>;
13
+ /** Increment numeric user attributes */
14
+ $increment?: Record<string, number>;
15
+ /** Decrement numeric user attributes */
16
+ $decrement?: Record<string, number>;
17
+ /** Remove user attributes */
18
+ $unset?: string[];
19
+ }
20
+ /**
21
+ * Secure options for user identification
22
+ */
23
+ export interface SecureOptions {
24
+ /** User signature (required when secure is set) */
25
+ signature: string;
26
+ /** Optional datetime in UTC when the signature was generated */
27
+ generatedDateTimeinUTC?: string;
28
+ }
29
+ /**
30
+ * Options for the identifyUser method
31
+ */
32
+ export interface IdentifyOptions {
33
+ /** User's preferred locale (ISO 639-1 codes, comma-separated) */
34
+ locale?: string;
35
+ /** User's country (ISO 3166 country code) */
36
+ country?: string;
37
+ /** Secure identification options with signature */
38
+ secure?: SecureOptions;
39
+ }
40
+ /**
41
+ * Options for the startSession method
42
+ */
43
+ export interface StartSessionOptions {
44
+ /** When true, do not call the immediate ping (30s ping interval still runs) */
45
+ skipImmediatePing?: boolean;
46
+ /** When true, do not send the initial trackScreen for the current URL (URL change listeners still run) */
47
+ skipImmediateTrackScreen?: boolean;
48
+ }
49
+ /**
50
+ * Theme options
51
+ */
52
+ export type Theme = 'light' | 'dark' | 'system';
53
+ /**
54
+ * Configuration options for the SDK
55
+ */
56
+ export interface EncatchConfig {
57
+ /** Override the default web host for loading the SDK script */
58
+ webHost?: string;
59
+ /** Theme setting - defaults to 'system' */
60
+ theme?: Theme;
61
+ /** API base URL - defaults to 'https://app.encatch.com' */
62
+ apiBaseUrl?: string;
63
+ /** When true, displays the form inline at full height without modal overlay */
64
+ isFullScreen?: boolean;
65
+ /**
66
+ * Optional interceptor called before any form is shown (manual or automatic).
67
+ * Receives the form configuration payload. If it returns false (or Promise<false>),
68
+ * the SDK will not display its built-in iframe form; the app can instead render a
69
+ * custom UI and use submitForm / emitEvent / refineText to complete the flow.
70
+ * Pending responses from addToResponse() are cleared when false is returned.
71
+ */
72
+ onBeforeShowForm?: (payload: ShowFormInterceptorPayload) => boolean | Promise<boolean>;
73
+ }
74
+ /**
75
+ * Payload passed to the onBeforeShowForm interceptor.
76
+ * Contains the full form configuration returned by the server along with
77
+ * context values the SDK resolved at call time.
78
+ */
79
+ export interface ShowFormInterceptorPayload {
80
+ /** The form slug or ID that was requested */
81
+ formId: string;
82
+ /** Raw form configuration returned by the show-form API */
83
+ formConfig: Record<string, unknown>;
84
+ /** Reset mode in effect for this show call */
85
+ resetMode: ResetMode;
86
+ /** Whether the form was triggered automatically (server-side) or manually (developer call) */
87
+ triggerType: 'automatic' | 'manual';
88
+ /** Pre-filled responses staged via addToResponse() */
89
+ prefillResponses: Record<string, unknown>;
90
+ /** Active locale, if set */
91
+ locale?: string;
92
+ /** Active theme */
93
+ theme?: Theme;
94
+ /** Serialized context values (Dates already converted to ISO strings) */
95
+ context?: Record<string, string | number | boolean>;
96
+ }
97
+ /**
98
+ * An individual question answer within a form submission
99
+ */
100
+ export interface QuestionAnswer {
101
+ nps?: number;
102
+ csat?: number;
103
+ /** Star-rating / rating scale answer (schema field: `rating`) */
104
+ rating?: number;
105
+ singleChoice?: string;
106
+ singleChoiceOther?: string;
107
+ multipleChoiceMultiple?: string[];
108
+ /** Free-text "Other" answer for multiple-choice-multiple questions (schema field: `multipleChoiceOther`) */
109
+ multipleChoiceOther?: string;
110
+ nestedSelection?: string[];
111
+ shortAnswer?: string;
112
+ longText?: string;
113
+ }
114
+ /**
115
+ * A single question response within a form submission
116
+ */
117
+ export interface QuestionResponse {
118
+ questionId: string;
119
+ type?: string;
120
+ answer?: QuestionAnswer;
121
+ /** Present on engine-built submits: whether this question was on the respondent's path */
122
+ isOnPath?: boolean;
123
+ }
124
+ /**
125
+ * Form details for a manual form submission
126
+ */
127
+ export interface FormDetails {
128
+ /** The server-issued configuration ID for this form */
129
+ formConfigurationId: string;
130
+ /** When true, marks this as a partial (mid-journey) submission */
131
+ isPartialSubmit?: boolean;
132
+ feedbackIdentifier?: string;
133
+ responseLanguageCode?: string;
134
+ response?: {
135
+ questions?: QuestionResponse[];
136
+ };
137
+ completionTimeInSeconds?: number;
138
+ /** Caller-provided metadata attached to this submission (Dates already serialized to ISO strings) */
139
+ context?: Record<string, string | number | boolean>;
140
+ /** IDs of questions the user actually visited, in order */
141
+ visitedQuestionIds?: string[];
142
+ }
143
+ /**
144
+ * Parameters for manually submitting a form (used with onBeforeShowForm interceptor)
145
+ */
146
+ export interface SubmitFormRequest {
147
+ triggerType?: 'automatic' | 'manual';
148
+ formDetails: FormDetails;
149
+ }
150
+ /**
151
+ * Parameters for the refineText AI enhancement endpoint
152
+ */
153
+ export interface RefineTextRequest {
154
+ questionId: string;
155
+ feedbackConfigurationId: string;
156
+ userText: string;
157
+ }
158
+ /**
159
+ * Response from the refineText endpoint
160
+ */
161
+ export interface RefineTextResponse {
162
+ message?: string;
163
+ refinedText?: string;
164
+ status?: number;
165
+ error?: string;
166
+ code?: string;
167
+ }
168
+ /**
169
+ * A single turn in a Q&A with AI conversation
170
+ */
171
+ export interface QnaWithAiConversationTurn {
172
+ /** The question asked by the respondent */
173
+ question: string;
174
+ /** The AI's answer; empty string for the current unanswered turn */
175
+ answer: string;
176
+ }
177
+ /**
178
+ * Parameters for the qnaWithAi endpoint
179
+ */
180
+ export interface QnaWithAiRequest {
181
+ feedbackConfigurationId: string;
182
+ questionId: string;
183
+ /** Full conversation including the current unanswered turn as the last entry */
184
+ conversation: QnaWithAiConversationTurn[];
185
+ }
186
+ /**
187
+ * Response from the qnaWithAi endpoint
188
+ */
189
+ export interface QnaWithAiResponse {
190
+ answer: string;
191
+ }
192
+ /**
193
+ * Parameters for the uploadFile method
194
+ */
195
+ export interface UploadFileRequest {
196
+ /** The form's server-issued configuration ID */
197
+ feedbackConfigurationId: string;
198
+ /** The question ID the file belongs to */
199
+ questionId: string;
200
+ /** The file or blob to upload */
201
+ file: File | Blob;
202
+ /**
203
+ * File name to send to the server (e.g. "signature.png").
204
+ * Defaults to "upload" when omitted.
205
+ */
206
+ fileName?: string;
207
+ /**
208
+ * Optional progress callback receives upload percentage (0–100).
209
+ * Useful for driving a progress bar in custom UIs.
210
+ */
211
+ onProgress?: (percent: number) => void;
212
+ }
213
+ /**
214
+ * Response from the uploadFile endpoint
215
+ */
216
+ export interface UploadFileResponse {
217
+ /** Permanent URL of the uploaded file */
218
+ fileUrl: string;
219
+ }
220
+ /**
221
+ * Reset mode for form data when showing a form
222
+ * - 'always': Clear form data every time showForm is called (default)
223
+ * - 'on-complete': Clear form data only if form was previously completed
224
+ * - 'never': Never clear form data (preserve user's previous answers)
225
+ */
226
+ export type ResetMode = 'always' | 'on-complete' | 'never';
227
+ /**
228
+ * Context values that can be attached to a form submission.
229
+ * Date values are automatically serialized to ISO strings before being sent.
230
+ */
231
+ export type ContextValue = string | number | Date | boolean;
232
+ /**
233
+ * Options for the showForm method
234
+ */
235
+ export interface ShowFormOptions {
236
+ /**
237
+ * Controls when form data should be cleared
238
+ * @default 'always'
239
+ */
240
+ reset?: ResetMode;
241
+ /**
242
+ * Arbitrary key-value pairs attached to the form submission.
243
+ * Useful for passing caller-side metadata (e.g. plan tier, feature flag states).
244
+ * Date values are automatically serialized to ISO 8601 strings.
245
+ */
246
+ context?: Record<string, ContextValue>;
247
+ }
248
+ /**
249
+ * Event types that can be subscribed to
250
+ */
251
+ export type EventType = 'form:show' | 'form:started' | 'form:submit' | 'form:complete' | 'form:close' | 'form:dismissed' | 'form:error' | 'form:section:change' | 'form:answered';
252
+ /**
253
+ * Event callback function type
254
+ * Receives all form events with the event type and payload
255
+ */
256
+ export type EventCallback = (eventType: EventType, payload: EventPayload) => void;
257
+ /**
258
+ * Event payload structure
259
+ */
260
+ export interface EventPayload {
261
+ /** The form ID related to the event */
262
+ formId?: string;
263
+ /** Timestamp of the event */
264
+ timestamp: number;
265
+ /** Additional event-specific data */
266
+ data?: Record<string, unknown>;
267
+ }
268
+ /**
269
+ * Internal command tuple type for the queue
270
+ */
271
+ export type Command = [string, ...unknown[]];
272
+ /**
273
+ * The Encatch SDK interface
274
+ */
275
+ export interface EncatchSDK {
276
+ /**
277
+ * Initialize the SDK with an API key
278
+ * This triggers the loading of the remote implementation script
279
+ * @param apiKey - Your Encatch API key
280
+ * @param config - Optional configuration options
281
+ */
282
+ init(apiKey: string, config?: EncatchConfig): void;
283
+ /**
284
+ * Identify the current user
285
+ * @param userName - User name or unique identifier (e.g. username, email) (required)
286
+ * @param traits - Optional user traits with nested operations ($set, $setOnce, $increment, $decrement, $unset)
287
+ * @param options - Optional settings like locale, country, and secure signature
288
+ */
289
+ identifyUser(userName: string, traits?: UserTraits, options?: IdentifyOptions): void;
290
+ /**
291
+ * Set the user's preferred locale
292
+ * @param locale - Comma-separated ISO 639-1 language codes (e.g., 'fr,en,es')
293
+ */
294
+ setLocale(locale: string): void;
295
+ /**
296
+ * Set the user's country
297
+ * @param country - ISO 3166 country code (e.g., 'US', 'FR')
298
+ */
299
+ setCountry(country: string): void;
300
+ /**
301
+ * Set the theme
302
+ * @param theme - Theme value ('light', 'dark', or 'system')
303
+ */
304
+ setTheme(theme: Theme): void;
305
+ /**
306
+ * Track a custom event
307
+ * @param eventName - Name of the event to track
308
+ */
309
+ trackEvent(eventName: string): void;
310
+ /**
311
+ * Track a screen view
312
+ * @param screenName - Name of the screen to track
313
+ */
314
+ trackScreen(screenName: string): void;
315
+ /**
316
+ * Manually start a new session
317
+ * Useful after user login to reset session timing
318
+ * @param options - Optional flags to skip immediate ping and/or immediate trackScreen
319
+ */
320
+ startSession(options?: StartSessionOptions): void;
321
+ /**
322
+ * Reset the current user (logout)
323
+ * Reverts the SDK to anonymous mode
324
+ */
325
+ resetUser(): void;
326
+ /**
327
+ * Show a specific form by ID
328
+ * @param formId - The ID of the form to display
329
+ * @param options - Optional settings for form display behavior
330
+ */
331
+ showForm(formId: string, options?: ShowFormOptions): void;
332
+ /**
333
+ * Dismiss a form and report to the server
334
+ * Closes the iframe if open and calls the dismiss-form endpoint
335
+ * @param formConfigurationId - The form configuration ID to dismiss (required for API call)
336
+ */
337
+ dismissForm(formConfigurationId?: string): void;
338
+ /**
339
+ * Prepopulate a form response.
340
+ * @param questionId - The ID or slug of the question to prepopulate. When a slug
341
+ * is provided the form engine resolves it to the matching question ID automatically.
342
+ * @param value - The value to set
343
+ */
344
+ addToResponse(questionId: string, value: unknown): void;
345
+ /**
346
+ * Manually submit a form to the Encatch API.
347
+ * Use this when onBeforeShowForm returns false and you render a custom UI —
348
+ * call submitForm once the user completes your custom form.
349
+ * @param params - Submission details including formConfigurationId and question responses
350
+ */
351
+ submitForm(params: SubmitFormRequest): void;
352
+ /**
353
+ * Emit a form lifecycle event to all on() subscribers.
354
+ * Use this when onBeforeShowForm returns false to mirror the events that the
355
+ * built-in iframe form would normally fire (e.g. form:show, form:started,
356
+ * form:answered, form:submit, form:complete, form:close).
357
+ * @param eventType - The event type to emit
358
+ * @param payload - Event payload (timestamp is added automatically)
359
+ */
360
+ emitEvent(eventType: EventType, payload: Omit<EventPayload, 'timestamp'>): void;
361
+ /**
362
+ * Request AI text refinement for a long-text answer.
363
+ * Use this when onBeforeShowForm returns false and your custom UI includes
364
+ * an AI-enhance feature.
365
+ * @param params - The question ID, form configuration ID, and user text to refine
366
+ * @returns Promise resolving to the refined text response
367
+ */
368
+ refineText(params: RefineTextRequest): Promise<RefineTextResponse>;
369
+ /**
370
+ * Call the Q&A with AI endpoint for a qna_with_ai question.
371
+ * Sends the full conversation history (including the current unanswered turn) and
372
+ * returns the AI-generated answer.
373
+ * @param params - feedbackConfigurationId, questionId, and full conversation array
374
+ * @returns Promise resolving to { answer: string }
375
+ */
376
+ qnaWithAi(params: QnaWithAiRequest): Promise<QnaWithAiResponse>;
377
+ /**
378
+ * Streaming variant of qnaWithAi.
379
+ * Calls onChunk for each partial delta as the AI generates the answer,
380
+ * and onDone with the final authoritative answer when complete.
381
+ * @param params - feedbackConfigurationId, questionId, and full conversation array
382
+ * @param callbacks.onChunk - Called for each partial text delta
383
+ * @param callbacks.onDone - Called once with the complete final answer
384
+ * @returns Promise that resolves when the stream is complete
385
+ */
386
+ streamQnaWithAi(params: QnaWithAiRequest, callbacks: {
387
+ onChunk: (delta: string) => void;
388
+ onDone: (answer: string) => void;
389
+ }): Promise<void>;
390
+ /**
391
+ * Upload a file to the Encatch file storage.
392
+ * Use this when onBeforeShowForm returns false and your custom UI contains a
393
+ * file, image, signature, or media question — call uploadFile for each selected
394
+ * file and store the returned fileUrl in your answer payload.
395
+ * @param params - feedbackConfigurationId, questionId, file, optional fileName and onProgress
396
+ * @returns Promise resolving to { fileUrl: string }
397
+ */
398
+ uploadFile(params: UploadFileRequest): Promise<UploadFileResponse>;
399
+ /**
400
+ * Subscribe to all form events
401
+ * The callback receives all form events (show, submit, close, complete, error)
402
+ * @param callback - Function to call when any form event occurs
403
+ * @returns Unsubscribe function
404
+ */
405
+ on(callback: EventCallback): () => void;
406
+ /**
407
+ * Clear all SDK state and stored data, reverting to a brand-new visitor state.
408
+ * Stops the ping interval and URL change listeners, clears all localStorage and
409
+ * IndexedDB data written by the SDK, and resets all in-memory identity state.
410
+ * showForm() and submitForm() continue to work after this call (with NIL UUIDs),
411
+ * but no tracking fires until startSession() or identifyUser() is called again.
412
+ * Use this to implement a "forget me" / consent withdrawal flow.
413
+ */
414
+ clearAll(): void;
415
+ /**
416
+ * Merge additional source tracking key-value pairs into the SDK's in-memory
417
+ * source tracking store. These values are combined with auto-parsed URL params
418
+ * whenever showForm() is called. Values set here take precedence over URL params
419
+ * on key collision. Persists in memory for the lifetime of the page session.
420
+ * Supported on the web SDK only.
421
+ * @param values - Key-value pairs to merge into the source tracking store
422
+ */
423
+ addSourceTracking(values: Record<string, string>): void;
424
+ /** Internal: Command queue for calls made before script loads */
425
+ _q: Command[];
426
+ /** Internal: Event callbacks */
427
+ _eventCallbacks: EventCallback[];
428
+ /** Internal: Whether the SDK has been initialized */
429
+ _initialized: boolean;
430
+ /** Internal: The API key */
431
+ _apiKey: string | null;
432
+ /** Internal: Configuration */
433
+ _config: EncatchConfig;
434
+ }
435
+ /**
436
+ * Global window augmentation for TypeScript
437
+ */
438
+ declare global {
439
+ interface Window {
440
+ _encatch: EncatchSDK;
441
+ }
442
+ }
443
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@encatch/web-sdk",
3
- "version": "1.2.1-beta.0",
3
+ "version": "1.2.1-beta.2",
4
4
  "description": "A lightweight, type-safe JavaScript SDK for integrating Encatch forms and surveys",
5
5
  "type": "module",
6
6
  "main": "dist/encatch.es.js",
7
7
  "module": "dist/encatch.es.js",
8
8
  "jsdelivr": "dist/encatch.iife.js",
9
- "types": "dist/index.d.ts",
9
+ "types": "dist/src/index.d.ts",
10
10
  "exports": {
11
11
  ".": {
12
- "types": "./dist/index.d.ts",
12
+ "types": "./dist/src/index.d.ts",
13
13
  "import": "./dist/encatch.es.js",
14
14
  "require": "./dist/encatch.iife.js"
15
15
  },
@@ -33,10 +33,10 @@
33
33
  "web-sdk"
34
34
  ],
35
35
  "devDependencies": {
36
- "typescript": "^5.9.3",
37
- "vite": "^7.3.1",
38
- "vite-plugin-dts": "^4.5.4",
39
- "terser": "^5.44.1"
36
+ "terser": "^5.47.1",
37
+ "typescript": "^6.0.3",
38
+ "vite": "^8.0.12",
39
+ "vite-plugin-dts": "^5.0.0"
40
40
  },
41
41
  "repository": {
42
42
  "type": "git",