@gengage/assistant-fe 0.2.8 → 0.2.10

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.
Files changed (80) hide show
  1. package/dist/assistant-fe.css +2 -1
  2. package/dist/chat-C1_48HTk.js +4867 -0
  3. package/dist/chat-C1_48HTk.js.map +1 -0
  4. package/dist/chat-DJpVCmRT.cjs +13 -0
  5. package/dist/chat-DJpVCmRT.cjs.map +1 -0
  6. package/dist/chat.cjs +1 -2
  7. package/dist/chat.iife.js +31 -31
  8. package/dist/chat.iife.js.map +1 -1
  9. package/dist/chat.js +2 -15
  10. package/dist/common--5smIEwc.js +390 -0
  11. package/dist/common--5smIEwc.js.map +1 -0
  12. package/dist/common-DTY__1sq.cjs +2 -0
  13. package/dist/common-DTY__1sq.cjs.map +1 -0
  14. package/dist/common.cjs +1 -2
  15. package/dist/common.js +5 -448
  16. package/dist/index.cjs +1 -2
  17. package/dist/index.js +7 -70
  18. package/dist/native-webview-D1v6n8kJ.cjs +2 -0
  19. package/dist/native-webview-D1v6n8kJ.cjs.map +1 -0
  20. package/dist/native-webview-DlY9mxqG.js +521 -0
  21. package/dist/native-webview-DlY9mxqG.js.map +1 -0
  22. package/dist/native.cjs +1 -2
  23. package/dist/native.iife.js +31 -31
  24. package/dist/native.iife.js.map +1 -1
  25. package/dist/native.js +2 -9
  26. package/dist/qna-C-ZboudC.cjs +2 -0
  27. package/dist/qna-C-ZboudC.cjs.map +1 -0
  28. package/dist/qna-CDfFy61x.js +442 -0
  29. package/dist/qna-CDfFy61x.js.map +1 -0
  30. package/dist/qna.cjs +1 -2
  31. package/dist/qna.css +1 -1
  32. package/dist/qna.iife.js +29 -29
  33. package/dist/qna.iife.js.map +1 -1
  34. package/dist/qna.js +2 -463
  35. package/dist/quantity-stepper-BuwCXbPt.cjs +2 -0
  36. package/dist/quantity-stepper-BuwCXbPt.cjs.map +1 -0
  37. package/dist/quantity-stepper-CTEOqVS6.js +74 -0
  38. package/dist/quantity-stepper-CTEOqVS6.js.map +1 -0
  39. package/dist/schemas-BNc2hTff.cjs +86 -0
  40. package/dist/schemas-BNc2hTff.cjs.map +1 -0
  41. package/dist/schemas-ClU0oPbf.js +4625 -0
  42. package/dist/schemas-ClU0oPbf.js.map +1 -0
  43. package/dist/simrel-B2UMdZ9p.cjs +2 -0
  44. package/dist/simrel-B2UMdZ9p.cjs.map +1 -0
  45. package/dist/simrel-BjL12luk.js +657 -0
  46. package/dist/simrel-BjL12luk.js.map +1 -0
  47. package/dist/simrel.cjs +1 -2
  48. package/dist/simrel.css +1 -1
  49. package/dist/simrel.iife.js +29 -29
  50. package/dist/simrel.iife.js.map +1 -1
  51. package/dist/simrel.js +2 -689
  52. package/package.json +13 -13
  53. package/dist/chat.cjs.map +0 -1
  54. package/dist/chat.js.map +0 -1
  55. package/dist/common.cjs.map +0 -1
  56. package/dist/common.js.map +0 -1
  57. package/dist/index-BAQXPosE.cjs +0 -2
  58. package/dist/index-BAQXPosE.cjs.map +0 -1
  59. package/dist/index-CUBMZpGs.js +0 -5111
  60. package/dist/index-CUBMZpGs.js.map +0 -1
  61. package/dist/index-Dco2Aw73.cjs +0 -13
  62. package/dist/index-Dco2Aw73.cjs.map +0 -1
  63. package/dist/index-DvSU2I9u.js +0 -506
  64. package/dist/index-DvSU2I9u.js.map +0 -1
  65. package/dist/index.cjs.map +0 -1
  66. package/dist/index.js.map +0 -1
  67. package/dist/native.cjs.map +0 -1
  68. package/dist/native.js.map +0 -1
  69. package/dist/qna.cjs.map +0 -1
  70. package/dist/qna.js.map +0 -1
  71. package/dist/quantity-stepper-CQWgexMO.cjs +0 -2
  72. package/dist/quantity-stepper-CQWgexMO.cjs.map +0 -1
  73. package/dist/quantity-stepper-CjY_cpgJ.js +0 -80
  74. package/dist/quantity-stepper-CjY_cpgJ.js.map +0 -1
  75. package/dist/schemas-5lXjLjwW.js +0 -4944
  76. package/dist/schemas-5lXjLjwW.js.map +0 -1
  77. package/dist/schemas-DqUVzVDf.cjs +0 -86
  78. package/dist/schemas-DqUVzVDf.cjs.map +0 -1
  79. package/dist/simrel.cjs.map +0 -1
  80. package/dist/simrel.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gengage/assistant-fe",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Source-available frontend widgets for Gengage AI Assistant — chat, Q&A, and similar-products. Backend is SaaS (gengage.ai).",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -97,20 +97,20 @@
97
97
  "prepublishOnly": "npm run typecheck && npm run test && npm run build"
98
98
  },
99
99
  "devDependencies": {
100
- "@playwright/test": "^1.41.0",
101
- "@types/node": "^25.3.1",
102
- "eslint": "^9.39.3",
100
+ "@playwright/test": "^1.58.2",
101
+ "@types/node": "^25.5.0",
102
+ "eslint": "^10.1.0",
103
103
  "eslint-config-prettier": "^10.1.8",
104
104
  "fake-indexeddb": "^6.2.5",
105
- "jsdom": "^28.1.0",
105
+ "jsdom": "^29.0.1",
106
106
  "prettier": "^3.8.1",
107
- "tsx": "^4.7.0",
108
- "typescript": "^5.3.0",
109
- "typescript-eslint": "^8.56.1",
110
- "vite": "^7.3.1",
107
+ "tsx": "^4.21.0",
108
+ "typescript": "^5.9.3",
109
+ "typescript-eslint": "^8.57.2",
110
+ "vite": "^8.0.2",
111
111
  "vite-plugin-dts": "^4.5.4",
112
- "vitepress": "^1.0.0",
113
- "vitest": "^4.0.18"
112
+ "vitepress": "^1.6.4",
113
+ "vitest": "^4.1.1"
114
114
  },
115
115
  "peerDependencies": {
116
116
  "react": ">=18.0.0",
@@ -125,11 +125,11 @@
125
125
  }
126
126
  },
127
127
  "dependencies": {
128
- "@json-render/core": "^0.11.0",
128
+ "@json-render/core": "^0.15.0",
129
129
  "zod": "^4.3.6"
130
130
  },
131
131
  "gengage": {
132
132
  "apiVersion": "1",
133
133
  "backendNote": "UI and client-side logic only. Backend services are proprietary and require a gengage.ai subscription."
134
134
  }
135
- }
135
+ }
package/dist/chat.cjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":""}
package/dist/chat.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"chat.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"common.cjs","sources":["../src/common/analytics.ts","../src/common/theme-utils.ts","../src/common/customization-factories.ts","../src/common/preflight.ts","../src/common/client.ts","../src/common/page-detect.ts"],"sourcesContent":["import { normalizeMiddlewareUrl } from './api-paths.js';\nimport type { AnalyticsAuthMode } from './config-schema.js';\n\nexport interface AnalyticsEnvelope {\n event_name: string;\n event_version: '1';\n timestamp_ms: number;\n account_id: string;\n session_id: string;\n correlation_id: string;\n view_id?: string;\n user_id?: string;\n widget?: 'chat' | 'qna' | 'simrel';\n page_type?: string;\n sku?: string;\n payload: Record<string, unknown>;\n}\n\nexport interface AnalyticsAuthConfig {\n mode?: AnalyticsAuthMode;\n key?: string;\n headerName?: string;\n bodyField?: string;\n}\n\nexport interface AnalyticsClientConfig {\n enabled?: boolean;\n middlewareUrl: string;\n endpoint?: string;\n auth?: AnalyticsAuthConfig;\n fireAndForget?: boolean;\n useBeacon?: boolean;\n keepaliveFetch?: boolean;\n timeoutMs?: number;\n maxRetries?: number;\n batchSize?: number;\n flushIntervalMs?: number;\n}\n\nexport type AnalyticsInput = Omit<AnalyticsEnvelope, 'event_version' | 'timestamp_ms'> &\n Partial<Pick<AnalyticsEnvelope, 'event_version' | 'timestamp_ms'>>;\n\ninterface AnalyticsTransportBody {\n events: AnalyticsEnvelope[];\n [extra: string]: unknown;\n}\n\nconst DEFAULT_ANALYTICS_CONFIG: Required<Omit<AnalyticsClientConfig, 'auth' | 'middlewareUrl'>> = {\n enabled: true,\n endpoint: '/analytics',\n fireAndForget: true,\n useBeacon: true,\n keepaliveFetch: true,\n timeoutMs: 4000,\n maxRetries: 0,\n batchSize: 10,\n flushIntervalMs: 250,\n};\n\nconst DEFAULT_AUTH: Required<AnalyticsAuthConfig> = {\n mode: 'none',\n key: '',\n headerName: 'X-API-Key',\n bodyField: 'api_key',\n};\n\n/**\n * Fire-and-forget analytics client.\n *\n * All transport errors are silently suppressed — the backend analytics\n * endpoint is not yet implemented, so callers must never observe failures.\n */\nexport class AnalyticsClient {\n private readonly config: Required<Omit<AnalyticsClientConfig, 'auth'>> & { auth: Required<AnalyticsAuthConfig> };\n private readonly queue: AnalyticsEnvelope[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly onPageHideBound: () => void;\n\n constructor(config: AnalyticsClientConfig) {\n this.config = {\n ...DEFAULT_ANALYTICS_CONFIG,\n ...config,\n auth: {\n ...DEFAULT_AUTH,\n ...(config.auth ?? {}),\n },\n };\n\n this.onPageHideBound = () => {\n if (this.queue.length === 0) return;\n this.flushAllSync();\n };\n\n if (typeof window !== 'undefined') {\n window.addEventListener('pagehide', this.onPageHideBound);\n }\n }\n\n track(input: AnalyticsInput): void {\n if (!this.config.enabled) return;\n const envelope = normalizeAnalyticsInput(input);\n this.queue.push(envelope);\n\n if (this.queue.length >= this.config.batchSize) {\n this.scheduleImmediateFlush();\n return;\n }\n\n this.scheduleFlush();\n }\n\n flush(): void {\n if (!this.config.enabled || this.queue.length === 0) return;\n\n const batch = this.queue.splice(0, this.config.batchSize);\n const body = this.buildTransportBody(batch);\n const endpoint = resolveAnalyticsEndpoint(this.config.endpoint, this.config.middlewareUrl);\n\n this.send(endpoint, body);\n }\n\n /** Drain the entire queue synchronously (used on page hide). */\n flushAll(): void {\n while (this.queue.length > 0) {\n this.flush();\n }\n }\n\n destroy(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n if (this.queue.length > 0) {\n this.flushAllSync();\n }\n if (typeof window !== 'undefined') {\n window.removeEventListener('pagehide', this.onPageHideBound);\n }\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return;\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n this.flush();\n }, this.config.flushIntervalMs);\n }\n\n private scheduleImmediateFlush(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n\n private buildTransportBody(events: AnalyticsEnvelope[]): AnalyticsTransportBody {\n const body: AnalyticsTransportBody = { events };\n if (this.config.auth.mode === 'body-api-key' && this.config.auth.key) {\n body[this.config.auth.bodyField] = this.config.auth.key;\n }\n return body;\n }\n\n /** Best-effort send — all errors silently suppressed. */\n private send(endpoint: string, body: AnalyticsTransportBody): void {\n try {\n const payload = JSON.stringify(body);\n\n // Prefer sendBeacon (works during page unload, no response needed)\n if (\n this.config.useBeacon &&\n this.config.auth.mode !== 'x-api-key-header' &&\n this.config.auth.mode !== 'bearer-header' &&\n hasSendBeacon()\n ) {\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(endpoint, blob);\n return;\n }\n\n if (typeof fetch === 'undefined') return;\n\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.auth.mode === 'x-api-key-header' && this.config.auth.key) {\n headers[this.config.auth.headerName] = this.config.auth.key;\n }\n if (this.config.auth.mode === 'bearer-header' && this.config.auth.key) {\n headers.Authorization = `Bearer ${this.config.auth.key}`;\n }\n\n // Fire-and-forget: no await, no error handling, keepalive for page unload\n void fetch(endpoint, {\n method: 'POST',\n headers,\n body: payload,\n keepalive: true,\n }).catch(() => {\n // Silently suppress — backend not implemented yet\n });\n } catch {\n // Silently suppress all errors\n }\n }\n\n /** Synchronous flush using sendBeacon only (for page unload). */\n private flushAllSync(): void {\n if (!this.config.enabled) return;\n const endpoint = resolveAnalyticsEndpoint(this.config.endpoint, this.config.middlewareUrl);\n while (this.queue.length > 0) {\n const batch = this.queue.splice(0, this.config.batchSize);\n const body = this.buildTransportBody(batch);\n try {\n const payload = JSON.stringify(body);\n if (hasSendBeacon()) {\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(endpoint, blob);\n }\n } catch {\n // Silently suppress\n }\n }\n }\n}\n\nexport function createAnalyticsClient(config: AnalyticsClientConfig): AnalyticsClient {\n return new AnalyticsClient(config);\n}\n\nfunction normalizeAnalyticsInput(input: AnalyticsInput): AnalyticsEnvelope {\n const envelope: AnalyticsEnvelope = {\n event_name: input.event_name,\n event_version: input.event_version ?? '1',\n timestamp_ms: input.timestamp_ms ?? Date.now(),\n account_id: input.account_id,\n session_id: input.session_id,\n correlation_id: input.correlation_id,\n payload: input.payload,\n };\n\n if (input.view_id !== undefined) envelope.view_id = input.view_id;\n if (input.user_id !== undefined) envelope.user_id = input.user_id;\n if (input.widget !== undefined) envelope.widget = input.widget;\n if (input.page_type !== undefined) envelope.page_type = input.page_type;\n if (input.sku !== undefined) envelope.sku = input.sku;\n\n return envelope;\n}\n\nfunction resolveAnalyticsEndpoint(endpoint: string, middlewareUrl: string): string {\n if (/^https?:\\/\\//i.test(endpoint)) return endpoint;\n const baseUrl = normalizeMiddlewareUrl(middlewareUrl);\n const normalizedEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;\n return `${baseUrl}${normalizedEndpoint}`;\n}\n\nfunction hasSendBeacon(): boolean {\n return typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function';\n}\n","import type { WidgetTheme } from './types.js';\n\n/**\n * Shared baseline tokens used by account customizations.\n *\n * These values come from historical Gengage host defaults and are\n * intentionally conservative so account themes can override only what differs.\n */\nexport const BASE_WIDGET_THEME: WidgetTheme = {\n /* ── Editorial Commerce Framework ────────────────────────────────────── */\n /* Primary: signature red; never use pure black for text — use on_surface */\n primaryColor: '#b7102a',\n primaryForeground: '#ffffff',\n backgroundColor: '#f8f9fa' /* canvas / background */,\n foregroundColor: '#191c1d' /* on_surface — softened contrast */,\n borderRadius: '0.75rem' /* md roundedness */,\n fontFamily: '\"Plus Jakarta Sans\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n fontSize: '14px',\n zIndex: '1000',\n\n '--glov-chatbot-width': '420px',\n '--glov-left-spacing': '260px',\n '--chatbot-padding': '16px',\n '--root-wrapper-background-color': '#f8f9fa' /* background token */,\n '--root-wrapper-border-color': '#edeeef' /* surface-container */,\n\n '--gengage-chat-width': '400px',\n '--gengage-chat-shell-radius': '1rem' /* lg roundedness */,\n '--gengage-chat-header-height': '60px',\n '--gengage-chat-conversation-width': '396px',\n '--gengage-chat-panel-min-width': '320px',\n '--gengage-chat-panel-max-width': '860px',\n '--gengage-chat-input-height': '48px',\n '--gengage-qna-pill-radius': '999px' /* roundedness-full */,\n '--gengage-qna-input-radius': '0.75rem' /* md roundedness */,\n '--gengage-simrel-card-radius': '0.75rem' /* md roundedness */,\n};\n\n/**\n * Merge account overrides on top of the shared base theme.\n *\n * Account customization files should call this helper so shared defaults stay\n * centralized under src/common.\n */\nexport function withBaseTheme(overrides: WidgetTheme): WidgetTheme {\n return { ...BASE_WIDGET_THEME, ...overrides };\n}\n","import type { ChatWidgetConfig } from '../chat/types.js';\nimport type { QNAWidgetConfig } from '../qna/types.js';\nimport type { SimRelWidgetConfig } from '../simrel/types.js';\nimport type { AnalyticsClientConfig } from './analytics.js';\nimport type { WidgetTheme } from './types.js';\n\nexport const DEFAULT_CUSTOMIZATION_LOCALE = 'tr';\n\nexport interface AccountIdentityConfig {\n accountId: string;\n middlewareUrl: string;\n locale?: string;\n}\n\nexport interface AccountIdentity {\n ACCOUNT_ID: string;\n MIDDLEWARE_URL: string;\n LOCALE: string;\n}\n\ninterface BaseAccountWidgetConfigInput {\n accountId: string;\n middlewareUrl: string;\n sessionId: string;\n theme?: WidgetTheme;\n}\n\nexport interface FloatingChatConfigInput extends BaseAccountWidgetConfigInput {\n locale?: string;\n}\n\nexport interface PdpQnaConfigInput extends BaseAccountWidgetConfigInput {\n sku: string;\n mountTarget: QNAWidgetConfig['mountTarget'];\n}\n\nexport interface PdpSimRelConfigInput extends BaseAccountWidgetConfigInput {\n sku: string;\n mountTarget: SimRelWidgetConfig['mountTarget'];\n}\n\ntype FloatingChatConfigOverrides = Omit<\n Partial<ChatWidgetConfig>,\n 'accountId' | 'middlewareUrl' | 'session' | 'variant' | 'theme' | 'locale'\n>;\ntype PdpQnaConfigOverrides = Omit<\n Partial<QNAWidgetConfig>,\n 'accountId' | 'middlewareUrl' | 'session' | 'pageContext' | 'mountTarget' | 'theme'\n>;\ntype SimRelAccountConfig = Omit<SimRelWidgetConfig, 'onAddToCart' | 'onProductNavigate'>;\ntype PdpSimRelConfigOverrides = Omit<\n Partial<SimRelAccountConfig>,\n 'accountId' | 'middlewareUrl' | 'session' | 'sku' | 'mountTarget' | 'theme'\n>;\ntype DefaultAnalyticsConfigOverrides = Omit<AnalyticsClientConfig, 'middlewareUrl'>;\n\n/**\n * Shared account identity factory used by all customization folders.\n * Keeps middleware URL + locale defaults centralized in the SDK layer.\n */\nexport function createAccountIdentity(config: AccountIdentityConfig): AccountIdentity {\n return {\n ACCOUNT_ID: config.accountId,\n MIDDLEWARE_URL: config.middlewareUrl,\n LOCALE: config.locale ?? DEFAULT_CUSTOMIZATION_LOCALE,\n };\n}\n\n/**\n * Shared floating-chat baseline used by account customizations.\n * Account files only pass differences via `overrides`.\n */\nexport function createFloatingChatConfig(\n input: FloatingChatConfigInput,\n overrides: FloatingChatConfigOverrides = {},\n): ChatWidgetConfig {\n const config: ChatWidgetConfig = {\n accountId: input.accountId,\n middlewareUrl: input.middlewareUrl,\n session: { sessionId: input.sessionId },\n variant: 'floating',\n locale: input.locale ?? DEFAULT_CUSTOMIZATION_LOCALE,\n ...overrides,\n };\n if (input.theme !== undefined) {\n config.theme = input.theme;\n }\n return config;\n}\n\n/**\n * Shared PDP QNA baseline used by account customizations.\n */\nexport function createPdpQnaConfig(input: PdpQnaConfigInput, overrides: PdpQnaConfigOverrides = {}): QNAWidgetConfig {\n const config: QNAWidgetConfig = {\n accountId: input.accountId,\n middlewareUrl: input.middlewareUrl,\n session: { sessionId: input.sessionId },\n pageContext: { pageType: 'pdp', sku: input.sku },\n mountTarget: input.mountTarget,\n ...overrides,\n };\n if (input.theme !== undefined) {\n config.theme = input.theme;\n }\n return config;\n}\n\n/**\n * Shared PDP SimRel baseline used by account customizations.\n * Host-level commerce callbacks stay in account init wrappers.\n */\nexport function createPdpSimRelConfig(\n input: PdpSimRelConfigInput,\n overrides: PdpSimRelConfigOverrides = {},\n): SimRelAccountConfig {\n const config: SimRelAccountConfig = {\n accountId: input.accountId,\n middlewareUrl: input.middlewareUrl,\n session: { sessionId: input.sessionId },\n sku: input.sku,\n mountTarget: input.mountTarget,\n ...overrides,\n };\n if (input.theme !== undefined) {\n config.theme = input.theme;\n }\n return config;\n}\n\n/**\n * Shared analytics defaults for account customization wrappers.\n */\nexport function createDefaultAnalyticsConfig(\n middlewareUrl: string,\n overrides: DefaultAnalyticsConfigOverrides = {},\n): AnalyticsClientConfig {\n return {\n enabled: true,\n middlewareUrl,\n endpoint: '/analytics',\n fireAndForget: true,\n useBeacon: true,\n ...overrides,\n };\n}\n","import type { AccountRuntimeConfig } from './config-schema.js';\n\nexport interface PreflightWarning {\n code: string;\n message: string;\n severity: 'warn' | 'error';\n}\n\nexport interface PreflightResult {\n ok: boolean;\n warnings: PreflightWarning[];\n}\n\nfunction isValidSelector(selector: string): boolean {\n try {\n document.querySelector(selector);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function preflightDiagnostics(\n config: AccountRuntimeConfig,\n options?: { skipCspCheck?: boolean },\n): PreflightResult {\n const warnings: PreflightWarning[] = [];\n\n const mounts = config.mounts;\n const mountEntries: Array<[string, string | undefined]> = [\n ['qna', mounts.qna],\n ['simrel', mounts.simrel],\n ['chat', mounts.chat],\n ];\n\n for (const [widget, selector] of mountEntries) {\n if (selector === undefined) continue;\n\n if (!isValidSelector(selector)) {\n warnings.push({\n code: 'INVALID_SELECTOR',\n message: `[gengage preflight] ${widget} mount selector is invalid CSS: \"${selector}\"`,\n severity: 'error',\n });\n continue;\n }\n\n if (!document.querySelector(selector)) {\n warnings.push({\n code: 'MOUNT_NOT_FOUND',\n message: `[gengage preflight] ${widget} mount target not found: \"${selector}\" — widget will skip or wait for DOM`,\n severity: 'warn',\n });\n }\n }\n\n const idempotencyKey = config.gtm.idempotencyKey;\n if ((window as unknown as Record<string, unknown>)[idempotencyKey] !== undefined) {\n warnings.push({\n code: 'DUPLICATE_IDEMPOTENCY',\n message: `[gengage preflight] window[\"${idempotencyKey}\"] already exists — widgets may have already initialized`,\n severity: 'warn',\n });\n }\n\n // CSP connect-src probe: detect if the middleware URL is blocked.\n // Uses a synchronous SecurityPolicyViolationEvent listener to catch CSP blocks.\n if (!options?.skipCspCheck) {\n let cspBlocked = false;\n const cspListener = (e: SecurityPolicyViolationEvent) => {\n if (e.blockedURI && config.middlewareUrl.startsWith(e.blockedURI)) {\n cspBlocked = true;\n }\n };\n document.addEventListener('securitypolicyviolation', cspListener);\n try {\n // A HEAD request with mode 'no-cors' is cheap and triggers CSP if connect-src blocks it.\n void fetch(config.middlewareUrl, { method: 'HEAD', mode: 'no-cors' }).catch(() => {\n /* swallow — we only care about CSP violations, not network errors */\n });\n } catch {\n // fetch itself may throw if CSP blocks it synchronously\n cspBlocked = true;\n }\n // Give the browser a tick to fire the violation event synchronously.\n // If it fired, cspBlocked is already true.\n document.removeEventListener('securitypolicyviolation', cspListener);\n if (cspBlocked) {\n warnings.push({\n code: 'CSP_BLOCKED',\n message: `[gengage preflight] middleware URL may be blocked by Content-Security-Policy: \"${config.middlewareUrl}\". Add it to connect-src.`,\n severity: 'warn',\n });\n }\n }\n\n for (const w of warnings) {\n if (w.severity === 'error') {\n console.error(w.message);\n } else {\n console.warn(w.message);\n }\n }\n\n return {\n ok: warnings.every((w) => w.severity !== 'error'),\n warnings,\n };\n}\n","import type { AccountRuntimeConfig } from './config-schema.js';\nimport { safeParseAccountRuntimeConfig } from './config-schema.js';\nimport { initOverlayWidgets } from './overlay.js';\nimport type { OverlayWidgetsController, OverlayWidgetsOptions } from './overlay.js';\nimport { preflightDiagnostics } from './preflight.js';\nimport type { PageContext } from './types.js';\n\nexport interface HostActions {\n onAddToCart?: (info: { sku: string; quantity?: number; cartCode?: string }) => void;\n onProductNavigate?: (url: string, sku: string, sessionId: string | null) => void;\n onScriptCall?: (params: { name: string; payload?: Record<string, unknown> }) => void;\n}\n\nexport interface GengageClientOptions {\n runtimeConfig: AccountRuntimeConfig | unknown;\n contextResolver?: () => Partial<PageContext>;\n hostActions?: HostActions;\n preflight?: boolean;\n}\n\nfunction parseConfig(raw: AccountRuntimeConfig | unknown): AccountRuntimeConfig {\n const result = safeParseAccountRuntimeConfig(raw);\n if (!result.success) {\n const messages = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n throw new Error(`[gengage] Invalid runtime config: ${messages}`);\n }\n return result.data;\n}\n\nfunction mapConfigToOverlayOptions(\n config: AccountRuntimeConfig,\n hostActions?: HostActions,\n initialContext?: Partial<PageContext>,\n): OverlayWidgetsOptions {\n const options: OverlayWidgetsOptions = {\n accountId: config.accountId,\n middlewareUrl: config.middlewareUrl,\n idempotencyKey: config.gtm.idempotencyKey,\n };\n\n if (config.locale !== undefined) options.locale = config.locale;\n\n if (initialContext !== undefined) {\n options.pageContext = initialContext;\n if (initialContext.sku !== undefined) options.sku = initialContext.sku;\n }\n\n options.chat = {\n enabled: config.widgets.chat.enabled,\n };\n if (config.mounts.chat !== undefined) {\n options.chat.mountTarget = config.mounts.chat;\n }\n\n options.qna = {\n enabled: config.widgets.qna.enabled,\n };\n if (config.mounts.qna !== undefined) {\n options.qna.mountTarget = config.mounts.qna;\n }\n\n options.simrel = {\n enabled: config.widgets.simrel.enabled,\n };\n if (config.mounts.simrel !== undefined) {\n options.simrel.mountTarget = config.mounts.simrel;\n }\n\n if (hostActions?.onAddToCart !== undefined) {\n options.onAddToCart = hostActions.onAddToCart;\n }\n\n if (hostActions?.onProductNavigate !== undefined) {\n options.onProductNavigate = hostActions.onProductNavigate;\n }\n\n if (hostActions?.onScriptCall !== undefined) {\n options.onScriptCall = hostActions.onScriptCall;\n }\n\n return options;\n}\n\nexport async function initGengageClient(options: GengageClientOptions): Promise<OverlayWidgetsController> {\n const config = parseConfig(options.runtimeConfig);\n\n if (options.preflight !== false) {\n const result = preflightDiagnostics(config);\n if (!result.ok) {\n const errors = result.warnings.filter((w) => w.severity === 'error');\n throw new Error(`[gengage] Preflight failed: ${errors.map((e) => e.message).join('; ')}`);\n }\n }\n\n const initialContext = options.contextResolver?.();\n\n const overlayOptions = mapConfigToOverlayOptions(config, options.hostActions, initialContext);\n const controller = await initOverlayWidgets(overlayOptions);\n\n if (options.contextResolver !== undefined) {\n const resolver = options.contextResolver;\n const listener = () => {\n const ctx = resolver();\n void controller.updateContext(ctx);\n };\n window.addEventListener('gengage:context:update', listener);\n\n // Wrap destroy to remove the listener and prevent a memory leak.\n const originalDestroy = controller.destroy.bind(controller);\n controller.destroy = () => {\n window.removeEventListener('gengage:context:update', listener);\n originalDestroy();\n };\n }\n\n return controller;\n}\n","/**\n * URL-based page type detection.\n *\n * Provides auto-detection of page type from URL patterns and DOM signals.\n * Falls back to 'other' when no rule matches.\n */\n\nimport type { PageContext } from './types.js';\n\nexport type DetectablePageType = PageContext['pageType'];\n\nexport interface PageDetectionRule {\n /** Page type to assign when this rule matches. */\n pageType: DetectablePageType;\n /** URL pathname patterns (tested with `new RegExp(pattern)`). */\n urlPatterns?: string[];\n /** If present, page type is detected only when this query param exists. */\n queryParam?: string;\n /** DOM selector — if an element matching this exists, rule matches. */\n selector?: string;\n}\n\n/** Default rules covering common Turkish e-commerce URL patterns. */\nconst DEFAULT_RULES: PageDetectionRule[] = [\n {\n pageType: 'home',\n urlPatterns: ['^/$', '^/index\\\\.html?$', '^/anasayfa$'],\n },\n {\n pageType: 'search',\n urlPatterns: ['/arama', '/search', '/ara\\\\?'],\n queryParam: 'q',\n },\n {\n pageType: 'cart',\n urlPatterns: ['/sepet', '/cart', '/basket', '/sepetim'],\n },\n {\n pageType: 'plp',\n urlPatterns: ['/kategori/', '/category/', '/c/', '/koleksiyon/', '/collection/'],\n },\n {\n pageType: 'pdp',\n urlPatterns: ['/urun/', '/product/', '/p/', '/-p-', '/-pm-'],\n },\n];\n\n/**\n * Detects page type from the current URL and optional DOM signals.\n *\n * @param rules - Custom rules (defaults to common Turkish e-commerce patterns).\n * @param url - URL to analyze (defaults to window.location).\n * @returns Detected page type, or 'other' if no rule matches.\n */\nexport function detectPageType(rules?: PageDetectionRule[], url?: URL): DetectablePageType {\n const loc = url ?? (typeof window !== 'undefined' ? new URL(window.location.href) : null);\n if (!loc) return 'other';\n\n const effectiveRules = rules ?? DEFAULT_RULES;\n const pathname = loc.pathname;\n\n for (const rule of effectiveRules) {\n // Check URL patterns\n if (rule.urlPatterns) {\n const urlMatch = rule.urlPatterns.some((pattern) => {\n try {\n return new RegExp(pattern, 'i').test(pathname);\n } catch {\n return false;\n }\n });\n if (!urlMatch) continue;\n }\n\n // Check query param requirement\n if (rule.queryParam && !loc.searchParams.has(rule.queryParam)) {\n continue;\n }\n\n // Check DOM selector\n if (rule.selector && typeof document !== 'undefined') {\n if (!document.querySelector(rule.selector)) continue;\n }\n\n return rule.pageType;\n }\n\n return 'other';\n}\n\n/**\n * Attempts to extract a product SKU from the URL path.\n * Looks for common patterns like `/p/SKU`, `/urun/SKU`, `/-p-SKU`.\n */\nexport function extractSkuFromUrl(url?: URL): string | undefined {\n const loc = url ?? (typeof window !== 'undefined' ? new URL(window.location.href) : null);\n if (!loc) return undefined;\n\n const pathname = loc.pathname;\n\n // Pattern: /p/SKU or /urun/SKU or /product/SKU\n const segmentMatch = pathname.match(/\\/(?:p|urun|product)\\/([^/?#]+)/i);\n if (segmentMatch?.[1]) return segmentMatch[1];\n\n // Pattern: -p-SKU at end of path (Trendyol style)\n const suffixMatch = pathname.match(/-p-(\\d+)/i);\n if (suffixMatch?.[1]) return suffixMatch[1];\n\n return undefined;\n}\n\n/**\n * Auto-detects page context from URL and DOM signals.\n * Use as a fallback when the host page doesn't set pageContext explicitly.\n */\nexport function autoDetectPageContext(rules?: PageDetectionRule[]): Partial<PageContext> {\n const pageType = detectPageType(rules);\n const result: Partial<PageContext> = { pageType };\n\n if (pageType === 'pdp') {\n const sku = extractSkuFromUrl();\n if (sku) result.sku = sku;\n }\n\n if (typeof window !== 'undefined') {\n result.url = window.location.href;\n }\n\n return result;\n}\n"],"names":["DEFAULT_ANALYTICS_CONFIG","DEFAULT_AUTH","AnalyticsClient","config","input","envelope","normalizeAnalyticsInput","batch","body","endpoint","resolveAnalyticsEndpoint","events","payload","hasSendBeacon","blob","headers","createAnalyticsClient","middlewareUrl","baseUrl","normalizeMiddlewareUrl","normalizedEndpoint","BASE_WIDGET_THEME","withBaseTheme","overrides","DEFAULT_CUSTOMIZATION_LOCALE","createAccountIdentity","createFloatingChatConfig","createPdpQnaConfig","createPdpSimRelConfig","createDefaultAnalyticsConfig","isValidSelector","selector","preflightDiagnostics","options","warnings","mounts","mountEntries","widget","idempotencyKey","cspBlocked","cspListener","e","w","parseConfig","raw","result","safeParseAccountRuntimeConfig","messages","i","mapConfigToOverlayOptions","hostActions","initialContext","initGengageClient","errors","overlayOptions","controller","initOverlayWidgets","resolver","listener","ctx","originalDestroy","DEFAULT_RULES","detectPageType","rules","url","loc","effectiveRules","pathname","rule","pattern","extractSkuFromUrl","segmentMatch","suffixMatch","autoDetectPageContext","pageType","sku"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"common.js","sources":["../src/common/analytics.ts","../src/common/theme-utils.ts","../src/common/customization-factories.ts","../src/common/preflight.ts","../src/common/client.ts","../src/common/page-detect.ts"],"sourcesContent":["import { normalizeMiddlewareUrl } from './api-paths.js';\nimport type { AnalyticsAuthMode } from './config-schema.js';\n\nexport interface AnalyticsEnvelope {\n event_name: string;\n event_version: '1';\n timestamp_ms: number;\n account_id: string;\n session_id: string;\n correlation_id: string;\n view_id?: string;\n user_id?: string;\n widget?: 'chat' | 'qna' | 'simrel';\n page_type?: string;\n sku?: string;\n payload: Record<string, unknown>;\n}\n\nexport interface AnalyticsAuthConfig {\n mode?: AnalyticsAuthMode;\n key?: string;\n headerName?: string;\n bodyField?: string;\n}\n\nexport interface AnalyticsClientConfig {\n enabled?: boolean;\n middlewareUrl: string;\n endpoint?: string;\n auth?: AnalyticsAuthConfig;\n fireAndForget?: boolean;\n useBeacon?: boolean;\n keepaliveFetch?: boolean;\n timeoutMs?: number;\n maxRetries?: number;\n batchSize?: number;\n flushIntervalMs?: number;\n}\n\nexport type AnalyticsInput = Omit<AnalyticsEnvelope, 'event_version' | 'timestamp_ms'> &\n Partial<Pick<AnalyticsEnvelope, 'event_version' | 'timestamp_ms'>>;\n\ninterface AnalyticsTransportBody {\n events: AnalyticsEnvelope[];\n [extra: string]: unknown;\n}\n\nconst DEFAULT_ANALYTICS_CONFIG: Required<Omit<AnalyticsClientConfig, 'auth' | 'middlewareUrl'>> = {\n enabled: true,\n endpoint: '/analytics',\n fireAndForget: true,\n useBeacon: true,\n keepaliveFetch: true,\n timeoutMs: 4000,\n maxRetries: 0,\n batchSize: 10,\n flushIntervalMs: 250,\n};\n\nconst DEFAULT_AUTH: Required<AnalyticsAuthConfig> = {\n mode: 'none',\n key: '',\n headerName: 'X-API-Key',\n bodyField: 'api_key',\n};\n\n/**\n * Fire-and-forget analytics client.\n *\n * All transport errors are silently suppressed — the backend analytics\n * endpoint is not yet implemented, so callers must never observe failures.\n */\nexport class AnalyticsClient {\n private readonly config: Required<Omit<AnalyticsClientConfig, 'auth'>> & { auth: Required<AnalyticsAuthConfig> };\n private readonly queue: AnalyticsEnvelope[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly onPageHideBound: () => void;\n\n constructor(config: AnalyticsClientConfig) {\n this.config = {\n ...DEFAULT_ANALYTICS_CONFIG,\n ...config,\n auth: {\n ...DEFAULT_AUTH,\n ...(config.auth ?? {}),\n },\n };\n\n this.onPageHideBound = () => {\n if (this.queue.length === 0) return;\n this.flushAllSync();\n };\n\n if (typeof window !== 'undefined') {\n window.addEventListener('pagehide', this.onPageHideBound);\n }\n }\n\n track(input: AnalyticsInput): void {\n if (!this.config.enabled) return;\n const envelope = normalizeAnalyticsInput(input);\n this.queue.push(envelope);\n\n if (this.queue.length >= this.config.batchSize) {\n this.scheduleImmediateFlush();\n return;\n }\n\n this.scheduleFlush();\n }\n\n flush(): void {\n if (!this.config.enabled || this.queue.length === 0) return;\n\n const batch = this.queue.splice(0, this.config.batchSize);\n const body = this.buildTransportBody(batch);\n const endpoint = resolveAnalyticsEndpoint(this.config.endpoint, this.config.middlewareUrl);\n\n this.send(endpoint, body);\n }\n\n /** Drain the entire queue synchronously (used on page hide). */\n flushAll(): void {\n while (this.queue.length > 0) {\n this.flush();\n }\n }\n\n destroy(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n if (this.queue.length > 0) {\n this.flushAllSync();\n }\n if (typeof window !== 'undefined') {\n window.removeEventListener('pagehide', this.onPageHideBound);\n }\n }\n\n private scheduleFlush(): void {\n if (this.flushTimer) return;\n this.flushTimer = setTimeout(() => {\n this.flushTimer = null;\n this.flush();\n }, this.config.flushIntervalMs);\n }\n\n private scheduleImmediateFlush(): void {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush();\n }\n\n private buildTransportBody(events: AnalyticsEnvelope[]): AnalyticsTransportBody {\n const body: AnalyticsTransportBody = { events };\n if (this.config.auth.mode === 'body-api-key' && this.config.auth.key) {\n body[this.config.auth.bodyField] = this.config.auth.key;\n }\n return body;\n }\n\n /** Best-effort send — all errors silently suppressed. */\n private send(endpoint: string, body: AnalyticsTransportBody): void {\n try {\n const payload = JSON.stringify(body);\n\n // Prefer sendBeacon (works during page unload, no response needed)\n if (\n this.config.useBeacon &&\n this.config.auth.mode !== 'x-api-key-header' &&\n this.config.auth.mode !== 'bearer-header' &&\n hasSendBeacon()\n ) {\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(endpoint, blob);\n return;\n }\n\n if (typeof fetch === 'undefined') return;\n\n const headers: Record<string, string> = { 'Content-Type': 'application/json' };\n if (this.config.auth.mode === 'x-api-key-header' && this.config.auth.key) {\n headers[this.config.auth.headerName] = this.config.auth.key;\n }\n if (this.config.auth.mode === 'bearer-header' && this.config.auth.key) {\n headers.Authorization = `Bearer ${this.config.auth.key}`;\n }\n\n // Fire-and-forget: no await, no error handling, keepalive for page unload\n void fetch(endpoint, {\n method: 'POST',\n headers,\n body: payload,\n keepalive: true,\n }).catch(() => {\n // Silently suppress — backend not implemented yet\n });\n } catch {\n // Silently suppress all errors\n }\n }\n\n /** Synchronous flush using sendBeacon only (for page unload). */\n private flushAllSync(): void {\n if (!this.config.enabled) return;\n const endpoint = resolveAnalyticsEndpoint(this.config.endpoint, this.config.middlewareUrl);\n while (this.queue.length > 0) {\n const batch = this.queue.splice(0, this.config.batchSize);\n const body = this.buildTransportBody(batch);\n try {\n const payload = JSON.stringify(body);\n if (hasSendBeacon()) {\n const blob = new Blob([payload], { type: 'application/json' });\n navigator.sendBeacon(endpoint, blob);\n }\n } catch {\n // Silently suppress\n }\n }\n }\n}\n\nexport function createAnalyticsClient(config: AnalyticsClientConfig): AnalyticsClient {\n return new AnalyticsClient(config);\n}\n\nfunction normalizeAnalyticsInput(input: AnalyticsInput): AnalyticsEnvelope {\n const envelope: AnalyticsEnvelope = {\n event_name: input.event_name,\n event_version: input.event_version ?? '1',\n timestamp_ms: input.timestamp_ms ?? Date.now(),\n account_id: input.account_id,\n session_id: input.session_id,\n correlation_id: input.correlation_id,\n payload: input.payload,\n };\n\n if (input.view_id !== undefined) envelope.view_id = input.view_id;\n if (input.user_id !== undefined) envelope.user_id = input.user_id;\n if (input.widget !== undefined) envelope.widget = input.widget;\n if (input.page_type !== undefined) envelope.page_type = input.page_type;\n if (input.sku !== undefined) envelope.sku = input.sku;\n\n return envelope;\n}\n\nfunction resolveAnalyticsEndpoint(endpoint: string, middlewareUrl: string): string {\n if (/^https?:\\/\\//i.test(endpoint)) return endpoint;\n const baseUrl = normalizeMiddlewareUrl(middlewareUrl);\n const normalizedEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;\n return `${baseUrl}${normalizedEndpoint}`;\n}\n\nfunction hasSendBeacon(): boolean {\n return typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function';\n}\n","import type { WidgetTheme } from './types.js';\n\n/**\n * Shared baseline tokens used by account customizations.\n *\n * These values come from historical Gengage host defaults and are\n * intentionally conservative so account themes can override only what differs.\n */\nexport const BASE_WIDGET_THEME: WidgetTheme = {\n /* ── Editorial Commerce Framework ────────────────────────────────────── */\n /* Primary: signature red; never use pure black for text — use on_surface */\n primaryColor: '#b7102a',\n primaryForeground: '#ffffff',\n backgroundColor: '#f8f9fa' /* canvas / background */,\n foregroundColor: '#191c1d' /* on_surface — softened contrast */,\n borderRadius: '0.75rem' /* md roundedness */,\n fontFamily: '\"Plus Jakarta Sans\", -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n fontSize: '14px',\n zIndex: '1000',\n\n '--glov-chatbot-width': '420px',\n '--glov-left-spacing': '260px',\n '--chatbot-padding': '16px',\n '--root-wrapper-background-color': '#f8f9fa' /* background token */,\n '--root-wrapper-border-color': '#edeeef' /* surface-container */,\n\n '--gengage-chat-width': '400px',\n '--gengage-chat-shell-radius': '1rem' /* lg roundedness */,\n '--gengage-chat-header-height': '60px',\n '--gengage-chat-conversation-width': '396px',\n '--gengage-chat-panel-min-width': '320px',\n '--gengage-chat-panel-max-width': '860px',\n '--gengage-chat-input-height': '48px',\n '--gengage-qna-pill-radius': '999px' /* roundedness-full */,\n '--gengage-qna-input-radius': '0.75rem' /* md roundedness */,\n '--gengage-simrel-card-radius': '0.75rem' /* md roundedness */,\n};\n\n/**\n * Merge account overrides on top of the shared base theme.\n *\n * Account customization files should call this helper so shared defaults stay\n * centralized under src/common.\n */\nexport function withBaseTheme(overrides: WidgetTheme): WidgetTheme {\n return { ...BASE_WIDGET_THEME, ...overrides };\n}\n","import type { ChatWidgetConfig } from '../chat/types.js';\nimport type { QNAWidgetConfig } from '../qna/types.js';\nimport type { SimRelWidgetConfig } from '../simrel/types.js';\nimport type { AnalyticsClientConfig } from './analytics.js';\nimport type { WidgetTheme } from './types.js';\n\nexport const DEFAULT_CUSTOMIZATION_LOCALE = 'tr';\n\nexport interface AccountIdentityConfig {\n accountId: string;\n middlewareUrl: string;\n locale?: string;\n}\n\nexport interface AccountIdentity {\n ACCOUNT_ID: string;\n MIDDLEWARE_URL: string;\n LOCALE: string;\n}\n\ninterface BaseAccountWidgetConfigInput {\n accountId: string;\n middlewareUrl: string;\n sessionId: string;\n theme?: WidgetTheme;\n}\n\nexport interface FloatingChatConfigInput extends BaseAccountWidgetConfigInput {\n locale?: string;\n}\n\nexport interface PdpQnaConfigInput extends BaseAccountWidgetConfigInput {\n sku: string;\n mountTarget: QNAWidgetConfig['mountTarget'];\n}\n\nexport interface PdpSimRelConfigInput extends BaseAccountWidgetConfigInput {\n sku: string;\n mountTarget: SimRelWidgetConfig['mountTarget'];\n}\n\ntype FloatingChatConfigOverrides = Omit<\n Partial<ChatWidgetConfig>,\n 'accountId' | 'middlewareUrl' | 'session' | 'variant' | 'theme' | 'locale'\n>;\ntype PdpQnaConfigOverrides = Omit<\n Partial<QNAWidgetConfig>,\n 'accountId' | 'middlewareUrl' | 'session' | 'pageContext' | 'mountTarget' | 'theme'\n>;\ntype SimRelAccountConfig = Omit<SimRelWidgetConfig, 'onAddToCart' | 'onProductNavigate'>;\ntype PdpSimRelConfigOverrides = Omit<\n Partial<SimRelAccountConfig>,\n 'accountId' | 'middlewareUrl' | 'session' | 'sku' | 'mountTarget' | 'theme'\n>;\ntype DefaultAnalyticsConfigOverrides = Omit<AnalyticsClientConfig, 'middlewareUrl'>;\n\n/**\n * Shared account identity factory used by all customization folders.\n * Keeps middleware URL + locale defaults centralized in the SDK layer.\n */\nexport function createAccountIdentity(config: AccountIdentityConfig): AccountIdentity {\n return {\n ACCOUNT_ID: config.accountId,\n MIDDLEWARE_URL: config.middlewareUrl,\n LOCALE: config.locale ?? DEFAULT_CUSTOMIZATION_LOCALE,\n };\n}\n\n/**\n * Shared floating-chat baseline used by account customizations.\n * Account files only pass differences via `overrides`.\n */\nexport function createFloatingChatConfig(\n input: FloatingChatConfigInput,\n overrides: FloatingChatConfigOverrides = {},\n): ChatWidgetConfig {\n const config: ChatWidgetConfig = {\n accountId: input.accountId,\n middlewareUrl: input.middlewareUrl,\n session: { sessionId: input.sessionId },\n variant: 'floating',\n locale: input.locale ?? DEFAULT_CUSTOMIZATION_LOCALE,\n ...overrides,\n };\n if (input.theme !== undefined) {\n config.theme = input.theme;\n }\n return config;\n}\n\n/**\n * Shared PDP QNA baseline used by account customizations.\n */\nexport function createPdpQnaConfig(input: PdpQnaConfigInput, overrides: PdpQnaConfigOverrides = {}): QNAWidgetConfig {\n const config: QNAWidgetConfig = {\n accountId: input.accountId,\n middlewareUrl: input.middlewareUrl,\n session: { sessionId: input.sessionId },\n pageContext: { pageType: 'pdp', sku: input.sku },\n mountTarget: input.mountTarget,\n ...overrides,\n };\n if (input.theme !== undefined) {\n config.theme = input.theme;\n }\n return config;\n}\n\n/**\n * Shared PDP SimRel baseline used by account customizations.\n * Host-level commerce callbacks stay in account init wrappers.\n */\nexport function createPdpSimRelConfig(\n input: PdpSimRelConfigInput,\n overrides: PdpSimRelConfigOverrides = {},\n): SimRelAccountConfig {\n const config: SimRelAccountConfig = {\n accountId: input.accountId,\n middlewareUrl: input.middlewareUrl,\n session: { sessionId: input.sessionId },\n sku: input.sku,\n mountTarget: input.mountTarget,\n ...overrides,\n };\n if (input.theme !== undefined) {\n config.theme = input.theme;\n }\n return config;\n}\n\n/**\n * Shared analytics defaults for account customization wrappers.\n */\nexport function createDefaultAnalyticsConfig(\n middlewareUrl: string,\n overrides: DefaultAnalyticsConfigOverrides = {},\n): AnalyticsClientConfig {\n return {\n enabled: true,\n middlewareUrl,\n endpoint: '/analytics',\n fireAndForget: true,\n useBeacon: true,\n ...overrides,\n };\n}\n","import type { AccountRuntimeConfig } from './config-schema.js';\n\nexport interface PreflightWarning {\n code: string;\n message: string;\n severity: 'warn' | 'error';\n}\n\nexport interface PreflightResult {\n ok: boolean;\n warnings: PreflightWarning[];\n}\n\nfunction isValidSelector(selector: string): boolean {\n try {\n document.querySelector(selector);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function preflightDiagnostics(\n config: AccountRuntimeConfig,\n options?: { skipCspCheck?: boolean },\n): PreflightResult {\n const warnings: PreflightWarning[] = [];\n\n const mounts = config.mounts;\n const mountEntries: Array<[string, string | undefined]> = [\n ['qna', mounts.qna],\n ['simrel', mounts.simrel],\n ['chat', mounts.chat],\n ];\n\n for (const [widget, selector] of mountEntries) {\n if (selector === undefined) continue;\n\n if (!isValidSelector(selector)) {\n warnings.push({\n code: 'INVALID_SELECTOR',\n message: `[gengage preflight] ${widget} mount selector is invalid CSS: \"${selector}\"`,\n severity: 'error',\n });\n continue;\n }\n\n if (!document.querySelector(selector)) {\n warnings.push({\n code: 'MOUNT_NOT_FOUND',\n message: `[gengage preflight] ${widget} mount target not found: \"${selector}\" — widget will skip or wait for DOM`,\n severity: 'warn',\n });\n }\n }\n\n const idempotencyKey = config.gtm.idempotencyKey;\n if ((window as unknown as Record<string, unknown>)[idempotencyKey] !== undefined) {\n warnings.push({\n code: 'DUPLICATE_IDEMPOTENCY',\n message: `[gengage preflight] window[\"${idempotencyKey}\"] already exists — widgets may have already initialized`,\n severity: 'warn',\n });\n }\n\n // CSP connect-src probe: detect if the middleware URL is blocked.\n // Uses a synchronous SecurityPolicyViolationEvent listener to catch CSP blocks.\n if (!options?.skipCspCheck) {\n let cspBlocked = false;\n const cspListener = (e: SecurityPolicyViolationEvent) => {\n if (e.blockedURI && config.middlewareUrl.startsWith(e.blockedURI)) {\n cspBlocked = true;\n }\n };\n document.addEventListener('securitypolicyviolation', cspListener);\n try {\n // A HEAD request with mode 'no-cors' is cheap and triggers CSP if connect-src blocks it.\n void fetch(config.middlewareUrl, { method: 'HEAD', mode: 'no-cors' }).catch(() => {\n /* swallow — we only care about CSP violations, not network errors */\n });\n } catch {\n // fetch itself may throw if CSP blocks it synchronously\n cspBlocked = true;\n }\n // Give the browser a tick to fire the violation event synchronously.\n // If it fired, cspBlocked is already true.\n document.removeEventListener('securitypolicyviolation', cspListener);\n if (cspBlocked) {\n warnings.push({\n code: 'CSP_BLOCKED',\n message: `[gengage preflight] middleware URL may be blocked by Content-Security-Policy: \"${config.middlewareUrl}\". Add it to connect-src.`,\n severity: 'warn',\n });\n }\n }\n\n for (const w of warnings) {\n if (w.severity === 'error') {\n console.error(w.message);\n } else {\n console.warn(w.message);\n }\n }\n\n return {\n ok: warnings.every((w) => w.severity !== 'error'),\n warnings,\n };\n}\n","import type { AccountRuntimeConfig } from './config-schema.js';\nimport { safeParseAccountRuntimeConfig } from './config-schema.js';\nimport { initOverlayWidgets } from './overlay.js';\nimport type { OverlayWidgetsController, OverlayWidgetsOptions } from './overlay.js';\nimport { preflightDiagnostics } from './preflight.js';\nimport type { PageContext } from './types.js';\n\nexport interface HostActions {\n onAddToCart?: (info: { sku: string; quantity?: number; cartCode?: string }) => void;\n onProductNavigate?: (url: string, sku: string, sessionId: string | null) => void;\n onScriptCall?: (params: { name: string; payload?: Record<string, unknown> }) => void;\n}\n\nexport interface GengageClientOptions {\n runtimeConfig: AccountRuntimeConfig | unknown;\n contextResolver?: () => Partial<PageContext>;\n hostActions?: HostActions;\n preflight?: boolean;\n}\n\nfunction parseConfig(raw: AccountRuntimeConfig | unknown): AccountRuntimeConfig {\n const result = safeParseAccountRuntimeConfig(raw);\n if (!result.success) {\n const messages = result.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`).join('; ');\n throw new Error(`[gengage] Invalid runtime config: ${messages}`);\n }\n return result.data;\n}\n\nfunction mapConfigToOverlayOptions(\n config: AccountRuntimeConfig,\n hostActions?: HostActions,\n initialContext?: Partial<PageContext>,\n): OverlayWidgetsOptions {\n const options: OverlayWidgetsOptions = {\n accountId: config.accountId,\n middlewareUrl: config.middlewareUrl,\n idempotencyKey: config.gtm.idempotencyKey,\n };\n\n if (config.locale !== undefined) options.locale = config.locale;\n\n if (initialContext !== undefined) {\n options.pageContext = initialContext;\n if (initialContext.sku !== undefined) options.sku = initialContext.sku;\n }\n\n options.chat = {\n enabled: config.widgets.chat.enabled,\n };\n if (config.mounts.chat !== undefined) {\n options.chat.mountTarget = config.mounts.chat;\n }\n\n options.qna = {\n enabled: config.widgets.qna.enabled,\n };\n if (config.mounts.qna !== undefined) {\n options.qna.mountTarget = config.mounts.qna;\n }\n\n options.simrel = {\n enabled: config.widgets.simrel.enabled,\n };\n if (config.mounts.simrel !== undefined) {\n options.simrel.mountTarget = config.mounts.simrel;\n }\n\n if (hostActions?.onAddToCart !== undefined) {\n options.onAddToCart = hostActions.onAddToCart;\n }\n\n if (hostActions?.onProductNavigate !== undefined) {\n options.onProductNavigate = hostActions.onProductNavigate;\n }\n\n if (hostActions?.onScriptCall !== undefined) {\n options.onScriptCall = hostActions.onScriptCall;\n }\n\n return options;\n}\n\nexport async function initGengageClient(options: GengageClientOptions): Promise<OverlayWidgetsController> {\n const config = parseConfig(options.runtimeConfig);\n\n if (options.preflight !== false) {\n const result = preflightDiagnostics(config);\n if (!result.ok) {\n const errors = result.warnings.filter((w) => w.severity === 'error');\n throw new Error(`[gengage] Preflight failed: ${errors.map((e) => e.message).join('; ')}`);\n }\n }\n\n const initialContext = options.contextResolver?.();\n\n const overlayOptions = mapConfigToOverlayOptions(config, options.hostActions, initialContext);\n const controller = await initOverlayWidgets(overlayOptions);\n\n if (options.contextResolver !== undefined) {\n const resolver = options.contextResolver;\n const listener = () => {\n const ctx = resolver();\n void controller.updateContext(ctx);\n };\n window.addEventListener('gengage:context:update', listener);\n\n // Wrap destroy to remove the listener and prevent a memory leak.\n const originalDestroy = controller.destroy.bind(controller);\n controller.destroy = () => {\n window.removeEventListener('gengage:context:update', listener);\n originalDestroy();\n };\n }\n\n return controller;\n}\n","/**\n * URL-based page type detection.\n *\n * Provides auto-detection of page type from URL patterns and DOM signals.\n * Falls back to 'other' when no rule matches.\n */\n\nimport type { PageContext } from './types.js';\n\nexport type DetectablePageType = PageContext['pageType'];\n\nexport interface PageDetectionRule {\n /** Page type to assign when this rule matches. */\n pageType: DetectablePageType;\n /** URL pathname patterns (tested with `new RegExp(pattern)`). */\n urlPatterns?: string[];\n /** If present, page type is detected only when this query param exists. */\n queryParam?: string;\n /** DOM selector — if an element matching this exists, rule matches. */\n selector?: string;\n}\n\n/** Default rules covering common Turkish e-commerce URL patterns. */\nconst DEFAULT_RULES: PageDetectionRule[] = [\n {\n pageType: 'home',\n urlPatterns: ['^/$', '^/index\\\\.html?$', '^/anasayfa$'],\n },\n {\n pageType: 'search',\n urlPatterns: ['/arama', '/search', '/ara\\\\?'],\n queryParam: 'q',\n },\n {\n pageType: 'cart',\n urlPatterns: ['/sepet', '/cart', '/basket', '/sepetim'],\n },\n {\n pageType: 'plp',\n urlPatterns: ['/kategori/', '/category/', '/c/', '/koleksiyon/', '/collection/'],\n },\n {\n pageType: 'pdp',\n urlPatterns: ['/urun/', '/product/', '/p/', '/-p-', '/-pm-'],\n },\n];\n\n/**\n * Detects page type from the current URL and optional DOM signals.\n *\n * @param rules - Custom rules (defaults to common Turkish e-commerce patterns).\n * @param url - URL to analyze (defaults to window.location).\n * @returns Detected page type, or 'other' if no rule matches.\n */\nexport function detectPageType(rules?: PageDetectionRule[], url?: URL): DetectablePageType {\n const loc = url ?? (typeof window !== 'undefined' ? new URL(window.location.href) : null);\n if (!loc) return 'other';\n\n const effectiveRules = rules ?? DEFAULT_RULES;\n const pathname = loc.pathname;\n\n for (const rule of effectiveRules) {\n // Check URL patterns\n if (rule.urlPatterns) {\n const urlMatch = rule.urlPatterns.some((pattern) => {\n try {\n return new RegExp(pattern, 'i').test(pathname);\n } catch {\n return false;\n }\n });\n if (!urlMatch) continue;\n }\n\n // Check query param requirement\n if (rule.queryParam && !loc.searchParams.has(rule.queryParam)) {\n continue;\n }\n\n // Check DOM selector\n if (rule.selector && typeof document !== 'undefined') {\n if (!document.querySelector(rule.selector)) continue;\n }\n\n return rule.pageType;\n }\n\n return 'other';\n}\n\n/**\n * Attempts to extract a product SKU from the URL path.\n * Looks for common patterns like `/p/SKU`, `/urun/SKU`, `/-p-SKU`.\n */\nexport function extractSkuFromUrl(url?: URL): string | undefined {\n const loc = url ?? (typeof window !== 'undefined' ? new URL(window.location.href) : null);\n if (!loc) return undefined;\n\n const pathname = loc.pathname;\n\n // Pattern: /p/SKU or /urun/SKU or /product/SKU\n const segmentMatch = pathname.match(/\\/(?:p|urun|product)\\/([^/?#]+)/i);\n if (segmentMatch?.[1]) return segmentMatch[1];\n\n // Pattern: -p-SKU at end of path (Trendyol style)\n const suffixMatch = pathname.match(/-p-(\\d+)/i);\n if (suffixMatch?.[1]) return suffixMatch[1];\n\n return undefined;\n}\n\n/**\n * Auto-detects page context from URL and DOM signals.\n * Use as a fallback when the host page doesn't set pageContext explicitly.\n */\nexport function autoDetectPageContext(rules?: PageDetectionRule[]): Partial<PageContext> {\n const pageType = detectPageType(rules);\n const result: Partial<PageContext> = { pageType };\n\n if (pageType === 'pdp') {\n const sku = extractSkuFromUrl();\n if (sku) result.sku = sku;\n }\n\n if (typeof window !== 'undefined') {\n result.url = window.location.href;\n }\n\n return result;\n}\n"],"names":["DEFAULT_ANALYTICS_CONFIG","DEFAULT_AUTH","AnalyticsClient","config","input","envelope","normalizeAnalyticsInput","batch","body","endpoint","resolveAnalyticsEndpoint","events","payload","hasSendBeacon","blob","headers","createAnalyticsClient","middlewareUrl","baseUrl","normalizeMiddlewareUrl","normalizedEndpoint","BASE_WIDGET_THEME","withBaseTheme","overrides","DEFAULT_CUSTOMIZATION_LOCALE","createAccountIdentity","createFloatingChatConfig","createPdpQnaConfig","createPdpSimRelConfig","createDefaultAnalyticsConfig","isValidSelector","selector","preflightDiagnostics","options","warnings","mounts","mountEntries","widget","idempotencyKey","cspBlocked","cspListener","e","w","parseConfig","raw","result","safeParseAccountRuntimeConfig","messages","i","mapConfigToOverlayOptions","hostActions","initialContext","initGengageClient","errors","overlayOptions","controller","initOverlayWidgets","resolver","listener","ctx","originalDestroy","DEFAULT_RULES","detectPageType","rules","url","loc","effectiveRules","pathname","rule","pattern","extractSkuFromUrl","segmentMatch","suffixMatch","autoDetectPageContext","pageType","sku"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- "use strict";const V=require("./index-Dco2Aw73.cjs"),K=require("./qna.cjs"),$=require("./simrel.cjs"),s=require("./schemas-DqUVzVDf.cjs"),b=s.object({enabled:s.boolean().default(!0)}),G=s.object({chat:s.string().optional(),qna:s.string().optional(),simrel:s.string().optional()}),Y=s.object({}),k=s._enum(["none","x-api-key-header","bearer-header","body-api-key"]),J=s.object({mode:k.default("none"),key:s.string().optional(),headerName:s.string().optional(),bodyField:s.string().default("api_key")}),X=s.object({enabled:s.boolean().default(!0),endpoint:s.string().default("/analytics"),auth:J.default({mode:"none",bodyField:"api_key"}),fireAndForget:s.boolean().default(!0),useBeacon:s.boolean().default(!0),keepaliveFetch:s.boolean().default(!0),timeoutMs:s.number().int().positive().default(4e3),maxRetries:s.number().int().min(0).max(5).default(1)}),E="__gengageWidgetsInit",z=s.object({idempotencyKey:s.string().default(E),requireDomReady:s.boolean().default(!0)}),R=s._enum(["log-and-ignore","throw","delegate"]),Z=s.object({unknownActionPolicy:R.default("log-and-ignore"),allowScriptCall:s.boolean().default(!1)}),q=s.object({version:s.literal("1",{error:'version must be "1"'}),accountId:s.string({error:"accountId must be a non-empty string"}).min(1,{error:"accountId must be a non-empty string"}),middlewareUrl:s.string({error:'middlewareUrl must be a valid URL (e.g. "https://your-backend.example.com")'}).url({error:'middlewareUrl must be a valid URL (e.g. "https://your-backend.example.com")'}),locale:s.string().optional(),widgets:s.object({chat:b.default({enabled:!0}),qna:b.default({enabled:!0}),simrel:b.default({enabled:!0})}),mounts:G.default({}),transport:Y.default({}),analytics:X.default({enabled:!0,endpoint:"/analytics",auth:{mode:"none",bodyField:"api_key"},fireAndForget:!0,useBeacon:!0,keepaliveFetch:!0,timeoutMs:4e3,maxRetries:1}),gtm:z.default({idempotencyKey:"__gengageWidgetsInit",requireDomReady:!0}),actionHandling:Z.default({unknownActionPolicy:"log-and-ignore",allowScriptCall:!1})});function U(n){s.debugLog("config","parsing account runtime config",n);const e=q.parse(n);return s.debugLog("config","config resolved",{accountId:e.accountId,middlewareUrl:e.middlewareUrl}),e}function ee(n){return q.safeParse(n)}function te(n){return U({version:"1",accountId:n.accountId,middlewareUrl:n.middlewareUrl,locale:n.locale,widgets:{chat:{enabled:!0},qna:{enabled:!0},simrel:{enabled:!0}}})}const x=`${E}_overlay_`,ne="#gengage-qna",ie="#gengage-simrel";function C(){const n=window;return n.__gengageOverlayRegistry||(n.__gengageOverlayRegistry={instances:{},pending:{}}),n.__gengageOverlayRegistry}function se(n){const e={pageType:n.pageContext?.pageType??(n.sku!==void 0?"pdp":"other")},t=n.pageContext;return t?.sku!==void 0&&(e.sku=t.sku),t?.price!==void 0&&(e.price=t.price),t?.categoryTree!==void 0&&(e.categoryTree=t.categoryTree),t?.url!==void 0&&(e.url=t.url),t?.extra!==void 0&&(e.extra=t.extra),n.sku!==void 0&&(e.sku=n.sku),e}function oe(n,e){const t={...n,...e,pageType:e.pageType??n.pageType};return e.sku===void 0&&n.sku!==void 0&&(t.sku=n.sku),t}function N(n){return n instanceof HTMLElement||document.querySelector(n)?n:null}function P(n){return n.idempotencyKey??`${x}${n.accountId}`}class ae{constructor(e,t){this.options=e,this.onDestroy=t,this._chat=null,this._qna=null,this._simrel=null,this._analyticsClient=null,this._offQnaWire=null,this._destroyed=!1,this._queue=Promise.resolve(),this._warnedQnaMountMissing=!1,this._warnedSimRelMountMissing=!1,this.idempotencyKey=P(e),this.session=s.resolveSession(e.session),this._pageContext=se(e)}get chat(){return this._chat}get qna(){return this._qna}get simrel(){return this._simrel}get analyticsClient(){return this._analyticsClient}async init(){window.gengage||(window.gengage={}),window.gengage.sessionId=this.session.sessionId,window.gengage.pageContext=this._pageContext,await this._initChat(),this.options.wireQnaToChat!==!1&&(this._offQnaWire=s.wireQNAToChat()),await this._syncPdpWidgets(),window.gengage.overlay=this}openChat(e){this._chat?.open(e)}closeChat(){this._chat?.close()}async updateContext(e){this._destroyed||await this._enqueue(async()=>{this._pageContext=oe(this._pageContext,e),window.gengage||(window.gengage={}),window.gengage.pageContext=this._pageContext,this._chat?.update(e),this._qna?.update(e),this._simrel?.update(e),await this._syncPdpWidgets()})}async updateSku(e,t="pdp"){await this.updateContext({sku:e,pageType:t})}destroy(){this._destroyed||(this._destroyed=!0,this._offQnaWire?.(),this._offQnaWire=null,this._chat?.destroy(),this._qna?.destroy(),this._simrel?.destroy(),this._chat=null,this._qna=null,this._simrel=null,window.gengage?.overlay===this&&delete window.gengage.overlay,this.onDestroy())}async _initChat(){if(this.options.chat?.enabled===!1)return;const e=this.options.middlewareUrl,t={accountId:this.options.accountId,middlewareUrl:e,session:this.session,pageContext:this._pageContext,variant:this.options.chat?.variant??"floating"};this.options.theme!==void 0&&(t.theme=this.options.theme),this.options.locale!==void 0&&(t.locale=this.options.locale),this.options.pricing!==void 0&&(t.pricing=this.options.pricing),this.options.chat?.mountTarget!==void 0&&(t.mountTarget=this.options.chat.mountTarget),this.options.chat?.launcherImageUrl!==void 0?t.launcherImageUrl=this.options.chat.launcherImageUrl:this.options.chat?.launcherSvg!==void 0&&(t.launcherSvg=this.options.chat.launcherSvg),this.options.chat?.headerTitle!==void 0&&(t.headerTitle=this.options.chat.headerTitle),this.options.chat?.headerAvatarUrl!==void 0&&(t.headerAvatarUrl=this.options.chat.headerAvatarUrl),this.options.chat?.headerBadge!==void 0&&(t.headerBadge=this.options.chat.headerBadge),this.options.chat?.headerCartUrl!==void 0&&(t.headerCartUrl=this.options.chat.headerCartUrl),this.options.chat?.headerFavoritesToggle!==void 0&&(t.headerFavoritesToggle=this.options.chat.headerFavoritesToggle),this.options.chat?.hideMobileLauncher!==void 0&&(t.hideMobileLauncher=this.options.chat.hideMobileLauncher),this.options.chat?.mobileBreakpoint!==void 0&&(t.mobileBreakpoint=this.options.chat.mobileBreakpoint),this.options.chat?.mobileInitialState!==void 0&&(t.mobileInitialState=this.options.chat.mobileInitialState),this.options.chat?.i18n!==void 0&&(t.i18n=this.options.chat.i18n),this.options.chat?.actionHandling!==void 0&&(t.actionHandling=this.options.chat.actionHandling),this.options.chat?.renderer!==void 0&&(t.renderer=this.options.chat.renderer),this.options.onScriptCall!==void 0&&(t.onScriptCall=this.options.onScriptCall),this._chat=new V.GengageChat,await this._chat.init(t)}async _syncPdpWidgets(){if(this._destroyed)return;const e=this._pageContext.sku;if(!(this._pageContext.pageType==="pdp"&&e!==void 0&&e.length>0)){this._destroyPdpWidgets();return}const r=this.options.middlewareUrl;if(this.options.qna?.enabled!==!1){const o=this.options.qna?.mountTarget??ne,i=N(o);if(i)if(this._warnedQnaMountMissing=!1,this._qna)this._qna.show(),this._qna.update({pageType:"pdp",sku:e});else{const h=new K.GengageQNA,a={accountId:this.options.accountId,middlewareUrl:r,session:this.session,pageContext:{pageType:"pdp",sku:e},mountTarget:i};this.options.theme!==void 0&&(a.theme=this.options.theme),this.options.qna?.ctaText!==void 0&&(a.ctaText=this.options.qna.ctaText),this.options.qna?.hideButtonRowCta!==void 0&&(a.hideButtonRowCta=this.options.qna.hideButtonRowCta),this.options.qna?.inputPlaceholder!==void 0&&(a.inputPlaceholder=this.options.qna.inputPlaceholder),this.options.qna?.i18n!==void 0&&(a.i18n=this.options.qna.i18n),this.options.qna?.renderer!==void 0&&(a.renderer=this.options.qna.renderer),await h.init(a),this._qna=h}else this._qna?.destroy(),this._qna=null,this._warnedQnaMountMissing||(console.warn(`[gengage] QNA mount target not found: ${o}`),this._warnedQnaMountMissing=!0)}else this._qna?.destroy(),this._qna=null;if(this.options.simrel?.enabled!==!1){const o=this.options.simrel?.mountTarget??ie,i=N(o);if(i)if(this._warnedSimRelMountMissing=!1,this._simrel)this._simrel.show(),this._simrel.update({pageType:"pdp",sku:e});else{const h=new $.GengageSimRel,a={accountId:this.options.accountId,middlewareUrl:r,session:this.session,sku:e,mountTarget:i};this.options.theme!==void 0&&(a.theme=this.options.theme),this.options.pricing!==void 0&&(a.pricing=this.options.pricing),this.options.simrel?.discountType!==void 0&&(a.discountType=this.options.simrel.discountType),this.options.simrel?.renderCardElement!==void 0&&(a.renderCardElement=this.options.simrel.renderCardElement),this.options.simrel?.renderer!==void 0&&(a.renderer=this.options.simrel.renderer),this.options.onAddToCart!==void 0&&(a.onAddToCart=this.options.onAddToCart),this.options.onProductNavigate!==void 0?a.onProductNavigate=this.options.onProductNavigate:a.onProductNavigate=(d,l,p)=>{s.isSafeUrl(d)&&(this._chat?.saveSession(p??this.session.sessionId,l),window.location.href=d)},await h.init(a),this._simrel=h}else this._simrel?.destroy(),this._simrel=null,this._warnedSimRelMountMissing||(console.warn(`[gengage] SimRel mount target not found: ${o}`),this._warnedSimRelMountMissing=!0)}else this._simrel?.destroy(),this._simrel=null}_destroyPdpWidgets(){this._qna?.destroy(),this._simrel?.destroy(),this._qna=null,this._simrel=null}_enqueue(e){const t=this._queue.then(e);return this._queue=t.catch(r=>{}),t}}async function W(n){const e=P(n),t=C(),r=t.instances[e];if(r)return r;const o=t.pending[e];if(o)return o;const i=new ae(n,()=>{const a=C();delete a.instances[e],delete a.pending[e]}),h=i.init().then(()=>(t.instances[e]=i,delete t.pending[e],i)).catch(a=>{throw delete t.pending[e],a});return t.pending[e]=h,h}function O(n){return C().instances[n]??null}function re(n){O(n)?.destroy()}function de(n){return`${x}${n}`}const L=["gengage:chat:open","gengage:chat:close","gengage:chat:ready","gengage:chat:add-to-cart","gengage:qna:action","gengage:qna:open-chat","gengage:similar:product-click","gengage:similar:add-to-cart","gengage:global:error","gengage:context:update"],ce=32,S="#gengage-qna",M="#gengage-simrel";function le(n){let e=n;if(typeof n=="string"){const i=n.trim();if(i.length===0)return null;if(!i.startsWith("{")&&!i.startsWith("["))return{type:i};try{e=JSON.parse(i)}catch{return null}}if(!e||typeof e!="object")return null;const t=e,r=[t.type,t.command,t.action,t.event].find(i=>typeof i=="string"&&i.length>0);if(!r)return null;let o=t.payload;if(o===void 0&&"data"in t&&(o=t.data),r==="setSession"&&o===void 0){const i={};typeof t.sessionId=="string"&&(i.sessionId=t.sessionId),typeof t.userId=="string"&&(i.userId=t.userId),(i.sessionId!==void 0||i.userId!==void 0)&&(o=i)}return o===void 0?{type:r}:{type:r,payload:o}}function ge(n){if(typeof n=="string"&&n.length>0)return{sku:n};if(n&&typeof n=="object"&&"sku"in n){const e=n.sku;if(typeof e=="string"&&e.length>0){const t=n.pageType;return t!==void 0?{sku:e,pageType:t}:{sku:e}}}return null}function T(n,e){return e instanceof HTMLElement?!0:typeof e!="string"?!1:n.document.querySelector(e)!==null}function A(n,e,t){if(e instanceof HTMLElement||T(n,e)||typeof e!="string")return e;if(e.startsWith("#")){const i=e.slice(1);if(i.length>0){const h=n.document.getElementById(i);if(h)return h;const a=n.document.createElement("div");return a.id=i,n.document.body.appendChild(a),a}}const r=n.document.getElementById(t);if(r)return r;const o=n.document.createElement("div");return o.id=t,n.document.body.appendChild(o),o}function B(n,e){const t=n.webkit?.messageHandlers?.[e];return t&&typeof t.postMessage=="function"?t.postMessage.bind(t):null}function v(n,e){const t=n[e];return t&&typeof t=="object"&&typeof t.postMessage=="function"?t:null}function D(n={}){const e=n.win??window,t=n.iosHandlerName??"gengage",r=n.androidInterfaceName??"GengageNative",o=n.reactNativeInterfaceName??"ReactNativeWebView";return B(e,t)?"ios":v(e,r)?"android":v(e,o)?"react-native":"browser"}function F(n,e={}){const t=e.win??window;if(n.sessionId!==void 0){t.__gengageSessionId=n.sessionId,t.gengage||(t.gengage={}),t.gengage.sessionId=n.sessionId;try{t.sessionStorage.setItem("gengage_session_id",n.sessionId)}catch{}}if(n.userId!==void 0){t.gengage||(t.gengage={});const r=t.gengage,o=r.session??{};o.userId=n.userId,r.session=o}}function j(n={}){const e=n.win??window,t=e;if(t.gengageNative)return t.gengageNative;const r=n.iosHandlerName??"gengage",o=n.androidInterfaceName??"GengageNative",i=n.reactNativeInterfaceName??"ReactNativeWebView",h=n.trackedEvents??[...L],a=D({win:e,iosHandlerName:r,androidInterfaceName:o,reactNativeInterfaceName:i});let d=e.gengage?.overlay??null;const l=[],p=(g,c)=>{const f=c===void 0?{type:g}:{type:g,payload:c};if(a==="ios"){B(e,r)?.(f);return}if(a==="android"){v(e,o)?.postMessage(JSON.stringify(f));return}if(a==="react-native"){v(e,i)?.postMessage(JSON.stringify(f));return}},m=g=>{const c=g.detail;!c||typeof c.namespace!="string"||typeof c.type!="string"||p("bridge_message",{namespace:c.namespace,type:c.type,payload:c.payload})};e.addEventListener("gengage:bridge:message",m);const Q=h.map(g=>{const c=f=>{const u=f.detail;p("widget_event",{event:g,detail:u})};return e.addEventListener(g,c),{event:g,handler:c}}),y=g=>{l.length>=ce&&l.shift(),l.push(g)},H=()=>{if(!d||l.length===0)return;const g=l.splice(0,l.length);for(const c of g)I(c)},I=g=>{const c=le(g);if(!c||typeof c.type!="string"){console.warn("[gengage:native-bridge] Invalid message:",g);return}const f=c.type,u=c.payload;switch(f){case"openChat":{d?d.openChat(u&&typeof u=="object"?u:u==="half"||u==="full"?{state:u}:void 0):y(c);return}case"closeChat":{d?d.closeChat():y(c);return}case"updateContext":{d&&u&&typeof u=="object"?d.updateContext(u):d?console.warn("[gengage:native-bridge] updateContext: missing payload"):y(c);return}case"updateSku":{const w=ge(u);if(d&&w){d.updateSku(w.sku,w.pageType);return}d?console.warn("[gengage:native-bridge] updateSku: missing sku"):y(c);return}case"setSession":{u&&typeof u=="object"&&F(u,{win:e});return}case"destroy":{d?.destroy();return}default:e.postMessage({gengage:"native",type:f,payload:u},e.location.origin),n.logUnhandled&&console.warn("[gengage:native-bridge] Unhandled inbound type forwarded:",f)}},_={env:a,sendToNative:p,receive:I,setController(g){d=g,H()},destroy(){e.removeEventListener("gengage:bridge:message",m);for(const g of Q)e.removeEventListener(g.event,g.handler);l.splice(0,l.length),e.gengageNative===_&&delete e.gengageNative}};return t.gengageNative=_,_}async function ue(n){const{nativeBridge:e,emitReadyEvent:t=!0,...r}=n,o=j(e),i={...r};i.onAddToCart||(i.onAddToCart=l=>{o.sendToNative("addToCart",{sku:l.sku,quantity:l.quantity,cartCode:l.cartCode})}),i.onProductNavigate||(i.onProductNavigate=(l,p,m)=>{o.sendToNative("productNavigate",{url:l,sku:p,sessionId:m})});const h=i.qna?.enabled===!0||i.qna?.mountTarget!==void 0;if(i.qna?.enabled!==!1)if(h){const l=A(window,i.qna?.mountTarget??S,"gengage-qna");i.qna={...i.qna,enabled:!0,mountTarget:l}}else T(window,S)||(i.qna={enabled:!1});const a=i.simrel?.enabled===!0||i.simrel?.mountTarget!==void 0;if(i.simrel?.enabled!==!1)if(a){const l=A(window,i.simrel?.mountTarget??M,"gengage-simrel");i.simrel={...i.simrel,enabled:!0,mountTarget:l}}else T(window,M)||(i.simrel={enabled:!1});const d=await W(i);return o.setController(d),t&&o.sendToNative("ready",{sessionId:d.session.sessionId,widgets:{chat:d.chat!==null,qna:d.qna!==null,simrel:d.simrel!==null}}),{controller:d,bridge:o,destroy(){d.destroy(),o.destroy()}}}exports.AccountRuntimeConfigSchema=q;exports.AnalyticsAuthModeSchema=k;exports.DEFAULT_NATIVE_TRACKED_EVENTS=L;exports.UnknownActionPolicySchema=R;exports.applyNativeSession=F;exports.buildOverlayIdempotencyKey=de;exports.createDefaultAccountRuntimeConfig=te;exports.createNativeWebViewBridge=j;exports.destroyOverlayWidgets=re;exports.detectNativeEnvironment=D;exports.getOverlayWidgets=O;exports.initNativeOverlayWidgets=ue;exports.initOverlayWidgets=W;exports.parseAccountRuntimeConfig=U;exports.safeParseAccountRuntimeConfig=ee;
2
- //# sourceMappingURL=index-BAQXPosE.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BAQXPosE.cjs","sources":["../src/common/config-schema.ts","../src/common/overlay.ts","../src/common/native-webview.ts"],"sourcesContent":["import { z } from 'zod';\nimport { debugLog } from './debug.js';\n\nconst WidgetToggleSchema = z.object({\n enabled: z.boolean().default(true),\n});\n\nconst MountSelectorsSchema = z.object({\n chat: z.string().optional(),\n qna: z.string().optional(),\n simrel: z.string().optional(),\n});\n\nconst TransportSchema = z.object({});\n\nexport const AnalyticsAuthModeSchema = z.enum(['none', 'x-api-key-header', 'bearer-header', 'body-api-key']);\n\nconst AnalyticsAuthSchema = z.object({\n mode: AnalyticsAuthModeSchema.default('none'),\n key: z.string().optional(),\n headerName: z.string().optional(),\n bodyField: z.string().default('api_key'),\n});\n\nconst AnalyticsSchema = z.object({\n enabled: z.boolean().default(true),\n endpoint: z.string().default('/analytics'),\n auth: AnalyticsAuthSchema.default({ mode: 'none', bodyField: 'api_key' }),\n fireAndForget: z.boolean().default(true),\n useBeacon: z.boolean().default(true),\n keepaliveFetch: z.boolean().default(true),\n timeoutMs: z.number().int().positive().default(4000),\n maxRetries: z.number().int().min(0).max(5).default(1),\n});\n\nexport const DEFAULT_IDEMPOTENCY_KEY = '__gengageWidgetsInit';\n\nconst GTMSchema = z.object({\n idempotencyKey: z.string().default(DEFAULT_IDEMPOTENCY_KEY),\n requireDomReady: z.boolean().default(true),\n});\n\nexport const UnknownActionPolicySchema = z.enum(['log-and-ignore', 'throw', 'delegate']);\n\nconst ActionHandlingSchema = z.object({\n unknownActionPolicy: UnknownActionPolicySchema.default('log-and-ignore'),\n allowScriptCall: z.boolean().default(false),\n});\n\nexport const AccountRuntimeConfigSchema = z.object({\n version: z.literal('1', { error: 'version must be \"1\"' }),\n accountId: z\n .string({ error: 'accountId must be a non-empty string' })\n .min(1, { error: 'accountId must be a non-empty string' }),\n middlewareUrl: z\n .string({ error: 'middlewareUrl must be a valid URL (e.g. \"https://your-backend.example.com\")' })\n .url({ error: 'middlewareUrl must be a valid URL (e.g. \"https://your-backend.example.com\")' }),\n locale: z.string().optional(),\n widgets: z.object({\n chat: WidgetToggleSchema.default({ enabled: true }),\n qna: WidgetToggleSchema.default({ enabled: true }),\n simrel: WidgetToggleSchema.default({ enabled: true }),\n }),\n mounts: MountSelectorsSchema.default({}),\n transport: TransportSchema.default({}),\n analytics: AnalyticsSchema.default({\n enabled: true,\n endpoint: '/analytics',\n auth: { mode: 'none', bodyField: 'api_key' },\n fireAndForget: true,\n useBeacon: true,\n keepaliveFetch: true,\n timeoutMs: 4000,\n maxRetries: 1,\n }),\n gtm: GTMSchema.default({\n idempotencyKey: '__gengageWidgetsInit',\n requireDomReady: true,\n }),\n actionHandling: ActionHandlingSchema.default({\n unknownActionPolicy: 'log-and-ignore',\n allowScriptCall: false,\n }),\n});\n\nexport type AccountRuntimeConfig = z.infer<typeof AccountRuntimeConfigSchema>;\nexport type AnalyticsAuthMode = z.infer<typeof AnalyticsAuthModeSchema>;\nexport type UnknownActionPolicy = z.infer<typeof UnknownActionPolicySchema>;\n\nexport function parseAccountRuntimeConfig(input: unknown): AccountRuntimeConfig {\n debugLog('config', 'parsing account runtime config', input);\n const result = AccountRuntimeConfigSchema.parse(input);\n debugLog('config', 'config resolved', { accountId: result.accountId, middlewareUrl: result.middlewareUrl });\n return result;\n}\n\nexport function safeParseAccountRuntimeConfig(input: unknown): ReturnType<typeof AccountRuntimeConfigSchema.safeParse> {\n return AccountRuntimeConfigSchema.safeParse(input);\n}\n\nexport function createDefaultAccountRuntimeConfig(params: {\n accountId: string;\n middlewareUrl: string;\n locale?: string;\n}): AccountRuntimeConfig {\n return parseAccountRuntimeConfig({\n version: '1',\n accountId: params.accountId,\n middlewareUrl: params.middlewareUrl,\n locale: params.locale,\n widgets: {\n chat: { enabled: true },\n qna: { enabled: true },\n simrel: { enabled: true },\n },\n });\n}\n","import { GengageChat } from '../chat/index.js';\nimport type { ChatI18n, ChatWidgetConfig } from '../chat/types.js';\nimport { GengageQNA } from '../qna/index.js';\nimport type { QNAWidgetConfig } from '../qna/types.js';\nimport { GengageSimRel } from '../simrel/index.js';\nimport type { SimRelWidgetConfig } from '../simrel/types.js';\nimport { DEFAULT_IDEMPOTENCY_KEY } from './config-schema.js';\nimport { resolveSession } from './context.js';\nimport { wireQNAToChat } from './events.js';\nimport { isSafeUrl } from './safe-html.js';\nimport type { PageContext, SessionContext, WidgetTheme } from './types.js';\n\nconst DEFAULT_OVERLAY_KEY_PREFIX = `${DEFAULT_IDEMPOTENCY_KEY}_overlay_`;\nconst DEFAULT_QNA_MOUNT = '#gengage-qna';\nconst DEFAULT_SIMREL_MOUNT = '#gengage-simrel';\n\ninterface OverlayRegistryState {\n instances: Record<string, OverlayWidgetsRuntime>;\n pending: Record<string, Promise<OverlayWidgetsRuntime>>;\n}\n\ninterface WindowWithOverlayRegistry extends Window {\n __gengageOverlayRegistry?: OverlayRegistryState;\n}\n\nfunction getOverlayRegistry(): OverlayRegistryState {\n const win = window as WindowWithOverlayRegistry;\n if (!win.__gengageOverlayRegistry) {\n win.__gengageOverlayRegistry = {\n instances: {},\n pending: {},\n };\n }\n return win.__gengageOverlayRegistry;\n}\n\nfunction buildInitialPageContext(options: OverlayWidgetsOptions): PageContext {\n const base: PageContext = {\n pageType: options.pageContext?.pageType ?? (options.sku !== undefined ? 'pdp' : 'other'),\n };\n\n const incoming = options.pageContext;\n if (incoming?.sku !== undefined) base.sku = incoming.sku;\n if (incoming?.price !== undefined) base.price = incoming.price;\n if (incoming?.categoryTree !== undefined) base.categoryTree = incoming.categoryTree;\n if (incoming?.url !== undefined) base.url = incoming.url;\n if (incoming?.extra !== undefined) base.extra = incoming.extra;\n\n if (options.sku !== undefined) {\n base.sku = options.sku;\n }\n\n return base;\n}\n\nfunction mergePageContext(current: PageContext, patch: Partial<PageContext>): PageContext {\n const next: PageContext = {\n ...current,\n ...patch,\n pageType: patch.pageType ?? current.pageType,\n };\n if (patch.sku === undefined && current.sku !== undefined) {\n next.sku = current.sku;\n }\n return next;\n}\n\nfunction resolveMountTarget(target: HTMLElement | string): HTMLElement | string | null {\n if (target instanceof HTMLElement) return target;\n if (document.querySelector(target)) return target;\n return null;\n}\n\nfunction buildOverlayKey(options: OverlayWidgetsOptions): string {\n return options.idempotencyKey ?? `${DEFAULT_OVERLAY_KEY_PREFIX}${options.accountId}`;\n}\n\nexport interface OverlayChatOptions {\n enabled?: boolean;\n variant?: ChatWidgetConfig['variant'];\n mountTarget?: HTMLElement | string;\n launcherSvg?: string;\n launcherImageUrl?: string;\n headerTitle?: string;\n headerAvatarUrl?: string;\n headerBadge?: string;\n headerCartUrl?: string;\n headerFavoritesToggle?: boolean;\n hideMobileLauncher?: boolean;\n mobileBreakpoint?: number;\n mobileInitialState?: 'half' | 'full';\n i18n?: Partial<ChatI18n>;\n actionHandling?: ChatWidgetConfig['actionHandling'];\n /** UISpec renderer overrides for chat components. */\n renderer?: ChatWidgetConfig['renderer'];\n}\n\nexport interface OverlayQNAOptions {\n enabled?: boolean;\n mountTarget?: HTMLElement | string;\n ctaText?: string;\n hideButtonRowCta?: boolean;\n inputPlaceholder?: QNAWidgetConfig['inputPlaceholder'];\n i18n?: QNAWidgetConfig['i18n'];\n /** UISpec renderer overrides for QNA components. */\n renderer?: QNAWidgetConfig['renderer'];\n}\n\nexport interface OverlaySimRelOptions {\n enabled?: boolean;\n mountTarget?: HTMLElement | string;\n discountType?: SimRelWidgetConfig['discountType'];\n /** Custom card element renderer for the direct rendering path (GroupTabs/ProductGrid). */\n renderCardElement?: SimRelWidgetConfig['renderCardElement'];\n /** UISpec renderer overrides for simrel components. */\n renderer?: SimRelWidgetConfig['renderer'];\n}\n\nexport interface OverlayWidgetsOptions {\n accountId: string;\n middlewareUrl: string;\n locale?: string;\n session?: Partial<SessionContext>;\n pageContext?: Partial<PageContext>;\n sku?: string;\n theme?: WidgetTheme;\n /** Price formatting options. Defaults to Turkish locale. */\n pricing?: import('./price-formatter.js').PriceFormatConfig;\n idempotencyKey?: string;\n wireQnaToChat?: boolean;\n chat?: OverlayChatOptions;\n qna?: OverlayQNAOptions;\n simrel?: OverlaySimRelOptions;\n onAddToCart?: SimRelWidgetConfig['onAddToCart'];\n onProductNavigate?: SimRelWidgetConfig['onProductNavigate'];\n onScriptCall?: ChatWidgetConfig['onScriptCall'];\n}\n\nexport interface OverlayWidgetsController {\n readonly idempotencyKey: string;\n readonly session: SessionContext;\n readonly chat: GengageChat | null;\n readonly qna: GengageQNA | null;\n readonly simrel: GengageSimRel | null;\n /** Shared analytics client for custom event tracking (null if not configured). */\n readonly analyticsClient: import('./analytics.js').AnalyticsClient | null;\n openChat(options?: { state?: 'half' | 'full' }): void;\n closeChat(): void;\n updateContext(patch: Partial<PageContext>): Promise<void>;\n updateSku(sku: string, pageType?: PageContext['pageType']): Promise<void>;\n destroy(): void;\n}\n\nclass OverlayWidgetsRuntime implements OverlayWidgetsController {\n private _chat: GengageChat | null = null;\n private _qna: GengageQNA | null = null;\n private _simrel: GengageSimRel | null = null;\n private _analyticsClient: import('./analytics.js').AnalyticsClient | null = null;\n private _offQnaWire: (() => void) | null = null;\n private _pageContext: PageContext;\n private _destroyed = false;\n private _queue: Promise<void> = Promise.resolve();\n private _warnedQnaMountMissing = false;\n private _warnedSimRelMountMissing = false;\n\n readonly idempotencyKey: string;\n readonly session: SessionContext;\n\n constructor(\n private readonly options: OverlayWidgetsOptions,\n private readonly onDestroy: () => void,\n ) {\n this.idempotencyKey = buildOverlayKey(options);\n this.session = resolveSession(options.session);\n this._pageContext = buildInitialPageContext(options);\n }\n\n get chat(): GengageChat | null {\n return this._chat;\n }\n\n get qna(): GengageQNA | null {\n return this._qna;\n }\n\n get simrel(): GengageSimRel | null {\n return this._simrel;\n }\n\n get analyticsClient(): import('./analytics.js').AnalyticsClient | null {\n return this._analyticsClient;\n }\n\n async init(): Promise<void> {\n if (!window.gengage) window.gengage = {};\n window.gengage.sessionId = this.session.sessionId;\n window.gengage.pageContext = this._pageContext;\n\n await this._initChat();\n\n if (this.options.wireQnaToChat !== false) {\n this._offQnaWire = wireQNAToChat();\n }\n\n await this._syncPdpWidgets();\n\n window.gengage.overlay = this;\n }\n\n openChat(options?: { state?: 'half' | 'full' }): void {\n this._chat?.open(options);\n }\n\n closeChat(): void {\n this._chat?.close();\n }\n\n async updateContext(patch: Partial<PageContext>): Promise<void> {\n if (this._destroyed) return;\n await this._enqueue(async () => {\n this._pageContext = mergePageContext(this._pageContext, patch);\n\n if (!window.gengage) window.gengage = {};\n window.gengage.pageContext = this._pageContext;\n\n this._chat?.update(patch);\n this._qna?.update(patch);\n this._simrel?.update(patch);\n await this._syncPdpWidgets();\n });\n }\n\n async updateSku(sku: string, pageType: PageContext['pageType'] = 'pdp'): Promise<void> {\n await this.updateContext({ sku, pageType });\n }\n\n destroy(): void {\n if (this._destroyed) return;\n this._destroyed = true;\n\n this._offQnaWire?.();\n this._offQnaWire = null;\n\n this._chat?.destroy();\n this._qna?.destroy();\n this._simrel?.destroy();\n\n this._chat = null;\n this._qna = null;\n this._simrel = null;\n\n if (window.gengage?.overlay === this) {\n delete window.gengage.overlay;\n }\n\n this.onDestroy();\n }\n\n private async _initChat(): Promise<void> {\n if (this.options.chat?.enabled === false) return;\n\n const middlewareUrl = this.options.middlewareUrl;\n\n const config: ChatWidgetConfig = {\n accountId: this.options.accountId,\n middlewareUrl,\n session: this.session,\n pageContext: this._pageContext,\n variant: this.options.chat?.variant ?? 'floating',\n };\n\n if (this.options.theme !== undefined) config.theme = this.options.theme;\n if (this.options.locale !== undefined) config.locale = this.options.locale;\n if (this.options.pricing !== undefined) config.pricing = this.options.pricing;\n if (this.options.chat?.mountTarget !== undefined) config.mountTarget = this.options.chat.mountTarget;\n if (this.options.chat?.launcherImageUrl !== undefined) config.launcherImageUrl = this.options.chat.launcherImageUrl;\n else if (this.options.chat?.launcherSvg !== undefined) config.launcherSvg = this.options.chat.launcherSvg;\n if (this.options.chat?.headerTitle !== undefined) config.headerTitle = this.options.chat.headerTitle;\n if (this.options.chat?.headerAvatarUrl !== undefined) {\n config.headerAvatarUrl = this.options.chat.headerAvatarUrl;\n }\n if (this.options.chat?.headerBadge !== undefined) config.headerBadge = this.options.chat.headerBadge;\n if (this.options.chat?.headerCartUrl !== undefined) config.headerCartUrl = this.options.chat.headerCartUrl;\n if (this.options.chat?.headerFavoritesToggle !== undefined) {\n config.headerFavoritesToggle = this.options.chat.headerFavoritesToggle;\n }\n if (this.options.chat?.hideMobileLauncher !== undefined) {\n config.hideMobileLauncher = this.options.chat.hideMobileLauncher;\n }\n if (this.options.chat?.mobileBreakpoint !== undefined) {\n config.mobileBreakpoint = this.options.chat.mobileBreakpoint;\n }\n if (this.options.chat?.mobileInitialState !== undefined) {\n config.mobileInitialState = this.options.chat.mobileInitialState;\n }\n if (this.options.chat?.i18n !== undefined) config.i18n = this.options.chat.i18n;\n if (this.options.chat?.actionHandling !== undefined) {\n config.actionHandling = this.options.chat.actionHandling;\n }\n if (this.options.chat?.renderer !== undefined) config.renderer = this.options.chat.renderer;\n if (this.options.onScriptCall !== undefined) {\n config.onScriptCall = this.options.onScriptCall;\n }\n\n this._chat = new GengageChat();\n await this._chat.init(config);\n }\n\n private async _syncPdpWidgets(): Promise<void> {\n if (this._destroyed) return;\n const sku = this._pageContext.sku;\n const isPdp = this._pageContext.pageType === 'pdp' && sku !== undefined && sku.length > 0;\n\n if (!isPdp) {\n this._destroyPdpWidgets();\n return;\n }\n\n const middlewareUrl = this.options.middlewareUrl;\n\n if (this.options.qna?.enabled !== false) {\n const qnaTarget = this.options.qna?.mountTarget ?? DEFAULT_QNA_MOUNT;\n const mountTarget = resolveMountTarget(qnaTarget);\n\n if (mountTarget) {\n this._warnedQnaMountMissing = false;\n if (!this._qna) {\n const qna = new GengageQNA();\n const qnaConfig: QNAWidgetConfig = {\n accountId: this.options.accountId,\n middlewareUrl,\n session: this.session,\n pageContext: {\n pageType: 'pdp',\n sku,\n },\n mountTarget,\n };\n if (this.options.theme !== undefined) qnaConfig.theme = this.options.theme;\n if (this.options.qna?.ctaText !== undefined) qnaConfig.ctaText = this.options.qna.ctaText;\n if (this.options.qna?.hideButtonRowCta !== undefined)\n qnaConfig.hideButtonRowCta = this.options.qna.hideButtonRowCta;\n if (this.options.qna?.inputPlaceholder !== undefined) {\n qnaConfig.inputPlaceholder = this.options.qna.inputPlaceholder;\n }\n if (this.options.qna?.i18n !== undefined) qnaConfig.i18n = this.options.qna.i18n;\n if (this.options.qna?.renderer !== undefined) qnaConfig.renderer = this.options.qna.renderer;\n await qna.init(qnaConfig);\n this._qna = qna;\n } else {\n this._qna.show();\n this._qna.update({ pageType: 'pdp', sku });\n }\n } else {\n this._qna?.destroy();\n this._qna = null;\n if (!this._warnedQnaMountMissing) {\n console.warn(`[gengage] QNA mount target not found: ${qnaTarget}`);\n this._warnedQnaMountMissing = true;\n }\n }\n } else {\n this._qna?.destroy();\n this._qna = null;\n }\n\n if (this.options.simrel?.enabled !== false) {\n const simRelTarget = this.options.simrel?.mountTarget ?? DEFAULT_SIMREL_MOUNT;\n const mountTarget = resolveMountTarget(simRelTarget);\n\n if (mountTarget) {\n this._warnedSimRelMountMissing = false;\n if (!this._simrel) {\n const simrel = new GengageSimRel();\n const simRelConfig: SimRelWidgetConfig = {\n accountId: this.options.accountId,\n middlewareUrl,\n session: this.session,\n sku,\n mountTarget,\n };\n if (this.options.theme !== undefined) simRelConfig.theme = this.options.theme;\n if (this.options.pricing !== undefined) simRelConfig.pricing = this.options.pricing;\n if (this.options.simrel?.discountType !== undefined) {\n simRelConfig.discountType = this.options.simrel.discountType;\n }\n if (this.options.simrel?.renderCardElement !== undefined) {\n simRelConfig.renderCardElement = this.options.simrel.renderCardElement;\n }\n if (this.options.simrel?.renderer !== undefined) {\n simRelConfig.renderer = this.options.simrel.renderer;\n }\n if (this.options.onAddToCart !== undefined) {\n simRelConfig.onAddToCart = this.options.onAddToCart;\n }\n if (this.options.onProductNavigate !== undefined) {\n simRelConfig.onProductNavigate = this.options.onProductNavigate;\n } else {\n simRelConfig.onProductNavigate = (url, productSku, sessionId) => {\n if (!isSafeUrl(url)) return;\n this._chat?.saveSession(sessionId ?? this.session.sessionId, productSku);\n window.location.href = url;\n };\n }\n await simrel.init(simRelConfig);\n this._simrel = simrel;\n } else {\n this._simrel.show();\n this._simrel.update({ pageType: 'pdp', sku });\n }\n } else {\n this._simrel?.destroy();\n this._simrel = null;\n if (!this._warnedSimRelMountMissing) {\n console.warn(`[gengage] SimRel mount target not found: ${simRelTarget}`);\n this._warnedSimRelMountMissing = true;\n }\n }\n } else {\n this._simrel?.destroy();\n this._simrel = null;\n }\n }\n\n private _destroyPdpWidgets(): void {\n this._qna?.destroy();\n this._simrel?.destroy();\n this._qna = null;\n this._simrel = null;\n }\n\n private _enqueue(fn: () => Promise<void>): Promise<void> {\n const next = this._queue.then(fn);\n this._queue = next.catch((err) => {\n if (import.meta.env?.DEV) {\n console.error('[gengage:overlay] Queued operation failed:', err);\n }\n });\n return next;\n }\n}\n\n/**\n * Initialize all three widgets (chat, QNA, SimRel) in a single call.\n * Idempotent — safe to call multiple times from GTM; deduplicates by account + SKU key.\n *\n * @example\n * ```ts\n * import { initOverlayWidgets } from '@gengage/assistant-fe';\n *\n * const controller = await initOverlayWidgets({\n * accountId: 'mystore',\n * middlewareUrl: 'https://chat.gengage.ai',\n * sku: window.productSku,\n * pageContext: { pageType: 'pdp' },\n * chat: { variant: 'floating' },\n * qna: { mountTarget: '#qna-section' },\n * simrel: { mountTarget: '#similar-products' },\n * });\n * ```\n */\nexport async function initOverlayWidgets(options: OverlayWidgetsOptions): Promise<OverlayWidgetsController> {\n const key = buildOverlayKey(options);\n const registry = getOverlayRegistry();\n\n const existing = registry.instances[key];\n if (existing) return existing;\n\n const pending = registry.pending[key];\n if (pending) return pending;\n\n const runtime = new OverlayWidgetsRuntime(options, () => {\n const liveRegistry = getOverlayRegistry();\n delete liveRegistry.instances[key];\n delete liveRegistry.pending[key];\n });\n\n const runtimeInit = runtime\n .init()\n .then(() => {\n registry.instances[key] = runtime;\n delete registry.pending[key];\n return runtime;\n })\n .catch((err) => {\n delete registry.pending[key];\n throw err;\n });\n\n registry.pending[key] = runtimeInit;\n return runtimeInit;\n}\n\nexport function getOverlayWidgets(idempotencyKey: string): OverlayWidgetsController | null {\n const registry = getOverlayRegistry();\n return registry.instances[idempotencyKey] ?? null;\n}\n\nexport function destroyOverlayWidgets(idempotencyKey: string): void {\n const controller = getOverlayWidgets(idempotencyKey);\n controller?.destroy();\n}\n\nexport function buildOverlayIdempotencyKey(accountId: string): string {\n return `${DEFAULT_OVERLAY_KEY_PREFIX}${accountId}`;\n}\n","import { initOverlayWidgets } from './overlay.js';\nimport type { OverlayWidgetsController, OverlayWidgetsOptions } from './overlay.js';\nimport type { PageContext } from './types.js';\n\nexport const DEFAULT_NATIVE_TRACKED_EVENTS = [\n 'gengage:chat:open',\n 'gengage:chat:close',\n 'gengage:chat:ready',\n 'gengage:chat:add-to-cart',\n 'gengage:qna:action',\n 'gengage:qna:open-chat',\n 'gengage:similar:product-click',\n 'gengage:similar:add-to-cart',\n 'gengage:global:error',\n 'gengage:context:update',\n] as const;\n\nexport type NativeTrackedEvent = (typeof DEFAULT_NATIVE_TRACKED_EVENTS)[number];\nexport type NativeInboundMessage = 'openChat' | 'closeChat' | 'updateContext' | 'updateSku' | 'setSession' | 'destroy';\n\nexport type NativeBridgeEnvironment = 'ios' | 'android' | 'react-native' | 'browser';\n\nexport interface NativeSessionPayload {\n sessionId?: string;\n userId?: string;\n}\n\nexport interface NativeBridgeMessage {\n type: string;\n payload?: unknown;\n}\n\nexport interface NativeWebViewBridgeOptions {\n iosHandlerName?: string;\n androidInterfaceName?: string;\n reactNativeInterfaceName?: string;\n trackedEvents?: NativeTrackedEvent[] | string[];\n /** Log unhandled inbound message types to console in addition to forwarding to postMessage. */\n logUnhandled?: boolean;\n /** Injected for tests; defaults to global window. */\n win?: Window;\n}\n\nexport interface NativeWebViewBridge {\n readonly env: NativeBridgeEnvironment;\n sendToNative(type: string, payload?: unknown): void;\n receive(message: NativeBridgeMessage | string): void;\n setController(controller: OverlayWidgetsController | null): void;\n destroy(): void;\n}\n\nexport interface NativeOverlayInitOptions extends OverlayWidgetsOptions {\n nativeBridge?: Omit<NativeWebViewBridgeOptions, 'win'>;\n emitReadyEvent?: boolean;\n}\n\nexport interface NativeOverlayInitResult {\n controller: OverlayWidgetsController;\n bridge: NativeWebViewBridge;\n destroy(): void;\n}\n\nconst MAX_QUEUED_NATIVE_COMMANDS = 32;\nconst DEFAULT_NATIVE_QNA_MOUNT = '#gengage-qna';\nconst DEFAULT_NATIVE_SIMREL_MOUNT = '#gengage-simrel';\n\ninterface NativeWindow extends Window {\n webkit?: {\n messageHandlers?: Record<string, { postMessage?: (message: unknown) => void }>;\n };\n GengageNative?: {\n postMessage?: (message: string) => void;\n };\n ReactNativeWebView?: {\n postMessage?: (message: string) => void;\n };\n gengageNative?: NativeWebViewBridge;\n}\n\nfunction toNativeWindow(win: Window): NativeWindow {\n return win as NativeWindow;\n}\n\nfunction parseNativeBridgeMessage(raw: NativeBridgeMessage | string): NativeBridgeMessage | null {\n let candidate: unknown = raw;\n\n if (typeof raw === 'string') {\n const trimmed = raw.trim();\n if (trimmed.length === 0) return null;\n\n // Allow plain command strings such as \"openChat\" from native evaluateJavaScript calls.\n if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {\n return { type: trimmed };\n }\n\n try {\n candidate = JSON.parse(trimmed);\n } catch {\n return null;\n }\n }\n\n if (!candidate || typeof candidate !== 'object') return null;\n const obj = candidate as Record<string, unknown>;\n\n const typeCandidate = [obj['type'], obj['command'], obj['action'], obj['event']].find(\n (value): value is string => typeof value === 'string' && value.length > 0,\n );\n if (!typeCandidate) return null;\n\n let payload = obj['payload'];\n if (payload === undefined && 'data' in obj) payload = obj['data'];\n\n // Common native shorthand:\n // { type: \"setSession\", sessionId: \"...\", userId: \"...\" }\n if (typeCandidate === 'setSession' && payload === undefined) {\n const sessionPayload: NativeSessionPayload = {};\n if (typeof obj['sessionId'] === 'string') sessionPayload.sessionId = obj['sessionId'];\n if (typeof obj['userId'] === 'string') sessionPayload.userId = obj['userId'];\n if (sessionPayload.sessionId !== undefined || sessionPayload.userId !== undefined) {\n payload = sessionPayload;\n }\n }\n\n return payload === undefined ? { type: typeCandidate } : { type: typeCandidate, payload };\n}\n\nfunction parseUpdateSkuPayload(payload: unknown): { sku: string; pageType?: PageContext['pageType'] } | null {\n if (typeof payload === 'string' && payload.length > 0) {\n return { sku: payload };\n }\n if (payload && typeof payload === 'object' && 'sku' in payload) {\n const sku = (payload as { sku?: unknown }).sku;\n if (typeof sku === 'string' && sku.length > 0) {\n const pageType = (payload as { pageType?: PageContext['pageType'] }).pageType;\n return pageType !== undefined ? { sku, pageType } : { sku };\n }\n }\n return null;\n}\n\nfunction hasMountTarget(win: Window, target: HTMLElement | string): boolean {\n if (target instanceof HTMLElement) return true;\n if (typeof target !== 'string') return false;\n return win.document.querySelector(target) !== null;\n}\n\nfunction ensureMountTarget(\n win: Window,\n preferredTarget: HTMLElement | string,\n fallbackId: string,\n): HTMLElement | string {\n if (preferredTarget instanceof HTMLElement) return preferredTarget;\n if (hasMountTarget(win, preferredTarget)) return preferredTarget;\n if (typeof preferredTarget !== 'string') return preferredTarget;\n\n // If target is a simple #id selector, create that mount.\n if (preferredTarget.startsWith('#')) {\n const id = preferredTarget.slice(1);\n if (id.length > 0) {\n const existing = win.document.getElementById(id);\n if (existing) return existing;\n const mount = win.document.createElement('div');\n mount.id = id;\n win.document.body.appendChild(mount);\n return mount;\n }\n }\n\n const fallback = win.document.getElementById(fallbackId);\n if (fallback) return fallback;\n const mount = win.document.createElement('div');\n mount.id = fallbackId;\n win.document.body.appendChild(mount);\n return mount;\n}\n\nfunction getIosPostMessage(win: Window, handlerName: string): ((message: unknown) => void) | null {\n const handler = toNativeWindow(win).webkit?.messageHandlers?.[handlerName];\n if (handler && typeof handler.postMessage === 'function') {\n return handler.postMessage.bind(handler);\n }\n return null;\n}\n\nfunction getNamedBridge(win: Window, interfaceName: string): { postMessage: (message: string) => void } | null {\n const candidate = (win as Window & Record<string, unknown>)[interfaceName];\n if (candidate && typeof candidate === 'object') {\n const postMessage = (candidate as { postMessage?: unknown }).postMessage;\n if (typeof postMessage === 'function') {\n return candidate as { postMessage: (message: string) => void };\n }\n }\n return null;\n}\n\nexport function detectNativeEnvironment(\n options: Pick<\n NativeWebViewBridgeOptions,\n 'iosHandlerName' | 'androidInterfaceName' | 'reactNativeInterfaceName' | 'win'\n > = {},\n): NativeBridgeEnvironment {\n const win = options.win ?? window;\n const iosHandlerName = options.iosHandlerName ?? 'gengage';\n const androidInterfaceName = options.androidInterfaceName ?? 'GengageNative';\n const reactNativeInterfaceName = options.reactNativeInterfaceName ?? 'ReactNativeWebView';\n\n if (getIosPostMessage(win, iosHandlerName)) return 'ios';\n if (getNamedBridge(win, androidInterfaceName)) return 'android';\n if (getNamedBridge(win, reactNativeInterfaceName)) return 'react-native';\n return 'browser';\n}\n\n/**\n * Applies native-provided session identity so widgets can share correlation IDs\n * with the host app. Safe to call before or after widget initialization.\n */\nexport function applyNativeSession(\n payload: NativeSessionPayload,\n options: Pick<NativeWebViewBridgeOptions, 'win'> = {},\n): void {\n const win = options.win ?? window;\n\n if (payload.sessionId !== undefined) {\n win.__gengageSessionId = payload.sessionId;\n if (!win.gengage) win.gengage = {};\n win.gengage.sessionId = payload.sessionId;\n try {\n win.sessionStorage.setItem('gengage_session_id', payload.sessionId);\n } catch {\n // sessionStorage can be unavailable in restricted WebView modes.\n }\n }\n\n if (payload.userId !== undefined) {\n if (!win.gengage) win.gengage = {};\n const bag = win.gengage as unknown as Record<string, unknown>;\n const session = (bag['session'] as Record<string, unknown> | undefined) ?? {};\n session['userId'] = payload.userId;\n bag['session'] = session;\n }\n}\n\n/**\n * Installs a native WebView bridge compatible with:\n * - iOS WKWebView (`webkit.messageHandlers`)\n * - Android JavascriptInterface (`window.GengageNative`)\n * - React Native WebView (`window.ReactNativeWebView`)\n * and exposes it on `window.gengageNative`.\n */\nexport function createNativeWebViewBridge(options: NativeWebViewBridgeOptions = {}): NativeWebViewBridge {\n const win = options.win ?? window;\n const nativeWin = toNativeWindow(win);\n if (nativeWin.gengageNative) return nativeWin.gengageNative;\n\n const iosHandlerName = options.iosHandlerName ?? 'gengage';\n const androidInterfaceName = options.androidInterfaceName ?? 'GengageNative';\n const reactNativeInterfaceName = options.reactNativeInterfaceName ?? 'ReactNativeWebView';\n const trackedEvents = options.trackedEvents ?? [...DEFAULT_NATIVE_TRACKED_EVENTS];\n const env = detectNativeEnvironment({ win, iosHandlerName, androidInterfaceName, reactNativeInterfaceName });\n\n let controller: OverlayWidgetsController | null = win.gengage?.overlay ?? null;\n const queuedCommands: NativeBridgeMessage[] = [];\n\n const sendToNative = (type: string, payload?: unknown): void => {\n const message: NativeBridgeMessage = payload === undefined ? { type } : { type, payload };\n\n if (env === 'ios') {\n const postMessage = getIosPostMessage(win, iosHandlerName);\n postMessage?.(message);\n return;\n }\n\n if (env === 'android') {\n const androidBridge = getNamedBridge(win, androidInterfaceName);\n androidBridge?.postMessage(JSON.stringify(message));\n return;\n }\n\n if (env === 'react-native') {\n const reactNativeBridge = getNamedBridge(win, reactNativeInterfaceName);\n reactNativeBridge?.postMessage(JSON.stringify(message));\n return;\n }\n\n // Browser fallback: no-op. Useful when running the same integration\n // outside a native WebView (desktop QA, local dev, docs previews).\n return;\n };\n\n const bridgeMessageHandler: EventListener = (event) => {\n const detail = (event as CustomEvent<{ namespace: string; type: string; payload?: unknown }>).detail;\n if (!detail || typeof detail.namespace !== 'string' || typeof detail.type !== 'string') return;\n sendToNative('bridge_message', {\n namespace: detail.namespace,\n type: detail.type,\n payload: detail.payload,\n });\n };\n\n win.addEventListener('gengage:bridge:message', bridgeMessageHandler);\n\n const trackedEventHandlers: Array<{ event: string; handler: EventListener }> = trackedEvents.map((eventName) => {\n const handler: EventListener = (event) => {\n const detail = (event as CustomEvent<unknown>).detail;\n sendToNative('widget_event', {\n event: eventName,\n detail,\n });\n };\n win.addEventListener(eventName, handler);\n return { event: eventName, handler };\n });\n\n const queueCommand = (command: NativeBridgeMessage): void => {\n if (queuedCommands.length >= MAX_QUEUED_NATIVE_COMMANDS) {\n queuedCommands.shift();\n }\n queuedCommands.push(command);\n };\n\n const flushQueuedCommands = (): void => {\n if (!controller || queuedCommands.length === 0) return;\n const pending = queuedCommands.splice(0, queuedCommands.length);\n for (const command of pending) {\n receive(command);\n }\n };\n\n const receive = (message: NativeBridgeMessage | string): void => {\n const incoming = parseNativeBridgeMessage(message);\n if (!incoming || typeof incoming.type !== 'string') {\n console.warn('[gengage:native-bridge] Invalid message:', message);\n return;\n }\n\n const type = incoming.type as NativeInboundMessage | string;\n const payload = incoming.payload;\n\n switch (type) {\n case 'openChat': {\n if (controller) {\n controller.openChat(\n payload && typeof payload === 'object'\n ? (payload as { state?: 'half' | 'full' })\n : payload === 'half' || payload === 'full'\n ? { state: payload }\n : undefined,\n );\n } else {\n queueCommand(incoming);\n }\n return;\n }\n\n case 'closeChat': {\n if (controller) {\n controller.closeChat();\n } else {\n queueCommand(incoming);\n }\n return;\n }\n\n case 'updateContext': {\n if (controller && payload && typeof payload === 'object') {\n void controller.updateContext(payload as Partial<PageContext>);\n } else if (!controller) {\n queueCommand(incoming);\n } else {\n console.warn('[gengage:native-bridge] updateContext: missing payload');\n }\n return;\n }\n\n case 'updateSku': {\n const parsed = parseUpdateSkuPayload(payload);\n if (controller && parsed) {\n void controller.updateSku(parsed.sku, parsed.pageType);\n return;\n }\n if (!controller) {\n queueCommand(incoming);\n } else {\n console.warn('[gengage:native-bridge] updateSku: missing sku');\n }\n return;\n }\n\n case 'setSession': {\n if (payload && typeof payload === 'object') {\n applyNativeSession(payload as NativeSessionPayload, { win });\n }\n return;\n }\n\n case 'destroy': {\n controller?.destroy();\n return;\n }\n\n default: {\n win.postMessage({ gengage: 'native', type, payload }, win.location.origin);\n if (options.logUnhandled) {\n console.warn('[gengage:native-bridge] Unhandled inbound type forwarded:', type);\n }\n }\n }\n };\n\n const bridge: NativeWebViewBridge = {\n env,\n sendToNative,\n receive,\n setController(nextController) {\n controller = nextController;\n flushQueuedCommands();\n },\n destroy() {\n win.removeEventListener('gengage:bridge:message', bridgeMessageHandler);\n for (const entry of trackedEventHandlers) {\n win.removeEventListener(entry.event, entry.handler);\n }\n queuedCommands.splice(0, queuedCommands.length);\n if (toNativeWindow(win).gengageNative === bridge) {\n delete toNativeWindow(win).gengageNative;\n }\n },\n };\n\n nativeWin.gengageNative = bridge;\n return bridge;\n}\n\n/**\n * Convenience helper for mobile WebViews:\n * 1) installs native bridge\n * 2) initializes overlay widgets\n * 3) sends a `ready` message to native\n */\nexport async function initNativeOverlayWidgets(options: NativeOverlayInitOptions): Promise<NativeOverlayInitResult> {\n const { nativeBridge, emitReadyEvent = true, ...overlayOptions } = options;\n const bridge = createNativeWebViewBridge(nativeBridge);\n const resolvedOptions: OverlayWidgetsOptions = { ...overlayOptions };\n\n // Mobile-app-friendly defaults:\n // 1) translate commerce callbacks to native bridge messages by default\n // 2) avoid noisy missing-mount warnings unless PDP widgets are explicitly requested\n if (!resolvedOptions.onAddToCart) {\n resolvedOptions.onAddToCart = (params) => {\n bridge.sendToNative('addToCart', {\n sku: params.sku,\n quantity: params.quantity,\n cartCode: params.cartCode,\n });\n };\n }\n\n if (!resolvedOptions.onProductNavigate) {\n resolvedOptions.onProductNavigate = (url, sku, sessionId) => {\n bridge.sendToNative('productNavigate', {\n url,\n sku,\n sessionId,\n });\n };\n }\n\n const qnaRequested = resolvedOptions.qna?.enabled === true || resolvedOptions.qna?.mountTarget !== undefined;\n if (resolvedOptions.qna?.enabled !== false) {\n if (qnaRequested) {\n const mountTarget = ensureMountTarget(\n window,\n resolvedOptions.qna?.mountTarget ?? DEFAULT_NATIVE_QNA_MOUNT,\n 'gengage-qna',\n );\n resolvedOptions.qna = { ...resolvedOptions.qna, enabled: true, mountTarget };\n } else if (!hasMountTarget(window, DEFAULT_NATIVE_QNA_MOUNT)) {\n resolvedOptions.qna = { enabled: false };\n }\n }\n\n const simrelRequested = resolvedOptions.simrel?.enabled === true || resolvedOptions.simrel?.mountTarget !== undefined;\n if (resolvedOptions.simrel?.enabled !== false) {\n if (simrelRequested) {\n const mountTarget = ensureMountTarget(\n window,\n resolvedOptions.simrel?.mountTarget ?? DEFAULT_NATIVE_SIMREL_MOUNT,\n 'gengage-simrel',\n );\n resolvedOptions.simrel = { ...resolvedOptions.simrel, enabled: true, mountTarget };\n } else if (!hasMountTarget(window, DEFAULT_NATIVE_SIMREL_MOUNT)) {\n resolvedOptions.simrel = { enabled: false };\n }\n }\n\n const controller = await initOverlayWidgets(resolvedOptions);\n bridge.setController(controller);\n\n if (emitReadyEvent) {\n bridge.sendToNative('ready', {\n sessionId: controller.session.sessionId,\n widgets: {\n chat: controller.chat !== null,\n qna: controller.qna !== null,\n simrel: controller.simrel !== null,\n },\n });\n }\n\n return {\n controller,\n bridge,\n destroy() {\n controller.destroy();\n bridge.destroy();\n },\n };\n}\n"],"names":["WidgetToggleSchema","z.object","z.boolean","MountSelectorsSchema","z.string","TransportSchema","AnalyticsAuthModeSchema","z.enum","AnalyticsAuthSchema","AnalyticsSchema","z.number","DEFAULT_IDEMPOTENCY_KEY","GTMSchema","UnknownActionPolicySchema","ActionHandlingSchema","AccountRuntimeConfigSchema","z.literal","parseAccountRuntimeConfig","input","debugLog","result","safeParseAccountRuntimeConfig","createDefaultAccountRuntimeConfig","params","DEFAULT_OVERLAY_KEY_PREFIX","DEFAULT_QNA_MOUNT","DEFAULT_SIMREL_MOUNT","getOverlayRegistry","win","buildInitialPageContext","options","base","incoming","mergePageContext","current","patch","next","resolveMountTarget","target","buildOverlayKey","OverlayWidgetsRuntime","onDestroy","resolveSession","wireQNAToChat","sku","pageType","middlewareUrl","config","GengageChat","qnaTarget","mountTarget","qna","GengageQNA","qnaConfig","simRelTarget","simrel","GengageSimRel","simRelConfig","url","productSku","sessionId","isSafeUrl","fn","err","initOverlayWidgets","key","registry","existing","pending","runtime","liveRegistry","runtimeInit","getOverlayWidgets","idempotencyKey","destroyOverlayWidgets","buildOverlayIdempotencyKey","accountId","DEFAULT_NATIVE_TRACKED_EVENTS","MAX_QUEUED_NATIVE_COMMANDS","DEFAULT_NATIVE_QNA_MOUNT","DEFAULT_NATIVE_SIMREL_MOUNT","parseNativeBridgeMessage","raw","candidate","trimmed","obj","typeCandidate","value","payload","sessionPayload","parseUpdateSkuPayload","hasMountTarget","ensureMountTarget","preferredTarget","fallbackId","id","mount","fallback","getIosPostMessage","handlerName","handler","getNamedBridge","interfaceName","detectNativeEnvironment","iosHandlerName","androidInterfaceName","reactNativeInterfaceName","applyNativeSession","bag","session","createNativeWebViewBridge","nativeWin","trackedEvents","env","controller","queuedCommands","sendToNative","type","message","bridgeMessageHandler","event","detail","trackedEventHandlers","eventName","queueCommand","command","flushQueuedCommands","receive","parsed","bridge","nextController","entry","initNativeOverlayWidgets","nativeBridge","emitReadyEvent","overlayOptions","resolvedOptions","qnaRequested","simrelRequested"],"mappings":"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"}