@beworke/pixel 0.1.0-rc.7 → 0.1.0-rc.9

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 (150) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/README.md +71 -56
  3. package/RELEASE_CANDIDATE.md +28 -62
  4. package/dist/Pixel-BnN86r4X.d.ts +797 -0
  5. package/dist/Pixel-BoUGqCbP.d.mts +797 -0
  6. package/dist/{StorageFactory-DeMaZ8wk.d.ts → StorageFactory-BfCArzMM.d.ts} +1 -1
  7. package/dist/{StorageFactory-Cq29vF32.d.mts → StorageFactory-C0prtNR7.d.mts} +1 -1
  8. package/dist/browser/index.cjs.js +3 -0
  9. package/dist/browser/index.cjs.js.map +1 -0
  10. package/dist/browser/index.d.mts +55 -0
  11. package/dist/browser/index.d.ts +55 -0
  12. package/dist/browser/index.esm.js +3 -0
  13. package/dist/browser/index.esm.js.map +1 -0
  14. package/dist/browser/pixel.global.js +4 -0
  15. package/dist/browser/pixel.global.js.map +1 -0
  16. package/dist/config/index.cjs.js +1 -1
  17. package/dist/config/index.cjs.js.map +1 -1
  18. package/dist/config/index.d.mts +15 -5
  19. package/dist/config/index.d.ts +15 -5
  20. package/dist/config/index.esm.js +1 -1
  21. package/dist/config/index.esm.js.map +1 -1
  22. package/dist/examples/html-script/RELEASE_CANDIDATE.md +6 -8
  23. package/dist/examples/html-script/add-payment-info/example-add-payment-info-card-autocomplete.html +40 -47
  24. package/dist/examples/html-script/add-payment-info/example-add-payment-info-card-disabled.html +40 -47
  25. package/dist/examples/html-script/add-payment-info/example-add-payment-info-card-fields.html +40 -47
  26. package/dist/examples/html-script/add-payment-info/example-add-payment-info-data-track.html +40 -47
  27. package/dist/examples/html-script/add-payment-info/example-add-payment-info-dedupe.html +40 -47
  28. package/dist/examples/html-script/add-payment-info/example-add-payment-info-manual.html +40 -47
  29. package/dist/examples/html-script/add-payment-info/example-add-payment-info-rules-card.html +40 -47
  30. package/dist/examples/html-script/add-payment-info/example-add-payment-info-security.html +40 -47
  31. package/dist/examples/html-script/add-to-cart/example-add-to-cart-attribute.html +40 -47
  32. package/dist/examples/html-script/add-to-cart/example-add-to-cart-auto.html +40 -47
  33. package/dist/examples/html-script/add-to-cart/example-add-to-cart-click.html +40 -47
  34. package/dist/examples/html-script/add-to-cart/example-add-to-cart-dedupe.html +40 -47
  35. package/dist/examples/html-script/add-to-cart/example-add-to-cart-link.html +40 -47
  36. package/dist/examples/html-script/add-to-cart/example-add-to-cart-manual.html +40 -47
  37. package/dist/examples/html-script/add-to-cart/example-add-to-cart-order-bump.html +40 -47
  38. package/dist/examples/html-script/add-to-cart/example-add-to-cart-text.html +40 -47
  39. package/dist/examples/html-script/behavior/example-behavior-engagement.html +4 -4
  40. package/dist/examples/html-script/behavior/example-behavior-heartbeat.html +4 -4
  41. package/dist/examples/html-script/behavior/example-behavior-runtime-intelligence.html +4 -4
  42. package/dist/examples/html-script/behavior/example-behavior-viewport.html +4 -4
  43. package/dist/examples/html-script/buygoods/example-buygoods-checkout.html +156 -0
  44. package/dist/examples/html-script/example-checkout-commerce.html +31 -30
  45. package/dist/examples/html-script/example-conversion.html +41 -48
  46. package/dist/examples/html-script/example-global-factory-classic.html +45 -0
  47. package/dist/examples/html-script/example-global-factory.html +40 -0
  48. package/dist/examples/html-script/example-integration.html +39 -45
  49. package/dist/examples/html-script/example-landing-commerce.html +3 -8
  50. package/dist/examples/html-script/example-runtime-diagnostics.html +4 -4
  51. package/dist/examples/html-script/example-transport.html +59 -57
  52. package/dist/examples/html-script/full-funnel/checkout.html +3 -1
  53. package/dist/examples/html-script/full-funnel/downsell.html +3 -1
  54. package/dist/examples/html-script/full-funnel/landing.html +3 -1
  55. package/dist/examples/html-script/full-funnel/thank-you.html +3 -1
  56. package/dist/examples/html-script/full-funnel/upsell.html +3 -1
  57. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-attribute.html +40 -47
  58. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-auto.html +40 -47
  59. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-click.html +40 -47
  60. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-manual.html +40 -47
  61. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-snapshot.html +40 -47
  62. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-submit.html +40 -47
  63. package/dist/examples/html-script/initiate-checkout/example-initiate-checkout-text.html +40 -47
  64. package/dist/examples/html-script/lead/example-lead-trigger-attribute.html +40 -47
  65. package/dist/examples/html-script/lead/example-lead-trigger-auto.html +40 -47
  66. package/dist/examples/html-script/lead/example-lead-trigger-click.html +40 -47
  67. package/dist/examples/html-script/release-candidate.html +31 -30
  68. package/dist/examples/html-script/remove-from-cart/README.md +3 -3
  69. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-attribute.html +40 -47
  70. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-css.html +40 -47
  71. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-dedupe.html +47 -54
  72. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-manual.html +40 -47
  73. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-multi.html +40 -47
  74. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-state.html +40 -47
  75. package/dist/examples/html-script/remove-from-cart/example-remove-from-cart-text.html +40 -47
  76. package/dist/examples/html-script/search/example-search-attribute.html +40 -47
  77. package/dist/examples/html-script/search/example-search-button-sync.html +40 -47
  78. package/dist/examples/html-script/search/example-search-dedupe.html +40 -47
  79. package/dist/examples/html-script/search/example-search-input.html +40 -47
  80. package/dist/examples/html-script/search/example-search-manual.html +40 -47
  81. package/dist/examples/html-script/search/example-search-submit.html +40 -47
  82. package/dist/examples/html-script/search/example-search-text.html +40 -47
  83. package/dist/examples/html-script/url-context/example-url-context-allowed-domains.html +4 -4
  84. package/dist/examples/html-script/url-context/example-url-context-landing.html +4 -4
  85. package/dist/examples/html-script/url-context/example-url-context-upsell.html +4 -4
  86. package/dist/examples/html-script/url-context/example-url-context.html +4 -4
  87. package/dist/examples/html-script/view-content/example-view-content-attribute.html +40 -47
  88. package/dist/examples/html-script/view-content/example-view-content-css.html +40 -47
  89. package/dist/examples/html-script/view-content/example-view-content-dedupe.html +40 -47
  90. package/dist/examples/html-script/view-content/example-view-content-empty.html +40 -47
  91. package/dist/examples/html-script/view-content/example-view-content-manual.html +40 -47
  92. package/dist/examples/html-script/view-content/example-view-content-product-card.html +40 -47
  93. package/dist/examples/html-script/view-content/example-view-content-text.html +40 -47
  94. package/dist/index.cjs.js +1 -1
  95. package/dist/index.cjs.js.map +1 -1
  96. package/dist/index.d.mts +8 -6
  97. package/dist/index.d.ts +8 -6
  98. package/dist/index.esm.js +1 -1
  99. package/dist/index.esm.js.map +1 -1
  100. package/dist/{pixel-2uL4LSyC.d.ts → pixel-DNGbAN5C.d.ts} +117 -98
  101. package/dist/{pixel-DMwpppf_.d.mts → pixel-_BSDpx4M.d.mts} +117 -98
  102. package/dist/pixel-default-config-BMYaqs7i.d.ts +21 -0
  103. package/dist/pixel-default-config-DLRya1tl.d.mts +21 -0
  104. package/dist/pixel-settings-D-t9zQb4.d.ts +40 -0
  105. package/dist/pixel-settings-DGxl0MVm.d.mts +40 -0
  106. package/dist/runtime/index.cjs.js +1 -1
  107. package/dist/runtime/index.cjs.js.map +1 -1
  108. package/dist/runtime/index.d.mts +4 -4
  109. package/dist/runtime/index.d.ts +4 -4
  110. package/dist/runtime/index.esm.js +1 -1
  111. package/dist/runtime/index.esm.js.map +1 -1
  112. package/dist/services/index.cjs.js +1 -1
  113. package/dist/services/index.cjs.js.map +1 -1
  114. package/dist/services/index.d.mts +4 -4
  115. package/dist/services/index.d.ts +4 -4
  116. package/dist/services/index.esm.js +1 -1
  117. package/dist/services/index.esm.js.map +1 -1
  118. package/dist/{types-6HF3UlsL.d.mts → types-B-Nzagpk.d.mts} +2 -2
  119. package/dist/{types-CgrabttM.d.mts → types-D0KVsgzs.d.mts} +1 -1
  120. package/dist/{types-fFcQ1apy.d.ts → types-D3kJ9bfT.d.ts} +1 -1
  121. package/dist/{types-BqUEoZo0.d.ts → types-Dfi9C49l.d.ts} +2 -2
  122. package/dist/v2/global.global.js +1 -1
  123. package/dist/v2/global.global.js.map +1 -1
  124. package/dist/v2/index.cjs.js +1 -1
  125. package/dist/v2/index.cjs.js.map +1 -1
  126. package/dist/v2/index.d.mts +21 -787
  127. package/dist/v2/index.d.ts +21 -787
  128. package/dist/v2/index.esm.js +1 -1
  129. package/dist/v2/index.esm.js.map +1 -1
  130. package/docs/public/README.md +7 -4
  131. package/docs/public/api/exports.md +12 -8
  132. package/docs/public/api/pixel.md +27 -6
  133. package/docs/public/configuration/commerce.md +2 -2
  134. package/docs/public/configuration/modules.md +11 -14
  135. package/docs/public/configuration/overview.md +45 -26
  136. package/docs/public/configuration/transport.md +127 -0
  137. package/docs/public/events/catalog.md +3 -1
  138. package/docs/public/getting-started/installation.md +14 -12
  139. package/docs/public/getting-started/quick-start.md +95 -30
  140. package/docs/public/getting-started/react-nextjs.md +57 -34
  141. package/docs/public/getting-started/script-tag.md +55 -32
  142. package/docs/public/guides/funnel-checkout.md +1 -1
  143. package/docs/public/guides/funnel-landing.md +9 -7
  144. package/docs/public/limitations.md +5 -4
  145. package/docs/public/privacy/limitations.md +6 -6
  146. package/docs/public/release-candidate/validation.md +4 -4
  147. package/docs/public/troubleshooting.md +7 -6
  148. package/package.json +8 -3
  149. package/dist/pixel-default-config-BDPUVHse.d.ts +0 -5
  150. package/dist/pixel-default-config-C5uLt52W.d.mts +0 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/services/dispatcher/DispatcherService.ts","../../src/services/browser-metadata/BrowserMetadataService.ts","../../src/services/fingerprint/FingerprintService.ts","../../src/services/session/session-id.ts","../../src/services/session/SessionService.ts","../../src/services/storage/BrowserStorageAdapter.ts","../../src/services/storage/MemoryStorageAdapter.ts","../../src/services/storage/StorageService.ts","../../src/services/storage/StorageFactory.ts","../../src/services/visitor/visitor-id.ts","../../src/services/visitor/VisitorService.ts","../../src/services/attribution/types.ts","../../src/services/attribution/ClickIdParser.ts","../../src/services/attribution/CookieCollector.ts","../../src/services/attribution/AttributionCollector.ts","../../src/services/attribution/AttributionStore.ts","../../src/services/attribution/AttributionService.ts","../../src/services/commerce/ProductCatalog.ts","../../src/services/commerce/CommerceState.ts","../../src/services/commerce/OrderCalculator.ts","../../src/config/shared/commerce.ts","../../src/services/commerce/CommerceResolver.ts","../../src/services/commerce/CommerceService.ts"],"sourcesContent":["import type { PixelEvent } from '@/events';\nimport type { PixelLogger } from '@/logger/PixelLogger';\n\nimport type { DispatcherService } from './types';\n\ntype EventListener = (event: PixelEvent) => void;\n\nconst MAX_ERROR_MESSAGE_LENGTH = 200;\n\n/**\n * Hardening 18.1 — falha de um listener não interrompe os demais nem propaga\n * para o produtor (trackers/engines). Log sanitizado, sem payload/PII.\n */\nexport class DispatcherServiceImpl implements DispatcherService {\n private readonly listeners = new Set<EventListener>();\n\n private lastEvent: PixelEvent | null = null;\n\n private readonly logger: Pick<PixelLogger, 'warn'> | undefined;\n\n constructor(logger?: Pick<PixelLogger, 'warn'>) {\n this.logger = logger;\n }\n\n dispatch(event: PixelEvent): void {\n this.lastEvent = event;\n\n // Snapshot: permite unsubscribe durante dispatch sem pular listeners.\n const snapshot = [...this.listeners];\n\n for (let index = 0; index < snapshot.length; index += 1) {\n const listener = snapshot[index];\n if (!listener) continue;\n\n try {\n listener(event);\n } catch (error) {\n this.logger?.warn(sanitizeDispatcherError(error, event.type, index));\n }\n }\n }\n\n subscribe(listener: (event: PixelEvent) => void): () => void {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n clear(): void {\n this.listeners.clear();\n this.lastEvent = null;\n }\n\n getListenerCount(): number {\n return this.listeners.size;\n }\n\n getLastEvent(): PixelEvent | null {\n return this.lastEvent;\n }\n}\n\nexport function sanitizeDispatcherError(\n error: unknown,\n eventType: string,\n listenerIndex: number\n): Record<string, unknown> {\n const name =\n error instanceof Error\n ? error.name\n : typeof error === 'object' && error !== null && 'name' in error\n ? String((error as { name: unknown }).name)\n : 'Error';\n\n let message =\n error instanceof Error\n ? error.message\n : typeof error === 'string'\n ? error\n : 'unknown';\n\n message = message\n .replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g, '[redacted]')\n .replace(/\\+?\\d[\\d\\s().-]{7,}\\d/g, '[redacted]');\n\n if (message.length > MAX_ERROR_MESSAGE_LENGTH) {\n message = `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}…`;\n }\n\n return {\n code: 'DISPATCHER_LISTENER_FAILED',\n eventType,\n listenerIndex,\n errorName: name,\n message,\n timestamp: Date.now(),\n };\n}\n","import type { BrowserMetadata, BrowserMetadataService } from './types';\n\nexport class BrowserMetadataServiceImpl implements BrowserMetadataService {\n getMetadata(): BrowserMetadata {\n if (typeof window === 'undefined') {\n return {};\n }\n\n const timezone = (() => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n return undefined;\n }\n })();\n\n return {\n url: location.href,\n path: location.pathname,\n hostname: location.hostname,\n origin: location.origin,\n title: typeof document !== 'undefined' ? document.title : undefined,\n referrer: typeof document !== 'undefined' ? document.referrer : undefined,\n language: navigator.language,\n timezone,\n userAgent: navigator.userAgent,\n platform: navigator.platform,\n screenWidth: screen.width,\n screenHeight: screen.height,\n colorDepth: screen.colorDepth,\n };\n }\n}\n","import type { PixelConfig } from '@/config';\nimport type { BrowserMetadataService } from '@/services/browser-metadata';\nimport type { StorageService } from '@/services/storage';\n\nimport type { FingerprintService } from './types';\n\nconst DEFAULT_FINGERPRINT_KEY = 'fingerprint';\n\nfunction hashFingerprintInput(input: string): string {\n let hash = 0;\n\n for (let index = 0; index < input.length; index++) {\n hash = (hash << 5) - hash + input.charCodeAt(index);\n hash |= 0;\n }\n\n const positiveHash = Math.abs(hash).toString(16).padStart(8, '0');\n let secondaryHash = 0;\n\n for (let index = input.length - 1; index >= 0; index--) {\n secondaryHash =\n (secondaryHash << 5) - secondaryHash + input.charCodeAt(index);\n secondaryHash |= 0;\n }\n\n return `fp_${positiveHash}${Math.abs(secondaryHash).toString(16).padStart(8, '0')}`;\n}\n\nfunction computeLightFingerprint(\n metadataService: BrowserMetadataService\n): string {\n const metadata = metadataService.getMetadata();\n\n const components = [\n metadata.userAgent ?? '',\n metadata.language ?? '',\n metadata.platform ?? '',\n String(metadata.screenWidth ?? ''),\n String(metadata.screenHeight ?? ''),\n String(metadata.colorDepth ?? ''),\n metadata.timezone ?? '',\n ];\n\n return hashFingerprintInput(components.join('|'));\n}\n\nexport class FingerprintServiceImpl implements FingerprintService {\n private readonly storage: StorageService;\n\n private readonly storageKey: string;\n\n private readonly metadataService: BrowserMetadataService;\n\n constructor(\n storage: StorageService,\n config: PixelConfig,\n metadataService: BrowserMetadataService\n ) {\n this.storage = storage;\n this.storageKey =\n config.storage.keys?.fingerprint ?? DEFAULT_FINGERPRINT_KEY;\n this.metadataService = metadataService;\n }\n\n getFingerprint(): string | null {\n return this.storage.get<string>(this.storageKey);\n }\n\n ensureFingerprint(): string {\n const existing = this.getFingerprint();\n if (existing) return existing;\n\n const fingerprint = computeLightFingerprint(this.metadataService);\n this.storage.set(this.storageKey, fingerprint);\n return fingerprint;\n }\n}\n","function createRandomSuffix(): string {\n if (\n typeof crypto !== 'undefined' &&\n typeof crypto.randomUUID === 'function'\n ) {\n return crypto.randomUUID().replace(/-/g, '');\n }\n\n return `${Date.now()}${Math.random().toString(36).slice(2)}`;\n}\n\nexport function generateSessionId(): string {\n return `ses_${createRandomSuffix()}`;\n}\n","import type { PixelConfig } from '@/config';\nimport type { StorageService } from '@/services/storage';\n\nimport type { EnsureSessionResult, SessionData, SessionService } from './types';\nimport { generateSessionId } from './session-id';\n\nconst DEFAULT_SESSION_KEY = 'session';\n\nexport class SessionServiceImpl implements SessionService {\n private readonly storage: StorageService;\n\n private readonly storageKey: string;\n\n constructor(storage: StorageService, config: PixelConfig) {\n this.storage = storage;\n this.storageKey = config.storage.keys?.session ?? DEFAULT_SESSION_KEY;\n }\n\n getSessionId(): string | null {\n return this.getSessionData()?.sessionId ?? null;\n }\n\n getSessionData(): SessionData | null {\n const raw = this.storage.get<SessionData | string>(this.storageKey);\n if (!raw) return null;\n\n if (typeof raw === 'string') {\n const now = Date.now();\n return {\n sessionId: raw,\n lastActivityAt: now,\n createdAt: now,\n };\n }\n\n return raw;\n }\n\n getLastActivityAt(): number | null {\n return this.getSessionData()?.lastActivityAt ?? null;\n }\n\n isExpired(ttlMs: number): boolean {\n const data = this.getSessionData();\n if (!data) return true;\n\n return Date.now() - data.lastActivityAt > ttlMs;\n }\n\n ensureSession(ttlMs: number): EnsureSessionResult {\n const data = this.getSessionData();\n const now = Date.now();\n\n if (!data) {\n const sessionId = generateSessionId();\n this.writeSessionData({\n sessionId,\n lastActivityAt: now,\n createdAt: now,\n });\n\n return {\n sessionId,\n expired: false,\n created: true,\n };\n }\n\n if (now - data.lastActivityAt > ttlMs) {\n const previousSessionId = data.sessionId;\n const sessionId = generateSessionId();\n\n this.writeSessionData({\n sessionId,\n lastActivityAt: now,\n createdAt: now,\n });\n\n return {\n sessionId,\n expired: true,\n previousSessionId,\n created: false,\n };\n }\n\n return {\n sessionId: data.sessionId,\n expired: false,\n created: false,\n };\n }\n\n ensureSessionId(): string {\n return this.ensureSession(Number.MAX_SAFE_INTEGER).sessionId;\n }\n\n touchActivity(): void {\n const data = this.getSessionData();\n if (!data) return;\n\n this.writeSessionData({\n ...data,\n lastActivityAt: Date.now(),\n });\n }\n\n renew(): string {\n const now = Date.now();\n const sessionId = generateSessionId();\n\n this.writeSessionData({\n sessionId,\n lastActivityAt: now,\n createdAt: now,\n });\n\n return sessionId;\n }\n\n clear(): void {\n this.storage.remove(this.storageKey);\n }\n\n private writeSessionData(data: SessionData): void {\n this.storage.set(this.storageKey, data);\n }\n}\n","import type { StorageAdapter } from './types';\n\nexport class BrowserStorageAdapter implements StorageAdapter {\n private readonly storage: Storage | null;\n\n private readonly memoryFallback = new Map<string, string>();\n\n constructor(storage: Storage) {\n this.storage = typeof window === 'undefined' ? null : storage;\n }\n\n get(key: string): string | null {\n if (this.storage) {\n return this.storage.getItem(key);\n }\n\n return this.memoryFallback.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n if (this.storage) {\n this.storage.setItem(key, value);\n return;\n }\n\n this.memoryFallback.set(key, value);\n }\n\n remove(key: string): void {\n if (this.storage) {\n this.storage.removeItem(key);\n return;\n }\n\n this.memoryFallback.delete(key);\n }\n\n clear(): void {\n // Never clear entire browser storage — namespace removal uses removeKeysMatching.\n if (!this.storage) {\n this.memoryFallback.clear();\n }\n }\n\n removeKeysMatching(predicate: (key: string) => boolean): void {\n if (this.storage) {\n const keysToRemove: string[] = [];\n\n for (let index = 0; index < this.storage.length; index++) {\n const key = this.storage.key(index);\n if (key && predicate(key)) {\n keysToRemove.push(key);\n }\n }\n\n for (const key of keysToRemove) {\n this.storage.removeItem(key);\n }\n\n return;\n }\n\n for (const key of this.memoryFallback.keys()) {\n if (predicate(key)) {\n this.memoryFallback.delete(key);\n }\n }\n }\n}\n","import type { StorageAdapter } from './types';\n\nexport class MemoryStorageAdapter implements StorageAdapter {\n private readonly store = new Map<string, string>();\n\n get(key: string): string | null {\n return this.store.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.store.set(key, value);\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n removeKeysMatching(predicate: (key: string) => boolean): void {\n for (const key of this.store.keys()) {\n if (predicate(key)) {\n this.store.delete(key);\n }\n }\n }\n}\n","import type { StorageAdapter, StorageService } from './types';\n\ntype NamespaceClearableAdapter = StorageAdapter & {\n removeKeysMatching(predicate: (key: string) => boolean): void;\n};\n\nfunction supportsNamespaceClear(\n adapter: StorageAdapter\n): adapter is NamespaceClearableAdapter {\n return (\n 'removeKeysMatching' in adapter &&\n typeof adapter.removeKeysMatching === 'function'\n );\n}\n\nexport class StorageServiceImpl implements StorageService {\n private readonly adapter: StorageAdapter;\n\n private readonly namespace: string;\n\n private readonly prefix?: string;\n\n constructor(adapter: StorageAdapter, namespace: string, prefix?: string) {\n this.adapter = adapter;\n this.namespace = namespace;\n this.prefix = prefix;\n }\n\n get<T>(key: string): T | null {\n const raw = this.adapter.get(this.createKey(key));\n if (raw === null) return null;\n\n try {\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T): void {\n this.adapter.set(this.createKey(key), JSON.stringify(value));\n }\n\n remove(key: string): void {\n this.adapter.remove(this.createKey(key));\n }\n\n has(key: string): boolean {\n return this.adapter.get(this.createKey(key)) !== null;\n }\n\n clear(): void {\n const namespaceKeyPrefix = this.getNamespaceKeyPrefix();\n\n if (supportsNamespaceClear(this.adapter)) {\n this.adapter.removeKeysMatching(key =>\n key.startsWith(namespaceKeyPrefix)\n );\n return;\n }\n\n this.adapter.clear();\n }\n\n createKey(key: string): string {\n if (this.prefix) {\n return `${this.prefix}:${this.namespace}:${key}`;\n }\n\n return `${this.namespace}:${key}`;\n }\n\n private getNamespaceKeyPrefix(): string {\n if (this.prefix) {\n return `${this.prefix}:${this.namespace}:`;\n }\n\n return `${this.namespace}:`;\n }\n}\n","import type {\n AttributionStoragePersistence,\n QueueStoragePersistence,\n SessionStoragePersistence,\n VisitorStoragePersistence,\n} from '@/config/shared/persistence';\n\nimport { BrowserStorageAdapter } from './BrowserStorageAdapter';\nimport { MemoryStorageAdapter } from './MemoryStorageAdapter';\nimport type { StorageAdapter } from './types';\n\nexport type StoragePersistence =\n | VisitorStoragePersistence\n | SessionStoragePersistence\n | AttributionStoragePersistence\n | QueueStoragePersistence;\n\nexport function createStorageAdapter(\n persistence?: StoragePersistence\n): StorageAdapter {\n const mode = persistence ?? 'memory';\n\n if (typeof window === 'undefined') {\n return new MemoryStorageAdapter();\n }\n\n switch (mode) {\n case 'memory':\n return new MemoryStorageAdapter();\n case 'localStorage':\n return new BrowserStorageAdapter(window.localStorage);\n case 'sessionStorage':\n return new BrowserStorageAdapter(window.sessionStorage);\n case 'cookie_localStorage':\n // TODO: implementar cookie fallback.\n return new BrowserStorageAdapter(window.localStorage);\n case 'cookie':\n return new MemoryStorageAdapter();\n case 'indexedDB':\n return new MemoryStorageAdapter();\n default:\n return new MemoryStorageAdapter();\n }\n}\n\nexport function resolveStorageAdapterName(\n persistence?: StoragePersistence\n): string {\n const mode = persistence ?? 'memory';\n\n switch (mode) {\n case 'localStorage':\n case 'sessionStorage':\n case 'cookie_localStorage':\n return 'BrowserStorageAdapter';\n default:\n return 'MemoryStorageAdapter';\n }\n}\n","function createRandomSuffix(): string {\n if (\n typeof crypto !== 'undefined' &&\n typeof crypto.randomUUID === 'function'\n ) {\n return crypto.randomUUID().replace(/-/g, '');\n }\n\n return `${Date.now()}${Math.random().toString(36).slice(2)}`;\n}\n\nexport function generateVisitorId(): string {\n return `vst_${createRandomSuffix()}`;\n}\n","import type { PixelConfig } from '@/config';\nimport type { StorageService } from '@/services/storage';\n\nimport type { VisitorService } from './types';\nimport { generateVisitorId } from './visitor-id';\n\nconst DEFAULT_VISITOR_KEY = 'visitor';\n\nexport class VisitorServiceImpl implements VisitorService {\n private readonly storage: StorageService;\n\n private readonly storageKey: string;\n\n constructor(storage: StorageService, config: PixelConfig) {\n this.storage = storage;\n this.storageKey = config.storage.keys?.visitor ?? DEFAULT_VISITOR_KEY;\n }\n\n getVisitorId(): string | null {\n return this.storage.get<string>(this.storageKey);\n }\n\n ensureVisitorId(): string {\n const existing = this.getVisitorId();\n if (existing) return existing;\n\n const visitorId = generateVisitorId();\n this.storage.set(this.storageKey, visitorId);\n return visitorId;\n }\n\n clearVisitorId(): void {\n this.storage.remove(this.storageKey);\n }\n}\n","export type AttributionIdentifiers = {\n readonly fbclid?: string;\n readonly fbp?: string;\n readonly fbc?: string;\n\n readonly gclid?: string;\n readonly gbraid?: string;\n readonly wbraid?: string;\n readonly ga?: string;\n readonly gid?: string;\n readonly gclAu?: string;\n\n readonly ttclid?: string;\n readonly ttp?: string;\n\n readonly msclkid?: string;\n readonly liFatId?: string;\n readonly epik?: string;\n\n readonly customClickIds?: Readonly<Record<string, string>>;\n\n readonly firstCollectedAt?: number;\n readonly lastCollectedAt?: number;\n readonly landingUrl?: string;\n readonly referrer?: string;\n};\n\nexport type AttributionConfig = {\n readonly enabled: boolean;\n readonly ttlDays?: number;\n readonly persist?: boolean;\n readonly captureUrlParams?: boolean;\n readonly captureCookies?: boolean;\n readonly customClickIdParams?: string[];\n};\n\nexport const DEFAULT_ATTRIBUTION_CONFIG: AttributionConfig = {\n enabled: true,\n ttlDays: 90,\n persist: true,\n captureUrlParams: true,\n captureCookies: true,\n customClickIdParams: [],\n};\n\nexport const ATTRIBUTION_STORAGE_KEY = 'attribution';\n\nexport interface AttributionService {\n init(): void;\n destroy(): void;\n collect(): AttributionIdentifiers;\n getSnapshot(): AttributionIdentifiers;\n update(partial: Partial<AttributionIdentifiers>): AttributionIdentifiers;\n clear(): void;\n}\n","import type { AttributionIdentifiers } from './types';\n\nconst BUILTIN_CLICK_PARAMS = [\n 'fbclid',\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'ttclid',\n 'msclkid',\n 'epik',\n 'li_fat_id',\n] as const;\n\n/**\n * Parses click IDs from URL search params and maps to AttributionIdentifiers fields.\n */\nexport class ClickIdParser {\n parse(customParams: readonly string[] = []): Partial<AttributionIdentifiers> {\n if (typeof window === 'undefined' || !window.location?.search) {\n return {};\n }\n\n try {\n const params = new URLSearchParams(window.location.search);\n const result: Record<string, unknown> = {};\n const customClickIds: Record<string, string> = {};\n\n for (const key of BUILTIN_CLICK_PARAMS) {\n const value = params.get(key);\n if (!value) continue;\n\n if (key === 'li_fat_id') {\n result.liFatId = value;\n } else {\n result[key] = value;\n }\n }\n\n for (const key of customParams) {\n const value = params.get(key);\n if (value) customClickIds[key] = value;\n }\n\n if (Object.keys(customClickIds).length > 0) {\n result.customClickIds = customClickIds;\n }\n\n return result as Partial<AttributionIdentifiers>;\n } catch {\n return {};\n }\n }\n\n /**\n * Meta convention: when fbclid is present and _fbc cookie is missing,\n * synthesize fbc = fb.1.<timestamp_ms>.<fbclid>\n */\n synthesizeFbc(fbclid: string, existingFbc?: string): string | undefined {\n if (existingFbc) return existingFbc;\n if (!fbclid) return undefined;\n return `fb.1.${Date.now()}.${fbclid}`;\n }\n}\n","/**\n * SSR-safe cookie reader for attribution identifiers.\n */\nexport class CookieCollector {\n collectKnown(): Readonly<Record<string, string>> {\n if (typeof document === 'undefined') return {};\n\n const cookies = this.parseCookies();\n const result: Record<string, string> = {};\n\n const map: Record<string, string> = {\n _fbp: 'fbp',\n _fbc: 'fbc',\n _ga: 'ga',\n _gid: 'gid',\n _gcl_au: 'gclAu',\n _ttp: 'ttp',\n li_fat_id: 'liFatId',\n epik: 'epik',\n };\n\n for (const [cookieName, field] of Object.entries(map)) {\n const value = cookies[cookieName];\n if (value) result[field] = value;\n }\n\n return result;\n }\n\n private parseCookies(): Record<string, string> {\n if (typeof document === 'undefined') return {};\n\n try {\n return document.cookie.split(';').reduce(\n (acc, part) => {\n const [rawKey, ...rest] = part.trim().split('=');\n if (!rawKey) return acc;\n acc[rawKey] = decodeURIComponent(rest.join('=') || '');\n return acc;\n },\n {} as Record<string, string>\n );\n } catch {\n return {};\n }\n }\n}\n","import type { AttributionIdentifiers } from './types';\nimport { ClickIdParser } from './ClickIdParser';\nimport { CookieCollector } from './CookieCollector';\n\n/**\n * Collects attribution signals from URL + cookies and merges them.\n */\nexport class AttributionCollector {\n private readonly clickIdParser = new ClickIdParser();\n\n private readonly cookieCollector = new CookieCollector();\n\n private readonly customParams: readonly string[];\n\n private readonly captureUrlParams: boolean;\n\n private readonly captureCookies: boolean;\n\n constructor(\n options: {\n customParams?: readonly string[];\n captureUrlParams?: boolean;\n captureCookies?: boolean;\n } = {}\n ) {\n this.customParams = options.customParams ?? [];\n this.captureUrlParams = options.captureUrlParams !== false;\n this.captureCookies = options.captureCookies !== false;\n }\n\n collectFresh(): Partial<AttributionIdentifiers> {\n const fromUrl = this.captureUrlParams\n ? this.clickIdParser.parse(this.customParams)\n : {};\n const fromCookies = this.captureCookies\n ? this.cookieCollector.collectKnown()\n : {};\n\n const merged: Record<string, unknown> = {\n ...fromCookies,\n ...fromUrl,\n };\n\n const customClickIds = {\n ...((fromCookies as AttributionIdentifiers).customClickIds ?? {}),\n ...(fromUrl.customClickIds ?? {}),\n };\n if (Object.keys(customClickIds).length > 0) {\n merged.customClickIds = customClickIds;\n }\n\n if (typeof merged.fbclid === 'string' && merged.fbclid) {\n const fbc = this.clickIdParser.synthesizeFbc(\n merged.fbclid,\n typeof merged.fbc === 'string' ? merged.fbc : undefined\n );\n if (fbc) merged.fbc = fbc;\n }\n\n if (typeof window !== 'undefined') {\n try {\n merged.landingUrl = window.location.href;\n } catch {\n // ignore\n }\n }\n\n if (typeof document !== 'undefined') {\n try {\n if (document.referrer) merged.referrer = document.referrer;\n } catch {\n // ignore\n }\n }\n\n return merged as Partial<AttributionIdentifiers>;\n }\n\n /**\n * Merge: never overwrite existing defined values with undefined.\n */\n merge(\n existing: AttributionIdentifiers,\n incoming: Partial<AttributionIdentifiers>\n ): AttributionIdentifiers {\n const next: Record<string, unknown> = { ...existing };\n\n for (const [key, value] of Object.entries(incoming)) {\n if (value === undefined || value === null || value === '') continue;\n\n if (key === 'customClickIds' && typeof value === 'object') {\n next.customClickIds = {\n ...((existing.customClickIds as Record<string, string>) ?? {}),\n ...(value as Record<string, string>),\n };\n continue;\n }\n\n next[key] = value;\n }\n\n const now = Date.now();\n if (!existing.firstCollectedAt) {\n next.firstCollectedAt = now;\n }\n next.lastCollectedAt = now;\n\n return next as AttributionIdentifiers;\n }\n}\n","import type { StorageService } from '@/services/storage/types';\n\nimport { ATTRIBUTION_STORAGE_KEY, type AttributionIdentifiers } from './types';\n\n/**\n * Persists AttributionIdentifiers via StorageService only (no direct localStorage).\n */\nexport class AttributionStore {\n private readonly storage: StorageService;\n\n private readonly persist: boolean;\n\n private readonly ttlMs: number;\n\n private readonly storageKey: string;\n\n constructor(\n storage: StorageService,\n options: { persist: boolean; ttlDays: number; storageKey?: string }\n ) {\n this.storage = storage;\n this.persist = options.persist;\n this.ttlMs = options.ttlDays * 24 * 60 * 60 * 1000;\n this.storageKey = options.storageKey ?? ATTRIBUTION_STORAGE_KEY;\n }\n\n load(): AttributionIdentifiers | null {\n if (!this.persist) return null;\n\n try {\n const snapshot = this.storage.get<AttributionIdentifiers>(\n this.storageKey\n );\n if (!snapshot) return null;\n\n if (this.isExpired(snapshot)) {\n this.clear();\n return null;\n }\n\n return snapshot;\n } catch {\n return null;\n }\n }\n\n save(snapshot: AttributionIdentifiers): void {\n if (!this.persist) return;\n\n try {\n this.storage.set(this.storageKey, snapshot);\n } catch {\n // quota / SSR — keep in-memory only\n }\n }\n\n clear(): void {\n try {\n this.storage.remove(this.storageKey);\n } catch {\n // ignore\n }\n }\n\n private isExpired(snapshot: AttributionIdentifiers): boolean {\n const anchor = snapshot.lastCollectedAt ?? snapshot.firstCollectedAt;\n if (!anchor) return false;\n return Date.now() - anchor > this.ttlMs;\n }\n}\n","import type { StorageService } from '@/services/storage/types';\n\nimport { AttributionCollector } from './AttributionCollector';\nimport { AttributionStore } from './AttributionStore';\nimport {\n DEFAULT_ATTRIBUTION_CONFIG,\n type AttributionConfig,\n type AttributionIdentifiers,\n type AttributionService,\n} from './types';\n\nexport class AttributionServiceImpl implements AttributionService {\n private readonly store: AttributionStore;\n\n private readonly collector: AttributionCollector;\n\n private readonly enabled: boolean;\n\n private snapshot: AttributionIdentifiers = {};\n\n private active = false;\n\n constructor(\n storage: StorageService,\n config: AttributionConfig = DEFAULT_ATTRIBUTION_CONFIG\n ) {\n this.enabled = config.enabled !== false;\n this.store = new AttributionStore(storage, {\n persist: config.persist !== false,\n ttlDays: config.ttlDays ?? 90,\n });\n this.collector = new AttributionCollector({\n customParams: config.customClickIdParams ?? [],\n captureUrlParams: config.captureUrlParams !== false,\n captureCookies: config.captureCookies !== false,\n });\n }\n\n init(): void {\n if (this.active) return;\n this.active = true;\n\n if (!this.enabled) return;\n\n const stored = this.store.load();\n if (stored) {\n this.snapshot = stored;\n }\n\n this.collect();\n }\n\n destroy(): void {\n if (!this.active) return;\n this.active = false;\n }\n\n collect(): AttributionIdentifiers {\n if (!this.enabled) return this.snapshot;\n\n const fresh = this.collector.collectFresh();\n this.snapshot = this.collector.merge(this.snapshot, fresh);\n this.store.save(this.snapshot);\n return this.snapshot;\n }\n\n getSnapshot(): AttributionIdentifiers {\n return { ...this.snapshot };\n }\n\n update(partial: Partial<AttributionIdentifiers>): AttributionIdentifiers {\n this.snapshot = this.collector.merge(this.snapshot, partial);\n this.store.save(this.snapshot);\n return this.getSnapshot();\n }\n\n clear(): void {\n this.snapshot = {};\n this.store.clear();\n }\n}\n","import type { CommerceProduct } from '@/config/shared/commerce';\n\nexport type ProductCatalogOptions = {\n readonly defaultCurrency?: string;\n};\n\nexport type ProductCatalogSnapshot = {\n readonly products: CommerceProduct[];\n readonly count: number;\n};\n\n/**\n * Catálogo de produtos configurados em `config.commerce.catalog`.\n * Isolado por instância — sem estado global / module-level.\n * Não acessa DOM, Transport nem altera payloads de eventos.\n */\nexport class ProductCatalog {\n private readonly productsById = new Map<string, CommerceProduct>();\n\n private readonly productsBySku = new Map<string, CommerceProduct>();\n\n private readonly orderedIds: string[] = [];\n\n constructor(\n products: readonly CommerceProduct[] | undefined = [],\n options: ProductCatalogOptions = {}\n ) {\n this.indexProducts(products ?? [], options.defaultCurrency);\n }\n\n list(): CommerceProduct[] {\n return this.orderedIds.map(id =>\n this.cloneProduct(this.productsById.get(id)!)\n );\n }\n\n getById(id: string): CommerceProduct | null {\n if (!id) return null;\n const product = this.productsById.get(id);\n return product ? this.cloneProduct(product) : null;\n }\n\n getBySku(sku: string): CommerceProduct | null {\n if (!sku) return null;\n const product = this.productsBySku.get(sku);\n return product ? this.cloneProduct(product) : null;\n }\n\n hasProduct(id: string): boolean {\n return Boolean(id) && this.productsById.has(id);\n }\n\n getSnapshot(): ProductCatalogSnapshot {\n const products = this.list();\n return { products, count: products.length };\n }\n\n private indexProducts(\n products: readonly CommerceProduct[],\n defaultCurrency?: string\n ): void {\n for (const raw of products) {\n if (!raw || typeof raw !== 'object') continue;\n\n const id = typeof raw.id === 'string' ? raw.id.trim() : '';\n if (!id) continue;\n\n // Duplicado por id: mantém o primeiro (determinístico).\n if (this.productsById.has(id)) continue;\n\n const product = this.normalizeProduct(raw, id, defaultCurrency);\n this.productsById.set(id, product);\n this.orderedIds.push(id);\n\n const sku = typeof product.sku === 'string' ? product.sku.trim() : '';\n if (sku && !this.productsBySku.has(sku)) {\n this.productsBySku.set(sku, product);\n }\n }\n }\n\n private normalizeProduct(\n raw: CommerceProduct,\n id: string,\n defaultCurrency?: string\n ): CommerceProduct {\n const sku =\n typeof raw.sku === 'string' && raw.sku.trim()\n ? raw.sku.trim()\n : undefined;\n\n const currency =\n typeof raw.currency === 'string' && raw.currency.trim()\n ? raw.currency.trim()\n : defaultCurrency;\n\n const quantity =\n typeof raw.quantity === 'number' && Number.isFinite(raw.quantity)\n ? raw.quantity\n : undefined;\n\n return {\n ...raw,\n id,\n ...(sku !== undefined ? { sku } : {}),\n ...(currency !== undefined ? { currency } : {}),\n ...(quantity !== undefined ? { quantity } : {}),\n ...(raw.metadata ? { metadata: { ...raw.metadata } } : {}),\n };\n }\n\n private cloneProduct(product: CommerceProduct): CommerceProduct {\n return {\n ...product,\n ...(product.metadata ? { metadata: { ...product.metadata } } : {}),\n };\n }\n}\n","import type { CommerceCartItem } from '@/config/shared/commerce';\n\nexport type CommerceStateOptions = {\n /**\n * Quando `false`, `upsertItem` só atualiza itens já presentes\n * (não adiciona novos productIds). Default: `true`.\n */\n readonly allowDynamicItems?: boolean;\n};\n\nexport type CommerceStateSnapshot = {\n /**\n * Estado vivo do carrinho (runtime).\n * Não confundir com `commerce.cart.initialItems` da config.\n */\n readonly selectedItems: CommerceCartItem[];\n readonly count: number;\n};\n\n/**\n * Estado em memória do cart da instância.\n * Inicializado com `config.commerce.cart.initialItems`.\n * Não persiste, não acessa DOM/Transport e não dispara eventos.\n */\nexport class CommerceState {\n private readonly itemsByProductId = new Map<string, CommerceCartItem>();\n\n private readonly allowDynamicItems: boolean;\n\n constructor(\n initialItems: readonly CommerceCartItem[] | undefined = [],\n options: CommerceStateOptions = {}\n ) {\n this.allowDynamicItems = options.allowDynamicItems !== false;\n this.seed(initialItems ?? []);\n }\n\n getSelectedItems(): CommerceCartItem[] {\n return Array.from(this.itemsByProductId.values()).map(item =>\n this.cloneItem(item)\n );\n }\n\n hasItem(productId: string): boolean {\n return Boolean(productId) && this.itemsByProductId.has(productId);\n }\n\n getItem(productId: string): CommerceCartItem | null {\n if (!productId) return null;\n const item = this.itemsByProductId.get(productId);\n return item ? this.cloneItem(item) : null;\n }\n\n /**\n * Insere ou atualiza item.\n * - Sem `productId` → no-op\n * - `selected === false` → remove se existir / não adiciona\n * - `quantity <= 0` → remove\n * - `allowDynamicItems === false` e item novo → no-op\n */\n upsertItem(item: CommerceCartItem): void {\n if (!item || typeof item !== 'object') return;\n\n const productId =\n typeof item.productId === 'string' ? item.productId.trim() : '';\n if (!productId) return;\n\n if (item.selected === false) {\n this.itemsByProductId.delete(productId);\n return;\n }\n\n const quantity = this.normalizeQuantity(item.quantity);\n if (quantity <= 0) {\n this.itemsByProductId.delete(productId);\n return;\n }\n\n const exists = this.itemsByProductId.has(productId);\n if (!exists && !this.allowDynamicItems) return;\n\n const previous = this.itemsByProductId.get(productId);\n const metadata = item.metadata\n ? { ...item.metadata }\n : previous?.metadata\n ? { ...previous.metadata }\n : undefined;\n\n const next: CommerceCartItem = {\n ...previous,\n ...item,\n productId,\n quantity,\n selected: true,\n ...(metadata ? { metadata } : {}),\n };\n\n this.itemsByProductId.set(productId, next);\n }\n\n removeItem(productId: string): void {\n if (!productId) return;\n this.itemsByProductId.delete(productId);\n }\n\n /**\n * Atualiza quantidade. `quantity <= 0` remove o item.\n */\n updateQuantity(productId: string, quantity: number): void {\n if (!productId || !this.itemsByProductId.has(productId)) return;\n\n const normalized = this.normalizeQuantity(quantity);\n if (normalized <= 0) {\n this.itemsByProductId.delete(productId);\n return;\n }\n\n const current = this.itemsByProductId.get(productId)!;\n this.itemsByProductId.set(productId, {\n ...current,\n quantity: normalized,\n });\n }\n\n clear(): void {\n this.itemsByProductId.clear();\n }\n\n getSnapshot(): CommerceStateSnapshot {\n const selectedItems = this.getSelectedItems();\n return { selectedItems, count: selectedItems.length };\n }\n\n private seed(initialItems: readonly CommerceCartItem[]): void {\n for (const item of initialItems) {\n // Seed ignora allowDynamicItems — itens da config sempre entram\n // (exceto selected:false / inválidos / quantity<=0).\n this.seedItem(item);\n }\n }\n\n private seedItem(item: CommerceCartItem): void {\n if (!item || typeof item !== 'object') return;\n\n const productId =\n typeof item.productId === 'string' ? item.productId.trim() : '';\n if (!productId) return;\n if (item.selected === false) return;\n\n const quantity = this.normalizeQuantity(item.quantity);\n if (quantity <= 0) return;\n\n // Duplicado por productId no seed: mantém o primeiro.\n if (this.itemsByProductId.has(productId)) return;\n\n this.itemsByProductId.set(productId, {\n ...item,\n productId,\n quantity,\n selected: true,\n ...(item.metadata ? { metadata: { ...item.metadata } } : {}),\n });\n }\n\n private normalizeQuantity(quantity: number | undefined): number {\n if (quantity === undefined || quantity === null) return 1;\n if (typeof quantity !== 'number' || !Number.isFinite(quantity)) return 1;\n return quantity;\n }\n\n private cloneItem(item: CommerceCartItem): CommerceCartItem {\n return {\n ...item,\n ...(item.metadata ? { metadata: { ...item.metadata } } : {}),\n };\n }\n}\n","/**\n * Calcula value/currency a partir de items resolvidos.\n * Não conhece DOM, detectors, Transport nem Dispatcher.\n * Não muta o input.\n */\n\nexport type ResolvedCommerceItem = {\n productId?: string;\n sku?: string;\n productName?: string;\n price?: number;\n quantity?: number;\n currency?: string;\n category?: string;\n variant?: string;\n brand?: string;\n type?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type OrderCalculationInput = {\n items?: ResolvedCommerceItem[];\n value?: number;\n currency?: string;\n defaultCurrency?: string;\n};\n\nexport type OrderCalculationResult = {\n items: ResolvedCommerceItem[];\n value?: number;\n currency?: string;\n};\n\nexport class OrderCalculator {\n calculate(input: OrderCalculationInput): OrderCalculationResult {\n const sourceItems = Array.isArray(input.items) ? input.items : [];\n const items = sourceItems.map(item => this.cloneItem(item));\n\n for (const item of items) {\n if (item.quantity == null || !Number.isFinite(item.quantity)) {\n item.quantity = 1;\n }\n }\n\n const value =\n typeof input.value === 'number' && Number.isFinite(input.value)\n ? input.value\n : this.sumValue(items);\n\n const currency = this.resolveCurrency(input, items);\n\n return {\n items,\n ...(value !== undefined ? { value } : {}),\n ...(currency !== undefined ? { currency } : {}),\n };\n }\n\n private sumValue(items: ResolvedCommerceItem[]): number | undefined {\n let total = 0;\n let hasPriced = false;\n\n for (const item of items) {\n if (typeof item.price !== 'number' || !Number.isFinite(item.price)) {\n continue;\n }\n const qty =\n typeof item.quantity === 'number' && Number.isFinite(item.quantity)\n ? item.quantity\n : 1;\n total += item.price * qty;\n hasPriced = true;\n }\n\n return hasPriced ? total : undefined;\n }\n\n /**\n * Ordem: currency manual → primeiro item com currency → defaultCurrency.\n * Multi-currency: determinístico — usa o primeiro item com currency\n * (não normaliza conversão entre moedas nesta etapa).\n */\n private resolveCurrency(\n input: OrderCalculationInput,\n items: ResolvedCommerceItem[]\n ): string | undefined {\n if (typeof input.currency === 'string' && input.currency.trim()) {\n return input.currency.trim();\n }\n\n for (const item of items) {\n if (typeof item.currency === 'string' && item.currency.trim()) {\n return item.currency.trim();\n }\n }\n\n if (\n typeof input.defaultCurrency === 'string' &&\n input.defaultCurrency.trim()\n ) {\n return input.defaultCurrency.trim();\n }\n\n return undefined;\n }\n\n private cloneItem(item: ResolvedCommerceItem): ResolvedCommerceItem {\n return {\n ...item,\n ...(item.metadata ? { metadata: { ...item.metadata } } : {}),\n };\n }\n}\n","/**\n * Contratos globais de commerce (root `PixelConfig.commerce`).\n * Não pertencem a conversion — representam o contexto comercial da página/fluxo.\n */\n\nexport type ProductType =\n | 'main'\n | 'order_bump'\n | 'upsell'\n | 'downsell'\n | 'cross_sell'\n | 'addon'\n | 'subscription'\n | 'custom'\n | 'other';\n\nexport type CommerceProduct = {\n id: string;\n name?: string;\n sku?: string;\n type?: ProductType;\n price?: number;\n currency?: string;\n quantity?: number;\n category?: string;\n variant?: string;\n brand?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type CommerceCartItem = {\n productId: string;\n quantity?: number;\n price?: number;\n currency?: string;\n selected?: boolean;\n metadata?: Record<string, unknown>;\n};\n\nexport type CommerceCartMode =\n | 'landing_page'\n | 'single_product'\n | 'multi_product'\n | 'checkout'\n | 'upsell'\n | 'custom'\n | 'cart'\n | 'funnel';\n\nexport type CommerceCalculateValueFrom =\n | 'cart'\n | 'event'\n | 'manual'\n | 'catalog';\n\nexport type CommerceEnrichmentSource =\n | 'cart'\n | 'event'\n | 'event_or_cart'\n | 'catalog';\n\nexport type CommerceEventEnrichmentConfig = {\n enabled: boolean;\n source?: CommerceEnrichmentSource;\n};\n\nexport type CommerceEnrichmentConfig = {\n pageView?: CommerceEventEnrichmentConfig;\n viewContent?: CommerceEventEnrichmentConfig;\n lead?: CommerceEventEnrichmentConfig;\n addToCart?: CommerceEventEnrichmentConfig;\n removeFromCart?: CommerceEventEnrichmentConfig;\n initiateCheckout?: CommerceEventEnrichmentConfig;\n addPaymentInfo?: CommerceEventEnrichmentConfig;\n purchase?: CommerceEventEnrichmentConfig;\n};\n\nexport type ProductCatalogConfig = {\n products?: CommerceProduct[];\n};\n\nexport type CommerceCartConfig = {\n mode?: CommerceCartMode;\n /** Seed inicial do carrinho — não é estado vivo. */\n initialItems?: CommerceCartItem[];\n allowDynamicItems?: boolean;\n calculateValueFrom?: CommerceCalculateValueFrom;\n metadata?: Record<string, unknown>;\n};\n\nexport type CommerceMappingsConfig = {\n attributes?: Record<string, string[]>;\n fields?: Record<string, string[]>;\n};\n\nexport type CommerceConfig = {\n enabled?: boolean;\n currency?: string;\n catalog?: ProductCatalogConfig;\n cart?: CommerceCartConfig;\n mappings?: CommerceMappingsConfig;\n enrichment?: CommerceEnrichmentConfig;\n};\n\nexport const DEFAULT_COMMERCE_ENRICHMENT: Required<CommerceEnrichmentConfig> = {\n pageView: { enabled: false, source: 'cart' },\n viewContent: { enabled: true, source: 'event_or_cart' },\n lead: { enabled: false, source: 'event_or_cart' },\n addToCart: { enabled: true, source: 'event_or_cart' },\n removeFromCart: { enabled: true, source: 'event_or_cart' },\n initiateCheckout: { enabled: true, source: 'cart' },\n addPaymentInfo: { enabled: true, source: 'cart' },\n purchase: { enabled: true, source: 'cart' },\n};\n\n/** Default seguro: commerce off, sem produtos, sem itens. */\nexport const DEFAULT_COMMERCE_CONFIG: CommerceConfig = {\n enabled: false,\n currency: 'BRL',\n catalog: {\n products: [],\n },\n cart: {\n mode: 'custom',\n initialItems: [],\n allowDynamicItems: true,\n calculateValueFrom: 'cart',\n },\n mappings: {\n attributes: {},\n fields: {},\n },\n enrichment: { ...DEFAULT_COMMERCE_ENRICHMENT },\n};\n\n/** Normaliza calculateValueFrom (inclui aliases legado em runtime). */\nexport function normalizeCalculateValueFrom(\n value: CommerceCalculateValueFrom | string | undefined\n): 'cart' | 'event' | 'manual' | 'catalog' {\n switch (value) {\n case 'event':\n case 'event_items':\n return 'event';\n case 'manual':\n return 'manual';\n case 'catalog':\n return 'catalog';\n case 'cart':\n case 'selected_items':\n default:\n return 'cart';\n }\n}\n","import type { CommerceCalculateValueFrom } from '@/config/shared/commerce';\nimport { normalizeCalculateValueFrom } from '@/config/shared/commerce';\nimport type { PixelItem } from '@/events/conversion';\n\nimport type { CommerceState } from './CommerceState';\nimport type { ProductCatalog } from './ProductCatalog';\nimport type { OrderCalculator, ResolvedCommerceItem } from './OrderCalculator';\n\nexport type CommerceEventType =\n | 'ADD_TO_CART'\n | 'REMOVE_FROM_CART'\n | 'INITIATE_CHECKOUT'\n | 'PURCHASE'\n | 'VIEW_CONTENT'\n | 'ADD_PAYMENT_INFO';\n\nexport type ExtractedProductInput = {\n productId?: string;\n productName?: string;\n price?: number;\n quantity?: number;\n currency?: string;\n sku?: string;\n};\n\nexport type CommerceResolverInput = {\n eventType: CommerceEventType;\n payload?: Record<string, unknown>;\n extractedProduct?: ExtractedProductInput;\n enrichmentSource?: import('@/config/shared/commerce').CommerceEnrichmentSource;\n items?: Array<{\n productId?: string;\n id?: string;\n sku?: string;\n name?: string;\n productName?: string;\n price?: number;\n quantity?: number;\n currency?: string;\n category?: string;\n }>;\n};\n\nexport type CommerceResolverResult = {\n data: Record<string, unknown>;\n items?: ResolvedCommerceItem[];\n value?: number;\n currency?: string;\n};\n\nexport type CommerceResolverOptions = {\n catalog: ProductCatalog;\n state: CommerceState;\n calculator: OrderCalculator;\n defaultCurrency?: string;\n calculateValueFrom?: CommerceCalculateValueFrom;\n};\n\n/**\n * Combina payload + extracted + state + catalog + defaults.\n * Não dispara eventos, não escreve em CommerceState, não conhece DOM/Transport.\n *\n * Prioridade de merge por campo:\n * manual payload > extractedProduct > commerce state > catalog > defaults\n */\nexport class CommerceResolver {\n private readonly catalog: ProductCatalog;\n\n private readonly state: CommerceState;\n\n private readonly calculator: OrderCalculator;\n\n private readonly defaultCurrency?: string;\n\n private readonly calculateValueFrom: ReturnType<\n typeof normalizeCalculateValueFrom\n >;\n\n constructor(options: CommerceResolverOptions) {\n this.catalog = options.catalog;\n this.state = options.state;\n this.calculator = options.calculator;\n this.defaultCurrency = trim(options.defaultCurrency);\n this.calculateValueFrom = normalizeCalculateValueFrom(\n options.calculateValueFrom\n );\n }\n\n resolve(input: CommerceResolverInput): CommerceResolverResult {\n const source = input.enrichmentSource;\n\n // source: 'event' — não completa via cart/catalog\n if (source === 'event') {\n return { data: { ...(input.payload ?? {}) } };\n }\n\n switch (input.eventType) {\n case 'ADD_TO_CART':\n return this.resolveAddToCart(input);\n case 'REMOVE_FROM_CART':\n return this.resolveRemoveFromCart(input);\n case 'INITIATE_CHECKOUT':\n return this.resolveCheckoutLike(input, false);\n case 'PURCHASE':\n return this.resolveCheckoutLike(input, true);\n case 'VIEW_CONTENT':\n return this.resolveViewContent(input);\n case 'ADD_PAYMENT_INFO':\n return this.resolveCheckoutLike(input, false);\n default:\n return { data: { ...(input.payload ?? {}) } };\n }\n }\n\n private resolveAddToCart(\n input: CommerceResolverInput\n ): CommerceResolverResult {\n const payload = input.payload ?? {};\n const extracted = input.extractedProduct ?? {};\n const source = input.enrichmentSource ?? 'event_or_cart';\n const useCart = source === 'cart' || source === 'event_or_cart';\n const useCatalog =\n source === 'catalog' || source === 'cart' || source === 'event_or_cart';\n\n let productId =\n asString(payload.priceId) ??\n asString(payload.productId) ??\n asString(extracted.productId) ??\n (useCatalog\n ? this.lookupIdBySku(asString(payload.sku) ?? asString(extracted.sku))\n : undefined);\n\n // Fallback: sem productId/sku no evento → item principal do cart\n const cartFallback =\n !productId && useCart ? this.resolvePrimaryCartItem() : null;\n if (!productId && cartFallback) {\n productId = cartFallback.productId;\n }\n\n const catalogProduct =\n useCatalog && productId\n ? this.catalog.getById(productId)\n : useCatalog\n ? this.lookupProductBySku(\n asString(payload.sku) ?? asString(extracted.sku)\n )\n : null;\n\n const resolvedId = productId ?? catalogProduct?.id;\n const stateItem =\n useCart && resolvedId\n ? (this.state.getItem(resolvedId) ?? cartFallback)\n : null;\n\n // source: 'catalog' sem productId/sku → não injeta cart\n if (source === 'catalog' && !resolvedId && !catalogProduct) {\n return { data: { ...payload } };\n }\n\n const productName =\n asString(payload.productName) ??\n asString(extracted.productName) ??\n catalogProduct?.name;\n\n const price =\n asNumber(payload.price) ??\n asNumber(extracted.price) ??\n (useCart ? asNumber(stateItem?.price) : undefined) ??\n catalogProduct?.price;\n\n const quantity =\n asNumber(payload.quantity) ??\n asNumber(extracted.quantity) ??\n (useCart ? asNumber(stateItem?.quantity) : undefined) ??\n catalogProduct?.quantity ??\n 1;\n\n const currency =\n asString(payload.currency) ??\n asString(extracted.currency) ??\n (useCart ? asString(stateItem?.currency) : undefined) ??\n catalogProduct?.currency ??\n this.defaultCurrency;\n\n const identity = resolveCatalogItemIdentity(catalogProduct, {\n priceId: asString(payload.priceId),\n productId: resolvedId,\n offerId: asString(payload.offerId),\n id: asString(payload.id),\n });\n\n const data: Record<string, unknown> = {};\n if (identity.id) data.id = identity.id;\n if (identity.priceId) data.priceId = identity.priceId;\n if (identity.productId) data.productId = identity.productId;\n if (identity.offerId) data.offerId = identity.offerId;\n if (productName) data.productName = productName;\n if (price !== undefined) data.price = price;\n if (currency) data.currency = currency;\n if (quantity !== undefined) data.quantity = quantity;\n\n // Preserva campos extras do payload (sem sobrescrever resolvidos).\n for (const [key, value] of Object.entries(payload)) {\n if (value === undefined) continue;\n if (!(key in data)) data[key] = value;\n }\n\n return { data };\n }\n\n /**\n * Escolhe o item principal do cart runtime:\n * 1. único item → esse\n * 2. múltiplos → preferir catalog.type === 'main'\n * 3. senão → primeiro do cart\n * 4. cart vazio → null\n */\n private resolvePrimaryCartItem(): {\n productId: string;\n quantity?: number;\n price?: number;\n currency?: string;\n } | null {\n const items = this.state.getSelectedItems();\n if (items.length === 0) return null;\n if (items.length === 1) return items[0] ?? null;\n\n const main = items.find(item => {\n const product = this.catalog.getById(item.productId);\n return product?.type === 'main';\n });\n return main ?? items[0] ?? null;\n }\n\n private resolveRemoveFromCart(\n input: CommerceResolverInput\n ): CommerceResolverResult {\n const payload = input.payload ?? {};\n const extracted = input.extractedProduct ?? {};\n\n const productId =\n asString(payload.productId) ??\n asString(extracted.productId) ??\n this.lookupIdBySku(asString(payload.sku) ?? asString(extracted.sku));\n\n const catalogProduct = productId ? this.catalog.getById(productId) : null;\n\n const resolvedId = productId ?? catalogProduct?.id;\n const stateItem = resolvedId ? this.state.getItem(resolvedId) : null;\n\n const quantity =\n asNumber(payload.quantity) ??\n asNumber(extracted.quantity) ??\n asNumber(stateItem?.quantity) ??\n 1;\n\n const data: Record<string, unknown> = {};\n if (resolvedId) data.productId = resolvedId;\n if (quantity !== undefined) data.quantity = quantity;\n\n for (const [key, value] of Object.entries(payload)) {\n if (value === undefined) continue;\n if (!(key in data)) data[key] = value;\n }\n\n return { data };\n }\n\n private resolveCheckoutLike(\n input: CommerceResolverInput,\n isPurchase: boolean\n ): CommerceResolverResult {\n const payload = { ...(input.payload ?? {}) };\n const manualValue = asNumber(payload.value);\n const manualCurrency = asString(payload.currency);\n const manualItems = this.readPayloadItems(input);\n const source = input.enrichmentSource;\n\n const resolvedItems = this.resolveItemsSource(manualItems, source);\n const pixelItems = resolvedItems.map(item => this.toPixelItem(item));\n\n const allowCalculatedValue =\n source !== 'catalog' && this.calculateValueFrom !== 'manual';\n\n const shouldCalculateValue =\n manualValue === undefined && allowCalculatedValue;\n\n const calc = this.calculator.calculate({\n items: resolvedItems,\n value: shouldCalculateValue ? undefined : manualValue,\n currency: manualCurrency,\n defaultCurrency: this.defaultCurrency,\n });\n\n const value =\n manualValue !== undefined\n ? manualValue\n : allowCalculatedValue\n ? calc.value\n : undefined;\n\n const currency = manualCurrency ?? calc.currency ?? this.defaultCurrency;\n\n const data: Record<string, unknown> = { ...payload };\n\n if (pixelItems.length > 0) {\n data.items = pixelItems;\n } else if (manualItems === null) {\n delete data.items;\n }\n\n if (value !== undefined) {\n data.value = value;\n } else {\n delete data.value;\n }\n\n if (currency) {\n data.currency = currency;\n }\n\n if (isPurchase) {\n // orderId e demais campos do payload já estão em data via spread.\n }\n\n return {\n data,\n items: calc.items,\n ...(value !== undefined ? { value } : {}),\n ...(currency ? { currency } : {}),\n };\n }\n\n private resolveViewContent(\n input: CommerceResolverInput\n ): CommerceResolverResult {\n const payload = { ...(input.payload ?? {}) };\n const source = input.enrichmentSource ?? 'event_or_cart';\n\n // Tenta completar productId/name/price a partir de payload + cart/catalog\n if (source === 'cart' || source === 'event_or_cart') {\n const atc = this.resolveAddToCart({\n ...input,\n eventType: 'ADD_TO_CART',\n enrichmentSource: source,\n });\n\n const checkout = this.resolveCheckoutLike(\n { ...input, eventType: 'INITIATE_CHECKOUT', enrichmentSource: source },\n false\n );\n\n const data: Record<string, unknown> = { ...payload };\n\n const contentId =\n asString(payload.contentId) ??\n asString(atc.data.productId as string | undefined) ??\n (Array.isArray(checkout.data.items) &&\n checkout.data.items[0] &&\n typeof (checkout.data.items[0] as { id?: unknown }).id === 'string'\n ? (checkout.data.items[0] as { id: string }).id\n : undefined);\n\n const contentName =\n asString(payload.contentName) ??\n asString(atc.data.productName as string | undefined) ??\n (Array.isArray(checkout.data.items) &&\n checkout.data.items[0] &&\n typeof (checkout.data.items[0] as { name?: unknown }).name === 'string'\n ? (checkout.data.items[0] as { name: string }).name\n : undefined);\n\n if (contentId) data.contentId = contentId;\n if (contentName) data.contentName = contentName;\n\n if (\n asNumber(payload.value) === undefined &&\n checkout.value !== undefined\n ) {\n data.value = checkout.value;\n }\n if (!asString(payload.currency) && checkout.currency) {\n data.currency = checkout.currency;\n }\n if (payload.items === undefined && Array.isArray(checkout.data.items)) {\n data.items = checkout.data.items;\n }\n\n return {\n data,\n ...(checkout.value !== undefined ? { value: checkout.value } : {}),\n ...(checkout.currency ? { currency: checkout.currency } : {}),\n items: checkout.items,\n };\n }\n\n if (source === 'catalog') {\n const atc = this.resolveAddToCart({\n ...input,\n eventType: 'ADD_TO_CART',\n enrichmentSource: 'catalog',\n });\n const data: Record<string, unknown> = { ...payload };\n if (atc.data.productId && !asString(payload.contentId)) {\n data.contentId = atc.data.productId;\n }\n if (atc.data.productName && !asString(payload.contentName)) {\n data.contentName = atc.data.productName;\n }\n if (\n atc.data.price !== undefined &&\n asNumber(payload.value) === undefined\n ) {\n data.value = atc.data.price;\n }\n if (atc.data.currency && !asString(payload.currency)) {\n data.currency = atc.data.currency;\n }\n return { data };\n }\n\n return { data: payload };\n }\n\n /**\n * null = payload não trouxe items (usar state conforme calculateValueFrom)\n * [] = payload trouxe items vazios\n */\n private readPayloadItems(\n input: CommerceResolverInput\n ): ResolvedCommerceItem[] | null {\n if (input.items) {\n return input.items.map(item => this.normalizeLooseItem(item));\n }\n\n const raw = input.payload?.items;\n if (raw === undefined) return null;\n if (!Array.isArray(raw)) return null;\n return raw.map(item =>\n this.normalizeLooseItem(\n (item && typeof item === 'object' ? item : {}) as Record<\n string,\n unknown\n >\n )\n );\n }\n\n private resolveItemsSource(\n manualItems: ResolvedCommerceItem[] | null,\n enrichmentSource?: import('@/config/shared/commerce').CommerceEnrichmentSource\n ): ResolvedCommerceItem[] {\n // Items manuais sempre vencem state.\n if (manualItems !== null) {\n return manualItems.map(item => this.enrichItem(item));\n }\n\n // source: 'catalog' — não injeta cart inteiro\n if (enrichmentSource === 'catalog') {\n return [];\n }\n\n // source: 'cart' força fallback do carrinho (independente de calculateValueFrom),\n // exceto quando calculateValueFrom === 'manual' (value/items só do payload).\n if (\n enrichmentSource === 'cart' &&\n this.calculateValueFrom !== 'manual' &&\n this.calculateValueFrom !== 'event'\n ) {\n return this.state.getSelectedItems().map(stateItem =>\n this.enrichItem({\n productId: stateItem.productId,\n price: stateItem.price,\n quantity: stateItem.quantity,\n currency: stateItem.currency,\n })\n );\n }\n\n if (this.calculateValueFrom === 'cart') {\n return this.state.getSelectedItems().map(stateItem =>\n this.enrichItem({\n productId: stateItem.productId,\n price: stateItem.price,\n quantity: stateItem.quantity,\n currency: stateItem.currency,\n })\n );\n }\n\n if (this.calculateValueFrom === 'catalog') {\n const fromState = this.state.getSelectedItems();\n if (fromState.length > 0) {\n return fromState.map(stateItem =>\n this.enrichItem({\n productId: stateItem.productId,\n price: stateItem.price,\n quantity: stateItem.quantity,\n currency: stateItem.currency,\n })\n );\n }\n return this.catalog.list().map(product =>\n this.enrichItem({\n productId: product.id,\n price: product.price,\n quantity: product.quantity ?? 1,\n currency: product.currency,\n productName: product.name,\n sku: product.sku,\n category: product.category,\n })\n );\n }\n\n // event / manual sem items no payload → sem items\n return [];\n }\n\n private enrichItem(item: ResolvedCommerceItem): ResolvedCommerceItem {\n const productId =\n item.productId ?? this.lookupIdBySku(item.sku) ?? undefined;\n const catalog = productId\n ? this.catalog.getById(productId)\n : this.lookupProductBySku(item.sku);\n\n const resolvedId = productId ?? catalog?.id;\n\n return {\n ...item,\n ...(resolvedId ? { productId: resolvedId } : {}),\n productName: item.productName ?? catalog?.name,\n sku: item.sku ?? catalog?.sku,\n price: item.price ?? catalog?.price,\n quantity: item.quantity ?? catalog?.quantity ?? 1,\n currency: item.currency ?? catalog?.currency ?? this.defaultCurrency,\n category: item.category ?? catalog?.category,\n variant: item.variant ?? catalog?.variant,\n brand: item.brand ?? catalog?.brand,\n type: item.type ?? catalog?.type,\n metadata: item.metadata ?? catalog?.metadata,\n };\n }\n\n private toPixelItem(item: ResolvedCommerceItem): PixelItem {\n const pixel: PixelItem = {\n ...(item.productId ? { id: item.productId } : {}),\n ...(item.productName ? { name: item.productName } : {}),\n ...(item.category ? { category: item.category } : {}),\n ...(item.price !== undefined ? { price: item.price } : {}),\n ...(item.quantity !== undefined ? { quantity: item.quantity } : {}),\n };\n return pixel;\n }\n\n private normalizeLooseItem(\n item:\n | Record<string, unknown>\n | {\n productId?: string;\n id?: string;\n sku?: string;\n name?: string;\n productName?: string;\n price?: number;\n quantity?: number;\n currency?: string;\n category?: string;\n }\n ): ResolvedCommerceItem {\n return {\n productId:\n asString((item as { productId?: unknown }).productId) ??\n asString((item as { id?: unknown }).id),\n sku: asString((item as { sku?: unknown }).sku),\n productName:\n asString((item as { productName?: unknown }).productName) ??\n asString((item as { name?: unknown }).name),\n price: asNumber((item as { price?: unknown }).price),\n quantity: asNumber((item as { quantity?: unknown }).quantity),\n currency: asString((item as { currency?: unknown }).currency),\n category: asString((item as { category?: unknown }).category),\n };\n }\n\n private lookupIdBySku(sku: string | undefined): string | undefined {\n if (!sku) return undefined;\n return this.catalog.getBySku(sku)?.id;\n }\n\n private lookupProductBySku(sku: string | undefined) {\n if (!sku) return null;\n return this.catalog.getBySku(sku);\n }\n}\n\nfunction resolveCatalogItemIdentity(\n catalogProduct: import('@/config/shared/commerce').CommerceProduct | null,\n incoming: {\n id?: string;\n priceId?: string;\n productId?: string;\n offerId?: string;\n }\n): {\n id?: string;\n priceId?: string;\n productId?: string;\n offerId?: string;\n} {\n const meta = catalogProduct?.metadata ?? {};\n const metaPriceId = asString(meta.priceId);\n const metaProductId = asString(meta.productId);\n const metaOfferId = asString(meta.offerId);\n\n // Identidade Bemony (id/priceId/offerId) só quando priceId explícito ou metadata.\n // Catálogo genérico do Core continua só com productId.\n const priceId = incoming.priceId ?? metaPriceId;\n if (!priceId) {\n const productId = incoming.productId ?? catalogProduct?.id;\n return {\n ...(incoming.id ? { id: incoming.id } : {}),\n ...(productId ? { productId } : {}),\n ...(incoming.offerId ? { offerId: incoming.offerId } : {}),\n };\n }\n\n return {\n id: incoming.id ?? priceId,\n priceId,\n productId: metaProductId ?? incoming.productId ?? priceId,\n offerId: metaOfferId ?? incoming.offerId ?? priceId,\n };\n}\n\nfunction asString(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n if (typeof value !== 'number' || !Number.isFinite(value)) return undefined;\n return value;\n}\n\nfunction trim(value: string | undefined): string | undefined {\n if (typeof value !== 'string') return undefined;\n const t = value.trim();\n return t.length > 0 ? t : undefined;\n}\n","import type {\n CommerceConfig,\n CommerceEnrichmentSource,\n CommerceEventEnrichmentConfig,\n} from '@/config/shared/commerce';\nimport {\n DEFAULT_COMMERCE_CONFIG,\n DEFAULT_COMMERCE_ENRICHMENT,\n normalizeCalculateValueFrom,\n} from '@/config/shared/commerce';\nimport type { PixelItem } from '@/events/conversion';\n\nimport { CommerceResolver } from './CommerceResolver';\nimport { CommerceState } from './CommerceState';\nimport { OrderCalculator } from './OrderCalculator';\nimport { ProductCatalog } from './ProductCatalog';\n\nexport type CommerceEnrichmentEvent =\n | 'pageView'\n | 'viewContent'\n | 'lead'\n | 'addToCart'\n | 'removeFromCart'\n | 'initiateCheckout'\n | 'addPaymentInfo'\n | 'purchase';\n\nexport type PageViewCommercePayload = {\n readonly value?: number;\n readonly currency?: string;\n readonly items?: PixelItem[];\n readonly contentId?: string;\n readonly contentName?: string;\n};\n\n/**\n * Serviço compartilhado de commerce (root config).\n * Usado por Core (PAGE_VIEW) e Conversion sem dependência circular\n * entre os módulos.\n */\nexport class CommerceService {\n readonly enabled: boolean;\n\n readonly config: CommerceConfig;\n\n readonly catalog: ProductCatalog;\n\n readonly state: CommerceState;\n\n private readonly resolver: CommerceResolver;\n\n constructor(config: CommerceConfig | undefined) {\n this.config = {\n ...DEFAULT_COMMERCE_CONFIG,\n ...config,\n catalog: {\n products: config?.catalog?.products ?? [],\n },\n cart: {\n ...DEFAULT_COMMERCE_CONFIG.cart,\n ...config?.cart,\n initialItems: config?.cart?.initialItems\n ? config.cart.initialItems.map(item => ({ ...item }))\n : [],\n },\n mappings: {\n attributes: { ...(config?.mappings?.attributes ?? {}) },\n fields: { ...(config?.mappings?.fields ?? {}) },\n },\n enrichment: {\n ...DEFAULT_COMMERCE_ENRICHMENT,\n ...config?.enrichment,\n },\n };\n\n this.enabled = this.config.enabled === true;\n\n this.catalog = new ProductCatalog(this.config.catalog?.products, {\n defaultCurrency: this.config.currency,\n });\n\n this.state = new CommerceState(this.config.cart?.initialItems, {\n allowDynamicItems: this.config.cart?.allowDynamicItems !== false,\n });\n\n this.resolver = new CommerceResolver({\n catalog: this.catalog,\n state: this.state,\n calculator: new OrderCalculator(),\n defaultCurrency: this.config.currency,\n calculateValueFrom: normalizeCalculateValueFrom(\n this.config.cart?.calculateValueFrom\n ),\n });\n }\n\n getEnrichment(event: CommerceEnrichmentEvent): CommerceEventEnrichmentConfig {\n const fromConfig = this.config.enrichment?.[event];\n const fallback = DEFAULT_COMMERCE_ENRICHMENT[event];\n return {\n enabled: fromConfig?.enabled ?? fallback.enabled,\n source: fromConfig?.source ?? fallback.source,\n };\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n isEnrichmentEnabled(event: CommerceEnrichmentEvent): boolean {\n return this.enabled && this.getEnrichment(event).enabled === true;\n }\n\n getEnrichmentSource(\n event: CommerceEnrichmentEvent\n ): CommerceEnrichmentSource {\n return this.getEnrichment(event).source ?? 'event_or_cart';\n }\n\n /**\n * Resolve payload de commerce para um evento conversion.\n * Retorna null quando enrichment está desabilitado (caller usa payload original).\n */\n resolveForEvent(\n event: CommerceEnrichmentEvent,\n eventType:\n | 'ADD_TO_CART'\n | 'REMOVE_FROM_CART'\n | 'INITIATE_CHECKOUT'\n | 'PURCHASE'\n | 'VIEW_CONTENT'\n | 'ADD_PAYMENT_INFO',\n payload: Record<string, unknown> = {}\n ): Record<string, unknown> | null {\n if (!this.isEnrichmentEnabled(event)) return null;\n\n const result = this.resolver.resolve({\n eventType,\n payload,\n enrichmentSource: this.getEnrichmentSource(event),\n });\n\n return result.data;\n }\n\n /**\n * Payload de commerce para PAGE_VIEW quando enrichment.pageView.enabled.\n * Não depende de ConversionEngine.\n */\n resolvePageViewEnrichment(): PageViewCommercePayload | null {\n if (!this.isEnrichmentEnabled('pageView')) return null;\n\n const source = this.getEnrichment('pageView').source ?? 'cart';\n if (source === 'event') return null;\n\n const resolved = this.resolver.resolve({\n eventType: 'INITIATE_CHECKOUT',\n payload: {},\n });\n\n const items = (resolved.data.items as PixelItem[] | undefined) ?? [];\n const first = items[0];\n const contentId =\n first && typeof first.id === 'string' ? first.id : undefined;\n const contentName =\n first && typeof first.name === 'string' ? first.name : undefined;\n\n if (\n resolved.value === undefined &&\n !resolved.currency &&\n items.length === 0\n ) {\n return null;\n }\n\n return {\n ...(resolved.value !== undefined ? { value: resolved.value } : {}),\n ...(resolved.currency ? { currency: resolved.currency } : {}),\n ...(items.length > 0 ? { items } : {}),\n ...(contentId ? { contentId } : {}),\n ...(contentName ? { contentName } : {}),\n };\n }\n\n getResolver(): CommerceResolver {\n return this.resolver;\n }\n\n getCalculateValueFrom(): ReturnType<typeof normalizeCalculateValueFrom> {\n return normalizeCalculateValueFrom(this.config.cart?.calculateValueFrom);\n }\n\n getMappings() {\n return this.config.mappings;\n }\n}\n"],"mappings":"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","names":["DispatcherServiceImpl","logger","event","snapshot","index","listener","error","sanitizeDispatcherError","eventType","listenerIndex","name","message","BrowserMetadataServiceImpl","timezone","DEFAULT_FINGERPRINT_KEY","hashFingerprintInput","input","hash","index","positiveHash","secondaryHash","computeLightFingerprint","metadataService","metadata","components","FingerprintServiceImpl","storage","config","existing","fingerprint","createRandomSuffix","generateSessionId","DEFAULT_SESSION_KEY","SessionServiceImpl","storage","config","raw","now","ttlMs","data","sessionId","generateSessionId","previousSessionId","BrowserStorageAdapter","storage","key","value","predicate","keysToRemove","index","MemoryStorageAdapter","key","value","predicate","supportsNamespaceClear","adapter","StorageServiceImpl","namespace","prefix","key","raw","value","namespaceKeyPrefix","createStorageAdapter","persistence","mode","MemoryStorageAdapter","BrowserStorageAdapter","resolveStorageAdapterName","createRandomSuffix","generateVisitorId","DEFAULT_VISITOR_KEY","VisitorServiceImpl","storage","config","existing","visitorId","generateVisitorId","DEFAULT_ATTRIBUTION_CONFIG","ATTRIBUTION_STORAGE_KEY","BUILTIN_CLICK_PARAMS","ClickIdParser","customParams","params","result","customClickIds","key","value","fbclid","existingFbc","CookieCollector","cookies","result","map","cookieName","field","value","acc","part","rawKey","rest","AttributionCollector","options","ClickIdParser","CookieCollector","fromUrl","fromCookies","merged","customClickIds","fbc","existing","incoming","next","key","value","now","AttributionStore","storage","options","ATTRIBUTION_STORAGE_KEY","snapshot","anchor","AttributionServiceImpl","storage","config","DEFAULT_ATTRIBUTION_CONFIG","AttributionStore","AttributionCollector","stored","fresh","partial","ProductCatalog","products","options","id","product","sku","defaultCurrency","raw","currency","quantity","CommerceState","initialItems","options","item","productId","quantity","previous","metadata","next","normalized","current","selectedItems","OrderCalculator","input","items","item","value","currency","total","hasPriced","qty","DEFAULT_COMMERCE_ENRICHMENT","DEFAULT_COMMERCE_CONFIG","normalizeCalculateValueFrom","value","CommerceResolver","options","trim","normalizeCalculateValueFrom","input","payload","extracted","source","useCart","useCatalog","productId","asString","cartFallback","catalogProduct","resolvedId","stateItem","productName","price","asNumber","quantity","currency","identity","resolveCatalogItemIdentity","data","key","value","items","item","isPurchase","manualValue","manualCurrency","manualItems","resolvedItems","pixelItems","allowCalculatedValue","shouldCalculateValue","calc","atc","checkout","contentId","contentName","raw","enrichmentSource","fromState","product","catalog","sku","incoming","meta","metaPriceId","metaProductId","metaOfferId","priceId","trimmed","t","CommerceService","config","DEFAULT_COMMERCE_CONFIG","item","DEFAULT_COMMERCE_ENRICHMENT","ProductCatalog","CommerceState","CommerceResolver","OrderCalculator","normalizeCalculateValueFrom","event","fromConfig","fallback","eventType","payload","resolved","items","first","contentId","contentName"]}
1
+ {"version":3,"sources":["../../src/services/dispatcher/DispatcherService.ts","../../src/services/browser-metadata/BrowserMetadataService.ts","../../src/services/fingerprint/FingerprintService.ts","../../src/services/session/session-id.ts","../../src/services/session/SessionService.ts","../../src/services/storage/BrowserStorageAdapter.ts","../../src/services/storage/MemoryStorageAdapter.ts","../../src/services/storage/StorageService.ts","../../src/services/storage/StorageFactory.ts","../../src/services/visitor/visitor-id.ts","../../src/services/visitor/VisitorService.ts","../../src/services/attribution/types.ts","../../src/services/attribution/ClickIdParser.ts","../../src/services/attribution/CookieCollector.ts","../../src/services/attribution/AttributionCollector.ts","../../src/services/attribution/AttributionStore.ts","../../src/services/attribution/AttributionService.ts","../../src/services/commerce/ProductCatalog.ts","../../src/services/commerce/CommerceState.ts","../../src/services/commerce/OrderCalculator.ts","../../src/config/shared/commerce.ts","../../src/services/commerce/CommerceResolver.ts","../../src/services/commerce/CommerceService.ts"],"sourcesContent":["import type { PixelEvent } from '@/events';\nimport type { PixelLogger } from '@/logger/PixelLogger';\n\nimport type { DispatcherService } from './types';\n\ntype EventListener = (event: PixelEvent) => void;\n\nconst MAX_ERROR_MESSAGE_LENGTH = 200;\n\n/**\n * Hardening 18.1 — falha de um listener não interrompe os demais nem propaga\n * para o produtor (trackers/engines). Log sanitizado, sem payload/PII.\n */\nexport class DispatcherServiceImpl implements DispatcherService {\n private readonly listeners = new Set<EventListener>();\n\n private lastEvent: PixelEvent | null = null;\n\n private readonly logger: Pick<PixelLogger, 'warn'> | undefined;\n\n constructor(logger?: Pick<PixelLogger, 'warn'>) {\n this.logger = logger;\n }\n\n dispatch(event: PixelEvent): void {\n this.lastEvent = event;\n\n // Snapshot: permite unsubscribe durante dispatch sem pular listeners.\n const snapshot = [...this.listeners];\n\n for (let index = 0; index < snapshot.length; index += 1) {\n const listener = snapshot[index];\n if (!listener) continue;\n\n try {\n listener(event);\n } catch (error) {\n this.logger?.warn(sanitizeDispatcherError(error, event.type, index));\n }\n }\n }\n\n subscribe(listener: (event: PixelEvent) => void): () => void {\n this.listeners.add(listener);\n\n return () => {\n this.listeners.delete(listener);\n };\n }\n\n clear(): void {\n this.listeners.clear();\n this.lastEvent = null;\n }\n\n getListenerCount(): number {\n return this.listeners.size;\n }\n\n getLastEvent(): PixelEvent | null {\n return this.lastEvent;\n }\n}\n\nexport function sanitizeDispatcherError(\n error: unknown,\n eventType: string,\n listenerIndex: number\n): Record<string, unknown> {\n const name =\n error instanceof Error\n ? error.name\n : typeof error === 'object' && error !== null && 'name' in error\n ? String((error as { name: unknown }).name)\n : 'Error';\n\n let message =\n error instanceof Error\n ? error.message\n : typeof error === 'string'\n ? error\n : 'unknown';\n\n message = message\n .replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g, '[redacted]')\n .replace(/\\+?\\d[\\d\\s().-]{7,}\\d/g, '[redacted]');\n\n if (message.length > MAX_ERROR_MESSAGE_LENGTH) {\n message = `${message.slice(0, MAX_ERROR_MESSAGE_LENGTH)}…`;\n }\n\n return {\n code: 'DISPATCHER_LISTENER_FAILED',\n eventType,\n listenerIndex,\n errorName: name,\n message,\n timestamp: Date.now(),\n };\n}\n","import type { BrowserMetadata, BrowserMetadataService } from './types';\n\nexport class BrowserMetadataServiceImpl implements BrowserMetadataService {\n getMetadata(): BrowserMetadata {\n if (typeof window === 'undefined') {\n return {};\n }\n\n const timezone = (() => {\n try {\n return Intl.DateTimeFormat().resolvedOptions().timeZone;\n } catch {\n return undefined;\n }\n })();\n\n return {\n url: location.href,\n path: location.pathname,\n hostname: location.hostname,\n origin: location.origin,\n title: typeof document !== 'undefined' ? document.title : undefined,\n referrer: typeof document !== 'undefined' ? document.referrer : undefined,\n language: navigator.language,\n timezone,\n userAgent: navigator.userAgent,\n platform: navigator.platform,\n screenWidth: screen.width,\n screenHeight: screen.height,\n colorDepth: screen.colorDepth,\n };\n }\n}\n","import type { PixelConfig } from '@/config';\nimport type { BrowserMetadataService } from '@/services/browser-metadata';\nimport type { StorageService } from '@/services/storage';\n\nimport type { FingerprintService } from './types';\n\nconst DEFAULT_FINGERPRINT_KEY = 'fingerprint';\n\nfunction hashFingerprintInput(input: string): string {\n let hash = 0;\n\n for (let index = 0; index < input.length; index++) {\n hash = (hash << 5) - hash + input.charCodeAt(index);\n hash |= 0;\n }\n\n const positiveHash = Math.abs(hash).toString(16).padStart(8, '0');\n let secondaryHash = 0;\n\n for (let index = input.length - 1; index >= 0; index--) {\n secondaryHash =\n (secondaryHash << 5) - secondaryHash + input.charCodeAt(index);\n secondaryHash |= 0;\n }\n\n return `fp_${positiveHash}${Math.abs(secondaryHash).toString(16).padStart(8, '0')}`;\n}\n\nfunction computeLightFingerprint(\n metadataService: BrowserMetadataService\n): string {\n const metadata = metadataService.getMetadata();\n\n const components = [\n metadata.userAgent ?? '',\n metadata.language ?? '',\n metadata.platform ?? '',\n String(metadata.screenWidth ?? ''),\n String(metadata.screenHeight ?? ''),\n String(metadata.colorDepth ?? ''),\n metadata.timezone ?? '',\n ];\n\n return hashFingerprintInput(components.join('|'));\n}\n\nexport class FingerprintServiceImpl implements FingerprintService {\n private readonly storage: StorageService;\n\n private readonly storageKey: string;\n\n private readonly metadataService: BrowserMetadataService;\n\n constructor(\n storage: StorageService,\n config: PixelConfig,\n metadataService: BrowserMetadataService\n ) {\n this.storage = storage;\n this.storageKey =\n config.storage.keys?.fingerprint ?? DEFAULT_FINGERPRINT_KEY;\n this.metadataService = metadataService;\n }\n\n getFingerprint(): string | null {\n return this.storage.get<string>(this.storageKey);\n }\n\n ensureFingerprint(): string {\n const existing = this.getFingerprint();\n if (existing) return existing;\n\n const fingerprint = computeLightFingerprint(this.metadataService);\n this.storage.set(this.storageKey, fingerprint);\n return fingerprint;\n }\n}\n","function createRandomSuffix(): string {\n if (\n typeof crypto !== 'undefined' &&\n typeof crypto.randomUUID === 'function'\n ) {\n return crypto.randomUUID().replace(/-/g, '');\n }\n\n return `${Date.now()}${Math.random().toString(36).slice(2)}`;\n}\n\nexport function generateSessionId(): string {\n return `ses_${createRandomSuffix()}`;\n}\n","import type { PixelConfig } from '@/config';\nimport type { StorageService } from '@/services/storage';\n\nimport type { EnsureSessionResult, SessionData, SessionService } from './types';\nimport { generateSessionId } from './session-id';\n\nconst DEFAULT_SESSION_KEY = 'session';\n\nexport class SessionServiceImpl implements SessionService {\n private readonly storage: StorageService;\n\n private readonly storageKey: string;\n\n constructor(storage: StorageService, config: PixelConfig) {\n this.storage = storage;\n this.storageKey = config.storage.keys?.session ?? DEFAULT_SESSION_KEY;\n }\n\n getSessionId(): string | null {\n return this.getSessionData()?.sessionId ?? null;\n }\n\n getSessionData(): SessionData | null {\n const raw = this.storage.get<SessionData | string>(this.storageKey);\n if (!raw) return null;\n\n if (typeof raw === 'string') {\n const now = Date.now();\n return {\n sessionId: raw,\n lastActivityAt: now,\n createdAt: now,\n };\n }\n\n return raw;\n }\n\n getLastActivityAt(): number | null {\n return this.getSessionData()?.lastActivityAt ?? null;\n }\n\n isExpired(ttlMs: number): boolean {\n const data = this.getSessionData();\n if (!data) return true;\n\n return Date.now() - data.lastActivityAt > ttlMs;\n }\n\n ensureSession(ttlMs: number): EnsureSessionResult {\n const data = this.getSessionData();\n const now = Date.now();\n\n if (!data) {\n const sessionId = generateSessionId();\n this.writeSessionData({\n sessionId,\n lastActivityAt: now,\n createdAt: now,\n });\n\n return {\n sessionId,\n expired: false,\n created: true,\n };\n }\n\n if (now - data.lastActivityAt > ttlMs) {\n const previousSessionId = data.sessionId;\n const sessionId = generateSessionId();\n\n this.writeSessionData({\n sessionId,\n lastActivityAt: now,\n createdAt: now,\n });\n\n return {\n sessionId,\n expired: true,\n previousSessionId,\n created: false,\n };\n }\n\n return {\n sessionId: data.sessionId,\n expired: false,\n created: false,\n };\n }\n\n ensureSessionId(): string {\n return this.ensureSession(Number.MAX_SAFE_INTEGER).sessionId;\n }\n\n touchActivity(): void {\n const data = this.getSessionData();\n if (!data) return;\n\n this.writeSessionData({\n ...data,\n lastActivityAt: Date.now(),\n });\n }\n\n renew(): string {\n const now = Date.now();\n const sessionId = generateSessionId();\n\n this.writeSessionData({\n sessionId,\n lastActivityAt: now,\n createdAt: now,\n });\n\n return sessionId;\n }\n\n clear(): void {\n this.storage.remove(this.storageKey);\n }\n\n private writeSessionData(data: SessionData): void {\n this.storage.set(this.storageKey, data);\n }\n}\n","import type { StorageAdapter } from './types';\n\nexport class BrowserStorageAdapter implements StorageAdapter {\n private readonly storage: Storage | null;\n\n private readonly memoryFallback = new Map<string, string>();\n\n constructor(storage: Storage) {\n this.storage = typeof window === 'undefined' ? null : storage;\n }\n\n get(key: string): string | null {\n if (this.storage) {\n return this.storage.getItem(key);\n }\n\n return this.memoryFallback.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n if (this.storage) {\n this.storage.setItem(key, value);\n return;\n }\n\n this.memoryFallback.set(key, value);\n }\n\n remove(key: string): void {\n if (this.storage) {\n this.storage.removeItem(key);\n return;\n }\n\n this.memoryFallback.delete(key);\n }\n\n clear(): void {\n // Never clear entire browser storage — namespace removal uses removeKeysMatching.\n if (!this.storage) {\n this.memoryFallback.clear();\n }\n }\n\n removeKeysMatching(predicate: (key: string) => boolean): void {\n if (this.storage) {\n const keysToRemove: string[] = [];\n\n for (let index = 0; index < this.storage.length; index++) {\n const key = this.storage.key(index);\n if (key && predicate(key)) {\n keysToRemove.push(key);\n }\n }\n\n for (const key of keysToRemove) {\n this.storage.removeItem(key);\n }\n\n return;\n }\n\n for (const key of this.memoryFallback.keys()) {\n if (predicate(key)) {\n this.memoryFallback.delete(key);\n }\n }\n }\n}\n","import type { StorageAdapter } from './types';\n\nexport class MemoryStorageAdapter implements StorageAdapter {\n private readonly store = new Map<string, string>();\n\n get(key: string): string | null {\n return this.store.get(key) ?? null;\n }\n\n set(key: string, value: string): void {\n this.store.set(key, value);\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n\n clear(): void {\n this.store.clear();\n }\n\n removeKeysMatching(predicate: (key: string) => boolean): void {\n for (const key of this.store.keys()) {\n if (predicate(key)) {\n this.store.delete(key);\n }\n }\n }\n}\n","import type { StorageAdapter, StorageService } from './types';\n\ntype NamespaceClearableAdapter = StorageAdapter & {\n removeKeysMatching(predicate: (key: string) => boolean): void;\n};\n\nfunction supportsNamespaceClear(\n adapter: StorageAdapter\n): adapter is NamespaceClearableAdapter {\n return (\n 'removeKeysMatching' in adapter &&\n typeof adapter.removeKeysMatching === 'function'\n );\n}\n\nexport class StorageServiceImpl implements StorageService {\n private readonly adapter: StorageAdapter;\n\n private readonly namespace: string;\n\n private readonly prefix?: string;\n\n constructor(adapter: StorageAdapter, namespace: string, prefix?: string) {\n this.adapter = adapter;\n this.namespace = namespace;\n this.prefix = prefix;\n }\n\n get<T>(key: string): T | null {\n const raw = this.adapter.get(this.createKey(key));\n if (raw === null) return null;\n\n try {\n return JSON.parse(raw) as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T): void {\n this.adapter.set(this.createKey(key), JSON.stringify(value));\n }\n\n remove(key: string): void {\n this.adapter.remove(this.createKey(key));\n }\n\n has(key: string): boolean {\n return this.adapter.get(this.createKey(key)) !== null;\n }\n\n clear(): void {\n const namespaceKeyPrefix = this.getNamespaceKeyPrefix();\n\n if (supportsNamespaceClear(this.adapter)) {\n this.adapter.removeKeysMatching(key =>\n key.startsWith(namespaceKeyPrefix)\n );\n return;\n }\n\n this.adapter.clear();\n }\n\n createKey(key: string): string {\n if (this.prefix) {\n return `${this.prefix}:${this.namespace}:${key}`;\n }\n\n return `${this.namespace}:${key}`;\n }\n\n private getNamespaceKeyPrefix(): string {\n if (this.prefix) {\n return `${this.prefix}:${this.namespace}:`;\n }\n\n return `${this.namespace}:`;\n }\n}\n","import type {\n AttributionStoragePersistence,\n QueueStoragePersistence,\n SessionStoragePersistence,\n VisitorStoragePersistence,\n} from '@/config/shared/persistence';\n\nimport { BrowserStorageAdapter } from './BrowserStorageAdapter';\nimport { MemoryStorageAdapter } from './MemoryStorageAdapter';\nimport type { StorageAdapter } from './types';\n\nexport type StoragePersistence =\n | VisitorStoragePersistence\n | SessionStoragePersistence\n | AttributionStoragePersistence\n | QueueStoragePersistence;\n\nexport function createStorageAdapter(\n persistence?: StoragePersistence\n): StorageAdapter {\n const mode = persistence ?? 'memory';\n\n if (typeof window === 'undefined') {\n return new MemoryStorageAdapter();\n }\n\n switch (mode) {\n case 'memory':\n return new MemoryStorageAdapter();\n case 'localStorage':\n return new BrowserStorageAdapter(window.localStorage);\n case 'sessionStorage':\n return new BrowserStorageAdapter(window.sessionStorage);\n case 'cookie_localStorage':\n // TODO: implementar cookie fallback.\n return new BrowserStorageAdapter(window.localStorage);\n case 'cookie':\n return new MemoryStorageAdapter();\n case 'indexedDB':\n return new MemoryStorageAdapter();\n default:\n return new MemoryStorageAdapter();\n }\n}\n\nexport function resolveStorageAdapterName(\n persistence?: StoragePersistence\n): string {\n const mode = persistence ?? 'memory';\n\n switch (mode) {\n case 'localStorage':\n case 'sessionStorage':\n case 'cookie_localStorage':\n return 'BrowserStorageAdapter';\n default:\n return 'MemoryStorageAdapter';\n }\n}\n","function createRandomSuffix(): string {\n if (\n typeof crypto !== 'undefined' &&\n typeof crypto.randomUUID === 'function'\n ) {\n return crypto.randomUUID().replace(/-/g, '');\n }\n\n return `${Date.now()}${Math.random().toString(36).slice(2)}`;\n}\n\nexport function generateVisitorId(): string {\n return `vst_${createRandomSuffix()}`;\n}\n","import type { PixelConfig } from '@/config';\nimport type { StorageService } from '@/services/storage';\n\nimport type { VisitorService } from './types';\nimport { generateVisitorId } from './visitor-id';\n\nconst DEFAULT_VISITOR_KEY = 'visitor';\n\nexport class VisitorServiceImpl implements VisitorService {\n private readonly storage: StorageService;\n\n private readonly storageKey: string;\n\n constructor(storage: StorageService, config: PixelConfig) {\n this.storage = storage;\n this.storageKey = config.storage.keys?.visitor ?? DEFAULT_VISITOR_KEY;\n }\n\n getVisitorId(): string | null {\n return this.storage.get<string>(this.storageKey);\n }\n\n ensureVisitorId(): string {\n const existing = this.getVisitorId();\n if (existing) return existing;\n\n const visitorId = generateVisitorId();\n this.storage.set(this.storageKey, visitorId);\n return visitorId;\n }\n\n clearVisitorId(): void {\n this.storage.remove(this.storageKey);\n }\n}\n","export type AttributionIdentifiers = {\n readonly fbclid?: string;\n readonly fbp?: string;\n readonly fbc?: string;\n\n readonly gclid?: string;\n readonly gbraid?: string;\n readonly wbraid?: string;\n readonly ga?: string;\n readonly gid?: string;\n readonly gclAu?: string;\n\n readonly ttclid?: string;\n readonly ttp?: string;\n\n readonly msclkid?: string;\n readonly liFatId?: string;\n readonly epik?: string;\n\n readonly customClickIds?: Readonly<Record<string, string>>;\n\n readonly firstCollectedAt?: number;\n readonly lastCollectedAt?: number;\n readonly landingUrl?: string;\n readonly referrer?: string;\n};\n\nexport type AttributionConfig = {\n readonly enabled: boolean;\n readonly ttlDays?: number;\n readonly persist?: boolean;\n readonly captureUrlParams?: boolean;\n readonly captureCookies?: boolean;\n readonly customClickIdParams?: string[];\n};\n\nexport const DEFAULT_ATTRIBUTION_CONFIG: AttributionConfig = {\n enabled: true,\n ttlDays: 90,\n persist: true,\n captureUrlParams: true,\n captureCookies: true,\n customClickIdParams: [],\n};\n\nexport const ATTRIBUTION_STORAGE_KEY = 'attribution';\n\nexport interface AttributionService {\n init(): void;\n destroy(): void;\n collect(): AttributionIdentifiers;\n getSnapshot(): AttributionIdentifiers;\n update(partial: Partial<AttributionIdentifiers>): AttributionIdentifiers;\n clear(): void;\n}\n","import type { AttributionIdentifiers } from './types';\n\nconst BUILTIN_CLICK_PARAMS = [\n 'fbclid',\n 'gclid',\n 'gbraid',\n 'wbraid',\n 'ttclid',\n 'msclkid',\n 'epik',\n 'li_fat_id',\n] as const;\n\n/**\n * Parses click IDs from URL search params and maps to AttributionIdentifiers fields.\n */\nexport class ClickIdParser {\n parse(customParams: readonly string[] = []): Partial<AttributionIdentifiers> {\n if (typeof window === 'undefined' || !window.location?.search) {\n return {};\n }\n\n try {\n const params = new URLSearchParams(window.location.search);\n const result: Record<string, unknown> = {};\n const customClickIds: Record<string, string> = {};\n\n for (const key of BUILTIN_CLICK_PARAMS) {\n const value = params.get(key);\n if (!value) continue;\n\n if (key === 'li_fat_id') {\n result.liFatId = value;\n } else {\n result[key] = value;\n }\n }\n\n for (const key of customParams) {\n const value = params.get(key);\n if (value) customClickIds[key] = value;\n }\n\n if (Object.keys(customClickIds).length > 0) {\n result.customClickIds = customClickIds;\n }\n\n return result as Partial<AttributionIdentifiers>;\n } catch {\n return {};\n }\n }\n\n /**\n * Meta convention: when fbclid is present and _fbc cookie is missing,\n * synthesize fbc = fb.1.<timestamp_ms>.<fbclid>\n */\n synthesizeFbc(fbclid: string, existingFbc?: string): string | undefined {\n if (existingFbc) return existingFbc;\n if (!fbclid) return undefined;\n return `fb.1.${Date.now()}.${fbclid}`;\n }\n}\n","/**\n * SSR-safe cookie reader for attribution identifiers.\n */\nexport class CookieCollector {\n collectKnown(): Readonly<Record<string, string>> {\n if (typeof document === 'undefined') return {};\n\n const cookies = this.parseCookies();\n const result: Record<string, string> = {};\n\n const map: Record<string, string> = {\n _fbp: 'fbp',\n _fbc: 'fbc',\n _ga: 'ga',\n _gid: 'gid',\n _gcl_au: 'gclAu',\n _ttp: 'ttp',\n li_fat_id: 'liFatId',\n epik: 'epik',\n };\n\n for (const [cookieName, field] of Object.entries(map)) {\n const value = cookies[cookieName];\n if (value) result[field] = value;\n }\n\n return result;\n }\n\n private parseCookies(): Record<string, string> {\n if (typeof document === 'undefined') return {};\n\n try {\n return document.cookie.split(';').reduce(\n (acc, part) => {\n const [rawKey, ...rest] = part.trim().split('=');\n if (!rawKey) return acc;\n acc[rawKey] = decodeURIComponent(rest.join('=') || '');\n return acc;\n },\n {} as Record<string, string>\n );\n } catch {\n return {};\n }\n }\n}\n","import type { AttributionIdentifiers } from './types';\nimport { ClickIdParser } from './ClickIdParser';\nimport { CookieCollector } from './CookieCollector';\n\n/**\n * Collects attribution signals from URL + cookies and merges them.\n */\nexport class AttributionCollector {\n private readonly clickIdParser = new ClickIdParser();\n\n private readonly cookieCollector = new CookieCollector();\n\n private readonly customParams: readonly string[];\n\n private readonly captureUrlParams: boolean;\n\n private readonly captureCookies: boolean;\n\n constructor(\n options: {\n customParams?: readonly string[];\n captureUrlParams?: boolean;\n captureCookies?: boolean;\n } = {}\n ) {\n this.customParams = options.customParams ?? [];\n this.captureUrlParams = options.captureUrlParams !== false;\n this.captureCookies = options.captureCookies !== false;\n }\n\n collectFresh(): Partial<AttributionIdentifiers> {\n const fromUrl = this.captureUrlParams\n ? this.clickIdParser.parse(this.customParams)\n : {};\n const fromCookies = this.captureCookies\n ? this.cookieCollector.collectKnown()\n : {};\n\n const merged: Record<string, unknown> = {\n ...fromCookies,\n ...fromUrl,\n };\n\n const customClickIds = {\n ...((fromCookies as AttributionIdentifiers).customClickIds ?? {}),\n ...(fromUrl.customClickIds ?? {}),\n };\n if (Object.keys(customClickIds).length > 0) {\n merged.customClickIds = customClickIds;\n }\n\n if (typeof merged.fbclid === 'string' && merged.fbclid) {\n const fbc = this.clickIdParser.synthesizeFbc(\n merged.fbclid,\n typeof merged.fbc === 'string' ? merged.fbc : undefined\n );\n if (fbc) merged.fbc = fbc;\n }\n\n if (typeof window !== 'undefined') {\n try {\n merged.landingUrl = window.location.href;\n } catch {\n // ignore\n }\n }\n\n if (typeof document !== 'undefined') {\n try {\n if (document.referrer) merged.referrer = document.referrer;\n } catch {\n // ignore\n }\n }\n\n return merged as Partial<AttributionIdentifiers>;\n }\n\n /**\n * Merge: never overwrite existing defined values with undefined.\n */\n merge(\n existing: AttributionIdentifiers,\n incoming: Partial<AttributionIdentifiers>\n ): AttributionIdentifiers {\n const next: Record<string, unknown> = { ...existing };\n\n for (const [key, value] of Object.entries(incoming)) {\n if (value === undefined || value === null || value === '') continue;\n\n if (key === 'customClickIds' && typeof value === 'object') {\n next.customClickIds = {\n ...((existing.customClickIds as Record<string, string>) ?? {}),\n ...(value as Record<string, string>),\n };\n continue;\n }\n\n next[key] = value;\n }\n\n const now = Date.now();\n if (!existing.firstCollectedAt) {\n next.firstCollectedAt = now;\n }\n next.lastCollectedAt = now;\n\n return next as AttributionIdentifiers;\n }\n}\n","import type { StorageService } from '@/services/storage/types';\n\nimport { ATTRIBUTION_STORAGE_KEY, type AttributionIdentifiers } from './types';\n\n/**\n * Persists AttributionIdentifiers via StorageService only (no direct localStorage).\n */\nexport class AttributionStore {\n private readonly storage: StorageService;\n\n private readonly persist: boolean;\n\n private readonly ttlMs: number;\n\n private readonly storageKey: string;\n\n constructor(\n storage: StorageService,\n options: { persist: boolean; ttlDays: number; storageKey?: string }\n ) {\n this.storage = storage;\n this.persist = options.persist;\n this.ttlMs = options.ttlDays * 24 * 60 * 60 * 1000;\n this.storageKey = options.storageKey ?? ATTRIBUTION_STORAGE_KEY;\n }\n\n load(): AttributionIdentifiers | null {\n if (!this.persist) return null;\n\n try {\n const snapshot = this.storage.get<AttributionIdentifiers>(\n this.storageKey\n );\n if (!snapshot) return null;\n\n if (this.isExpired(snapshot)) {\n this.clear();\n return null;\n }\n\n return snapshot;\n } catch {\n return null;\n }\n }\n\n save(snapshot: AttributionIdentifiers): void {\n if (!this.persist) return;\n\n try {\n this.storage.set(this.storageKey, snapshot);\n } catch {\n // quota / SSR — keep in-memory only\n }\n }\n\n clear(): void {\n try {\n this.storage.remove(this.storageKey);\n } catch {\n // ignore\n }\n }\n\n private isExpired(snapshot: AttributionIdentifiers): boolean {\n const anchor = snapshot.lastCollectedAt ?? snapshot.firstCollectedAt;\n if (!anchor) return false;\n return Date.now() - anchor > this.ttlMs;\n }\n}\n","import type { StorageService } from '@/services/storage/types';\n\nimport { AttributionCollector } from './AttributionCollector';\nimport { AttributionStore } from './AttributionStore';\nimport {\n DEFAULT_ATTRIBUTION_CONFIG,\n type AttributionConfig,\n type AttributionIdentifiers,\n type AttributionService,\n} from './types';\n\nexport class AttributionServiceImpl implements AttributionService {\n private readonly store: AttributionStore;\n\n private readonly collector: AttributionCollector;\n\n private readonly enabled: boolean;\n\n private snapshot: AttributionIdentifiers = {};\n\n private active = false;\n\n constructor(\n storage: StorageService,\n config: AttributionConfig = DEFAULT_ATTRIBUTION_CONFIG\n ) {\n this.enabled = config.enabled !== false;\n this.store = new AttributionStore(storage, {\n persist: config.persist !== false,\n ttlDays: config.ttlDays ?? 90,\n });\n this.collector = new AttributionCollector({\n customParams: config.customClickIdParams ?? [],\n captureUrlParams: config.captureUrlParams !== false,\n captureCookies: config.captureCookies !== false,\n });\n }\n\n init(): void {\n if (this.active) return;\n this.active = true;\n\n if (!this.enabled) return;\n\n const stored = this.store.load();\n if (stored) {\n this.snapshot = stored;\n }\n\n this.collect();\n }\n\n destroy(): void {\n if (!this.active) return;\n this.active = false;\n }\n\n collect(): AttributionIdentifiers {\n if (!this.enabled) return this.snapshot;\n\n const fresh = this.collector.collectFresh();\n this.snapshot = this.collector.merge(this.snapshot, fresh);\n this.store.save(this.snapshot);\n return this.snapshot;\n }\n\n getSnapshot(): AttributionIdentifiers {\n return { ...this.snapshot };\n }\n\n update(partial: Partial<AttributionIdentifiers>): AttributionIdentifiers {\n this.snapshot = this.collector.merge(this.snapshot, partial);\n this.store.save(this.snapshot);\n return this.getSnapshot();\n }\n\n clear(): void {\n this.snapshot = {};\n this.store.clear();\n }\n}\n","import type { CommerceProduct } from '@/config/shared/commerce';\n\nexport type ProductCatalogOptions = {\n readonly defaultCurrency?: string;\n};\n\nexport type ProductCatalogSnapshot = {\n readonly products: CommerceProduct[];\n readonly count: number;\n};\n\n/**\n * Catálogo de produtos configurados em `config.commerce.catalog`.\n * Isolado por instância — sem estado global / module-level.\n * Não acessa DOM, Transport nem altera payloads de eventos.\n */\nexport class ProductCatalog {\n private readonly productsById = new Map<string, CommerceProduct>();\n\n private readonly productsBySku = new Map<string, CommerceProduct>();\n\n private readonly orderedIds: string[] = [];\n\n constructor(\n products: readonly CommerceProduct[] | undefined = [],\n options: ProductCatalogOptions = {}\n ) {\n this.indexProducts(products ?? [], options.defaultCurrency);\n }\n\n list(): CommerceProduct[] {\n return this.orderedIds.map(id =>\n this.cloneProduct(this.productsById.get(id)!)\n );\n }\n\n getById(id: string): CommerceProduct | null {\n if (!id) return null;\n const product = this.productsById.get(id);\n return product ? this.cloneProduct(product) : null;\n }\n\n getBySku(sku: string): CommerceProduct | null {\n if (!sku) return null;\n const product = this.productsBySku.get(sku);\n return product ? this.cloneProduct(product) : null;\n }\n\n hasProduct(id: string): boolean {\n return Boolean(id) && this.productsById.has(id);\n }\n\n getSnapshot(): ProductCatalogSnapshot {\n const products = this.list();\n return { products, count: products.length };\n }\n\n private indexProducts(\n products: readonly CommerceProduct[],\n defaultCurrency?: string\n ): void {\n for (const raw of products) {\n if (!raw || typeof raw !== 'object') continue;\n\n const id = typeof raw.id === 'string' ? raw.id.trim() : '';\n if (!id) continue;\n\n // Duplicado por id: mantém o primeiro (determinístico).\n if (this.productsById.has(id)) continue;\n\n const product = this.normalizeProduct(raw, id, defaultCurrency);\n this.productsById.set(id, product);\n this.orderedIds.push(id);\n\n const sku = typeof product.sku === 'string' ? product.sku.trim() : '';\n if (sku && !this.productsBySku.has(sku)) {\n this.productsBySku.set(sku, product);\n }\n }\n }\n\n private normalizeProduct(\n raw: CommerceProduct,\n id: string,\n defaultCurrency?: string\n ): CommerceProduct {\n const sku =\n typeof raw.sku === 'string' && raw.sku.trim()\n ? raw.sku.trim()\n : undefined;\n\n const currency =\n typeof raw.currency === 'string' && raw.currency.trim()\n ? raw.currency.trim()\n : defaultCurrency;\n\n const quantity =\n typeof raw.quantity === 'number' && Number.isFinite(raw.quantity)\n ? raw.quantity\n : undefined;\n\n return {\n ...raw,\n id,\n ...(sku !== undefined ? { sku } : {}),\n ...(currency !== undefined ? { currency } : {}),\n ...(quantity !== undefined ? { quantity } : {}),\n ...(raw.metadata ? { metadata: { ...raw.metadata } } : {}),\n };\n }\n\n private cloneProduct(product: CommerceProduct): CommerceProduct {\n return {\n ...product,\n ...(product.metadata ? { metadata: { ...product.metadata } } : {}),\n };\n }\n}\n","import type { CommerceCartItem } from '@/config/shared/commerce';\n\nexport type CommerceStateOptions = {\n /**\n * Quando `false`, `upsertItem` só atualiza itens já presentes\n * (não adiciona novos productIds). Default: `true`.\n */\n readonly allowDynamicItems?: boolean;\n};\n\nexport type CommerceStateSnapshot = {\n /**\n * Estado vivo do carrinho (runtime).\n * Não confundir com `commerce.cart.initialItems` da config.\n */\n readonly selectedItems: CommerceCartItem[];\n readonly count: number;\n};\n\n/**\n * Estado em memória do cart da instância.\n * Inicializado com `config.commerce.cart.initialItems`.\n * Não persiste, não acessa DOM/Transport e não dispara eventos.\n */\nexport class CommerceState {\n private readonly itemsByProductId = new Map<string, CommerceCartItem>();\n\n private readonly allowDynamicItems: boolean;\n\n constructor(\n initialItems: readonly CommerceCartItem[] | undefined = [],\n options: CommerceStateOptions = {}\n ) {\n this.allowDynamicItems = options.allowDynamicItems !== false;\n this.seed(initialItems ?? []);\n }\n\n getSelectedItems(): CommerceCartItem[] {\n return Array.from(this.itemsByProductId.values()).map(item =>\n this.cloneItem(item)\n );\n }\n\n hasItem(productId: string): boolean {\n return Boolean(productId) && this.itemsByProductId.has(productId);\n }\n\n getItem(productId: string): CommerceCartItem | null {\n if (!productId) return null;\n const item = this.itemsByProductId.get(productId);\n return item ? this.cloneItem(item) : null;\n }\n\n /**\n * Insere ou atualiza item.\n * - Sem `productId` → no-op\n * - `selected === false` → remove se existir / não adiciona\n * - `quantity <= 0` → remove\n * - `allowDynamicItems === false` e item novo → no-op\n */\n upsertItem(item: CommerceCartItem): void {\n if (!item || typeof item !== 'object') return;\n\n const productId =\n typeof item.productId === 'string' ? item.productId.trim() : '';\n if (!productId) return;\n\n if (item.selected === false) {\n this.itemsByProductId.delete(productId);\n return;\n }\n\n const quantity = this.normalizeQuantity(item.quantity);\n if (quantity <= 0) {\n this.itemsByProductId.delete(productId);\n return;\n }\n\n const exists = this.itemsByProductId.has(productId);\n if (!exists && !this.allowDynamicItems) return;\n\n const previous = this.itemsByProductId.get(productId);\n const metadata = item.metadata\n ? { ...item.metadata }\n : previous?.metadata\n ? { ...previous.metadata }\n : undefined;\n\n const next: CommerceCartItem = {\n ...previous,\n ...item,\n productId,\n quantity,\n selected: true,\n ...(metadata ? { metadata } : {}),\n };\n\n this.itemsByProductId.set(productId, next);\n }\n\n removeItem(productId: string): void {\n if (!productId) return;\n this.itemsByProductId.delete(productId);\n }\n\n /**\n * Atualiza quantidade. `quantity <= 0` remove o item.\n */\n updateQuantity(productId: string, quantity: number): void {\n if (!productId || !this.itemsByProductId.has(productId)) return;\n\n const normalized = this.normalizeQuantity(quantity);\n if (normalized <= 0) {\n this.itemsByProductId.delete(productId);\n return;\n }\n\n const current = this.itemsByProductId.get(productId)!;\n this.itemsByProductId.set(productId, {\n ...current,\n quantity: normalized,\n });\n }\n\n clear(): void {\n this.itemsByProductId.clear();\n }\n\n getSnapshot(): CommerceStateSnapshot {\n const selectedItems = this.getSelectedItems();\n return { selectedItems, count: selectedItems.length };\n }\n\n private seed(initialItems: readonly CommerceCartItem[]): void {\n for (const item of initialItems) {\n // Seed ignora allowDynamicItems — itens da config sempre entram\n // (exceto selected:false / inválidos / quantity<=0).\n this.seedItem(item);\n }\n }\n\n private seedItem(item: CommerceCartItem): void {\n if (!item || typeof item !== 'object') return;\n\n const productId =\n typeof item.productId === 'string' ? item.productId.trim() : '';\n if (!productId) return;\n if (item.selected === false) return;\n\n const quantity = this.normalizeQuantity(item.quantity);\n if (quantity <= 0) return;\n\n // Duplicado por productId no seed: mantém o primeiro.\n if (this.itemsByProductId.has(productId)) return;\n\n this.itemsByProductId.set(productId, {\n ...item,\n productId,\n quantity,\n selected: true,\n ...(item.metadata ? { metadata: { ...item.metadata } } : {}),\n });\n }\n\n private normalizeQuantity(quantity: number | undefined): number {\n if (quantity === undefined || quantity === null) return 1;\n if (typeof quantity !== 'number' || !Number.isFinite(quantity)) return 1;\n return quantity;\n }\n\n private cloneItem(item: CommerceCartItem): CommerceCartItem {\n return {\n ...item,\n ...(item.metadata ? { metadata: { ...item.metadata } } : {}),\n };\n }\n}\n","/**\n * Calcula value/currency a partir de items resolvidos.\n * Não conhece DOM, detectors, Transport nem Dispatcher.\n * Não muta o input.\n */\n\nexport type ResolvedCommerceItem = {\n productId?: string;\n sku?: string;\n productName?: string;\n price?: number;\n quantity?: number;\n currency?: string;\n category?: string;\n variant?: string;\n brand?: string;\n type?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type OrderCalculationInput = {\n items?: ResolvedCommerceItem[];\n value?: number;\n currency?: string;\n defaultCurrency?: string;\n};\n\nexport type OrderCalculationResult = {\n items: ResolvedCommerceItem[];\n value?: number;\n currency?: string;\n};\n\nexport class OrderCalculator {\n calculate(input: OrderCalculationInput): OrderCalculationResult {\n const sourceItems = Array.isArray(input.items) ? input.items : [];\n const items = sourceItems.map(item => this.cloneItem(item));\n\n for (const item of items) {\n if (item.quantity == null || !Number.isFinite(item.quantity)) {\n item.quantity = 1;\n }\n }\n\n const value =\n typeof input.value === 'number' && Number.isFinite(input.value)\n ? input.value\n : this.sumValue(items);\n\n const currency = this.resolveCurrency(input, items);\n\n return {\n items,\n ...(value !== undefined ? { value } : {}),\n ...(currency !== undefined ? { currency } : {}),\n };\n }\n\n private sumValue(items: ResolvedCommerceItem[]): number | undefined {\n let total = 0;\n let hasPriced = false;\n\n for (const item of items) {\n if (typeof item.price !== 'number' || !Number.isFinite(item.price)) {\n continue;\n }\n const qty =\n typeof item.quantity === 'number' && Number.isFinite(item.quantity)\n ? item.quantity\n : 1;\n total += item.price * qty;\n hasPriced = true;\n }\n\n return hasPriced ? total : undefined;\n }\n\n /**\n * Ordem: currency manual → primeiro item com currency → defaultCurrency.\n * Multi-currency: determinístico — usa o primeiro item com currency\n * (não normaliza conversão entre moedas nesta etapa).\n */\n private resolveCurrency(\n input: OrderCalculationInput,\n items: ResolvedCommerceItem[]\n ): string | undefined {\n if (typeof input.currency === 'string' && input.currency.trim()) {\n return input.currency.trim();\n }\n\n for (const item of items) {\n if (typeof item.currency === 'string' && item.currency.trim()) {\n return item.currency.trim();\n }\n }\n\n if (\n typeof input.defaultCurrency === 'string' &&\n input.defaultCurrency.trim()\n ) {\n return input.defaultCurrency.trim();\n }\n\n return undefined;\n }\n\n private cloneItem(item: ResolvedCommerceItem): ResolvedCommerceItem {\n return {\n ...item,\n ...(item.metadata ? { metadata: { ...item.metadata } } : {}),\n };\n }\n}\n","/**\n * Contratos globais de commerce (root `PixelConfig.commerce`).\n * Não pertencem a conversion — representam o contexto comercial da página/fluxo.\n */\n\nexport type ProductType =\n | 'main'\n | 'order_bump'\n | 'upsell'\n | 'downsell'\n | 'cross_sell'\n | 'addon'\n | 'subscription'\n | 'custom'\n | 'other';\n\nexport type CommerceProduct = {\n id: string;\n name?: string;\n sku?: string;\n type?: ProductType;\n price?: number;\n currency?: string;\n quantity?: number;\n category?: string;\n variant?: string;\n brand?: string;\n metadata?: Record<string, unknown>;\n};\n\nexport type CommerceCartItem = {\n productId: string;\n quantity?: number;\n price?: number;\n currency?: string;\n selected?: boolean;\n metadata?: Record<string, unknown>;\n};\n\nexport type CommerceCartMode =\n | 'landing_page'\n | 'single_product'\n | 'multi_product'\n | 'checkout'\n | 'upsell'\n | 'custom'\n | 'cart'\n | 'funnel';\n\nexport type CommerceCalculateValueFrom =\n | 'cart'\n | 'event'\n | 'manual'\n | 'catalog';\n\nexport type CommerceEnrichmentSource =\n | 'cart'\n | 'event'\n | 'event_or_cart'\n | 'catalog';\n\nexport type CommerceEventEnrichmentConfig = {\n enabled: boolean;\n source?: CommerceEnrichmentSource;\n};\n\nexport type CommerceEnrichmentConfig = {\n pageView?: CommerceEventEnrichmentConfig;\n viewContent?: CommerceEventEnrichmentConfig;\n lead?: CommerceEventEnrichmentConfig;\n addToCart?: CommerceEventEnrichmentConfig;\n removeFromCart?: CommerceEventEnrichmentConfig;\n initiateCheckout?: CommerceEventEnrichmentConfig;\n addPaymentInfo?: CommerceEventEnrichmentConfig;\n purchase?: CommerceEventEnrichmentConfig;\n};\n\nexport type ProductCatalogConfig = {\n products?: CommerceProduct[];\n};\n\nexport type CommerceCartConfig = {\n mode?: CommerceCartMode;\n /** Seed inicial do carrinho — não é estado vivo. */\n initialItems?: CommerceCartItem[];\n allowDynamicItems?: boolean;\n calculateValueFrom?: CommerceCalculateValueFrom;\n metadata?: Record<string, unknown>;\n};\n\nexport type CommerceMappingsConfig = {\n attributes?: Record<string, string[]>;\n fields?: Record<string, string[]>;\n};\n\nexport type CommerceConfig = {\n enabled?: boolean;\n currency?: string;\n catalog?: ProductCatalogConfig;\n cart?: CommerceCartConfig;\n mappings?: CommerceMappingsConfig;\n enrichment?: CommerceEnrichmentConfig;\n};\n\nexport const DEFAULT_COMMERCE_ENRICHMENT: Required<CommerceEnrichmentConfig> = {\n pageView: { enabled: true, source: 'cart' },\n viewContent: { enabled: true, source: 'event_or_cart' },\n lead: { enabled: false, source: 'event_or_cart' },\n addToCart: { enabled: true, source: 'event_or_cart' },\n removeFromCart: { enabled: true, source: 'event_or_cart' },\n initiateCheckout: { enabled: true, source: 'cart' },\n addPaymentInfo: { enabled: true, source: 'cart' },\n purchase: { enabled: true, source: 'cart' },\n};\n\n/**\n * Commerce on by default so catalog/cart enrichment runs when products exist.\n * Empty catalog / empty cart is a no-op.\n */\nexport const DEFAULT_COMMERCE_CONFIG: CommerceConfig = {\n enabled: true,\n currency: 'BRL',\n catalog: {\n products: [],\n },\n cart: {\n mode: 'custom',\n initialItems: [],\n allowDynamicItems: true,\n calculateValueFrom: 'cart',\n },\n mappings: {\n attributes: {},\n fields: {},\n },\n enrichment: { ...DEFAULT_COMMERCE_ENRICHMENT },\n};\n\n/** Normaliza calculateValueFrom (inclui aliases legado em runtime). */\nexport function normalizeCalculateValueFrom(\n value: CommerceCalculateValueFrom | string | undefined\n): 'cart' | 'event' | 'manual' | 'catalog' {\n switch (value) {\n case 'event':\n case 'event_items':\n return 'event';\n case 'manual':\n return 'manual';\n case 'catalog':\n return 'catalog';\n case 'cart':\n case 'selected_items':\n default:\n return 'cart';\n }\n}\n","import type { CommerceCalculateValueFrom } from '@/config/shared/commerce';\nimport { normalizeCalculateValueFrom } from '@/config/shared/commerce';\nimport type { PixelItem } from '@/events/conversion';\n\nimport type { CommerceState } from './CommerceState';\nimport type { ProductCatalog } from './ProductCatalog';\nimport type { OrderCalculator, ResolvedCommerceItem } from './OrderCalculator';\n\nexport type CommerceEventType =\n | 'ADD_TO_CART'\n | 'REMOVE_FROM_CART'\n | 'INITIATE_CHECKOUT'\n | 'PURCHASE'\n | 'VIEW_CONTENT'\n | 'ADD_PAYMENT_INFO';\n\nexport type ExtractedProductInput = {\n productId?: string;\n productName?: string;\n price?: number;\n quantity?: number;\n currency?: string;\n sku?: string;\n};\n\nexport type CommerceResolverInput = {\n eventType: CommerceEventType;\n payload?: Record<string, unknown>;\n extractedProduct?: ExtractedProductInput;\n enrichmentSource?: import('@/config/shared/commerce').CommerceEnrichmentSource;\n items?: Array<{\n productId?: string;\n id?: string;\n sku?: string;\n name?: string;\n productName?: string;\n price?: number;\n quantity?: number;\n currency?: string;\n category?: string;\n }>;\n};\n\nexport type CommerceResolverResult = {\n data: Record<string, unknown>;\n items?: ResolvedCommerceItem[];\n value?: number;\n currency?: string;\n};\n\nexport type CommerceResolverOptions = {\n catalog: ProductCatalog;\n state: CommerceState;\n calculator: OrderCalculator;\n defaultCurrency?: string;\n calculateValueFrom?: CommerceCalculateValueFrom;\n};\n\n/**\n * Combina payload + extracted + state + catalog + defaults.\n * Não dispara eventos, não escreve em CommerceState, não conhece DOM/Transport.\n *\n * Prioridade de merge por campo:\n * manual payload > extractedProduct > commerce state > catalog > defaults\n */\nexport class CommerceResolver {\n private readonly catalog: ProductCatalog;\n\n private readonly state: CommerceState;\n\n private readonly calculator: OrderCalculator;\n\n private readonly defaultCurrency?: string;\n\n private readonly calculateValueFrom: ReturnType<\n typeof normalizeCalculateValueFrom\n >;\n\n constructor(options: CommerceResolverOptions) {\n this.catalog = options.catalog;\n this.state = options.state;\n this.calculator = options.calculator;\n this.defaultCurrency = trim(options.defaultCurrency);\n this.calculateValueFrom = normalizeCalculateValueFrom(\n options.calculateValueFrom\n );\n }\n\n resolve(input: CommerceResolverInput): CommerceResolverResult {\n const source = input.enrichmentSource;\n\n // source: 'event' — não completa via cart/catalog\n if (source === 'event') {\n return { data: { ...(input.payload ?? {}) } };\n }\n\n switch (input.eventType) {\n case 'ADD_TO_CART':\n return this.resolveAddToCart(input);\n case 'REMOVE_FROM_CART':\n return this.resolveRemoveFromCart(input);\n case 'INITIATE_CHECKOUT':\n return this.resolveCheckoutLike(input, false);\n case 'PURCHASE':\n return this.resolveCheckoutLike(input, true);\n case 'VIEW_CONTENT':\n return this.resolveViewContent(input);\n case 'ADD_PAYMENT_INFO':\n return this.resolveCheckoutLike(input, false);\n default:\n return { data: { ...(input.payload ?? {}) } };\n }\n }\n\n private resolveAddToCart(\n input: CommerceResolverInput\n ): CommerceResolverResult {\n const payload = input.payload ?? {};\n const extracted = input.extractedProduct ?? {};\n const source = input.enrichmentSource ?? 'event_or_cart';\n const useCart = source === 'cart' || source === 'event_or_cart';\n const useCatalog =\n source === 'catalog' || source === 'cart' || source === 'event_or_cart';\n\n let productId =\n asString(payload.priceId) ??\n asString(payload.productId) ??\n asString(extracted.productId) ??\n (useCatalog\n ? this.lookupIdBySku(asString(payload.sku) ?? asString(extracted.sku))\n : undefined);\n\n // Fallback: sem productId/sku no evento → item principal do cart\n const cartFallback =\n !productId && useCart ? this.resolvePrimaryCartItem() : null;\n if (!productId && cartFallback) {\n productId = cartFallback.productId;\n }\n\n const catalogProduct =\n useCatalog && productId\n ? this.catalog.getById(productId)\n : useCatalog\n ? this.lookupProductBySku(\n asString(payload.sku) ?? asString(extracted.sku)\n )\n : null;\n\n const resolvedId = productId ?? catalogProduct?.id;\n const stateItem =\n useCart && resolvedId\n ? (this.state.getItem(resolvedId) ?? cartFallback)\n : null;\n\n // source: 'catalog' sem productId/sku → não injeta cart\n if (source === 'catalog' && !resolvedId && !catalogProduct) {\n return { data: { ...payload } };\n }\n\n const productName =\n asString(payload.productName) ??\n asString(extracted.productName) ??\n catalogProduct?.name;\n\n const price =\n asNumber(payload.price) ??\n asNumber(extracted.price) ??\n (useCart ? asNumber(stateItem?.price) : undefined) ??\n catalogProduct?.price;\n\n const quantity =\n asNumber(payload.quantity) ??\n asNumber(extracted.quantity) ??\n (useCart ? asNumber(stateItem?.quantity) : undefined) ??\n catalogProduct?.quantity ??\n 1;\n\n const currency =\n asString(payload.currency) ??\n asString(extracted.currency) ??\n (useCart ? asString(stateItem?.currency) : undefined) ??\n catalogProduct?.currency ??\n this.defaultCurrency;\n\n const identity = resolveCatalogItemIdentity(catalogProduct, {\n priceId: asString(payload.priceId),\n productId: resolvedId,\n offerId: asString(payload.offerId),\n id: asString(payload.id),\n });\n\n const data: Record<string, unknown> = {};\n if (identity.id) data.id = identity.id;\n if (identity.priceId) data.priceId = identity.priceId;\n if (identity.productId) data.productId = identity.productId;\n if (identity.offerId) data.offerId = identity.offerId;\n if (productName) data.productName = productName;\n if (price !== undefined) data.price = price;\n if (currency) data.currency = currency;\n if (quantity !== undefined) data.quantity = quantity;\n\n // Preserva campos extras do payload (sem sobrescrever resolvidos).\n for (const [key, value] of Object.entries(payload)) {\n if (value === undefined) continue;\n if (!(key in data)) data[key] = value;\n }\n\n return { data };\n }\n\n /**\n * Escolhe o item principal do cart runtime:\n * 1. único item → esse\n * 2. múltiplos → preferir catalog.type === 'main'\n * 3. senão → primeiro do cart\n * 4. cart vazio → null\n */\n private resolvePrimaryCartItem(): {\n productId: string;\n quantity?: number;\n price?: number;\n currency?: string;\n } | null {\n const items = this.state.getSelectedItems();\n if (items.length === 0) return null;\n if (items.length === 1) return items[0] ?? null;\n\n const main = items.find(item => {\n const product = this.catalog.getById(item.productId);\n return product?.type === 'main';\n });\n return main ?? items[0] ?? null;\n }\n\n private resolveRemoveFromCart(\n input: CommerceResolverInput\n ): CommerceResolverResult {\n const payload = input.payload ?? {};\n const extracted = input.extractedProduct ?? {};\n\n const productId =\n asString(payload.productId) ??\n asString(extracted.productId) ??\n this.lookupIdBySku(asString(payload.sku) ?? asString(extracted.sku));\n\n const catalogProduct = productId ? this.catalog.getById(productId) : null;\n\n const resolvedId = productId ?? catalogProduct?.id;\n const stateItem = resolvedId ? this.state.getItem(resolvedId) : null;\n\n const quantity =\n asNumber(payload.quantity) ??\n asNumber(extracted.quantity) ??\n asNumber(stateItem?.quantity) ??\n 1;\n\n const data: Record<string, unknown> = {};\n if (resolvedId) data.productId = resolvedId;\n if (quantity !== undefined) data.quantity = quantity;\n\n for (const [key, value] of Object.entries(payload)) {\n if (value === undefined) continue;\n if (!(key in data)) data[key] = value;\n }\n\n return { data };\n }\n\n private resolveCheckoutLike(\n input: CommerceResolverInput,\n isPurchase: boolean\n ): CommerceResolverResult {\n const payload = { ...(input.payload ?? {}) };\n const manualValue = asNumber(payload.value);\n const manualCurrency = asString(payload.currency);\n const manualItems = this.readPayloadItems(input);\n const source = input.enrichmentSource;\n\n const resolvedItems = this.resolveItemsSource(manualItems, source);\n const pixelItems = resolvedItems.map(item => this.toPixelItem(item));\n\n const allowCalculatedValue =\n source !== 'catalog' && this.calculateValueFrom !== 'manual';\n\n const shouldCalculateValue =\n manualValue === undefined && allowCalculatedValue;\n\n const calc = this.calculator.calculate({\n items: resolvedItems,\n value: shouldCalculateValue ? undefined : manualValue,\n currency: manualCurrency,\n defaultCurrency: this.defaultCurrency,\n });\n\n const value =\n manualValue !== undefined\n ? manualValue\n : allowCalculatedValue\n ? calc.value\n : undefined;\n\n const currency = manualCurrency ?? calc.currency ?? this.defaultCurrency;\n\n const data: Record<string, unknown> = { ...payload };\n\n if (pixelItems.length > 0) {\n data.items = pixelItems;\n } else if (manualItems === null) {\n delete data.items;\n }\n\n if (value !== undefined) {\n data.value = value;\n } else {\n delete data.value;\n }\n\n if (currency) {\n data.currency = currency;\n }\n\n if (isPurchase) {\n // orderId e demais campos do payload já estão em data via spread.\n }\n\n return {\n data,\n items: calc.items,\n ...(value !== undefined ? { value } : {}),\n ...(currency ? { currency } : {}),\n };\n }\n\n private resolveViewContent(\n input: CommerceResolverInput\n ): CommerceResolverResult {\n const payload = { ...(input.payload ?? {}) };\n const source = input.enrichmentSource ?? 'event_or_cart';\n\n // Tenta completar productId/name/price a partir de payload + cart/catalog\n if (source === 'cart' || source === 'event_or_cart') {\n const atc = this.resolveAddToCart({\n ...input,\n eventType: 'ADD_TO_CART',\n enrichmentSource: source,\n });\n\n const checkout = this.resolveCheckoutLike(\n { ...input, eventType: 'INITIATE_CHECKOUT', enrichmentSource: source },\n false\n );\n\n const data: Record<string, unknown> = { ...payload };\n\n const contentId =\n asString(payload.contentId) ??\n asString(atc.data.productId as string | undefined) ??\n (Array.isArray(checkout.data.items) &&\n checkout.data.items[0] &&\n typeof (checkout.data.items[0] as { id?: unknown }).id === 'string'\n ? (checkout.data.items[0] as { id: string }).id\n : undefined);\n\n const contentName =\n asString(payload.contentName) ??\n asString(atc.data.productName as string | undefined) ??\n (Array.isArray(checkout.data.items) &&\n checkout.data.items[0] &&\n typeof (checkout.data.items[0] as { name?: unknown }).name === 'string'\n ? (checkout.data.items[0] as { name: string }).name\n : undefined);\n\n if (contentId) data.contentId = contentId;\n if (contentName) data.contentName = contentName;\n\n if (\n asNumber(payload.value) === undefined &&\n checkout.value !== undefined\n ) {\n data.value = checkout.value;\n }\n if (!asString(payload.currency) && checkout.currency) {\n data.currency = checkout.currency;\n }\n if (payload.items === undefined && Array.isArray(checkout.data.items)) {\n data.items = checkout.data.items;\n }\n\n return {\n data,\n ...(checkout.value !== undefined ? { value: checkout.value } : {}),\n ...(checkout.currency ? { currency: checkout.currency } : {}),\n items: checkout.items,\n };\n }\n\n if (source === 'catalog') {\n const atc = this.resolveAddToCart({\n ...input,\n eventType: 'ADD_TO_CART',\n enrichmentSource: 'catalog',\n });\n const data: Record<string, unknown> = { ...payload };\n if (atc.data.productId && !asString(payload.contentId)) {\n data.contentId = atc.data.productId;\n }\n if (atc.data.productName && !asString(payload.contentName)) {\n data.contentName = atc.data.productName;\n }\n if (\n atc.data.price !== undefined &&\n asNumber(payload.value) === undefined\n ) {\n data.value = atc.data.price;\n }\n if (atc.data.currency && !asString(payload.currency)) {\n data.currency = atc.data.currency;\n }\n return { data };\n }\n\n return { data: payload };\n }\n\n /**\n * null = payload não trouxe items (usar state conforme calculateValueFrom)\n * [] = payload trouxe items vazios\n */\n private readPayloadItems(\n input: CommerceResolverInput\n ): ResolvedCommerceItem[] | null {\n if (input.items) {\n return input.items.map(item => this.normalizeLooseItem(item));\n }\n\n const raw = input.payload?.items;\n if (raw === undefined) return null;\n if (!Array.isArray(raw)) return null;\n return raw.map(item =>\n this.normalizeLooseItem(\n (item && typeof item === 'object' ? item : {}) as Record<\n string,\n unknown\n >\n )\n );\n }\n\n private resolveItemsSource(\n manualItems: ResolvedCommerceItem[] | null,\n enrichmentSource?: import('@/config/shared/commerce').CommerceEnrichmentSource\n ): ResolvedCommerceItem[] {\n // Items manuais sempre vencem state.\n if (manualItems !== null) {\n return manualItems.map(item => this.enrichItem(item));\n }\n\n // source: 'catalog' — não injeta cart inteiro\n if (enrichmentSource === 'catalog') {\n return [];\n }\n\n // source: 'cart' força fallback do carrinho (independente de calculateValueFrom),\n // exceto quando calculateValueFrom === 'manual' (value/items só do payload).\n if (\n enrichmentSource === 'cart' &&\n this.calculateValueFrom !== 'manual' &&\n this.calculateValueFrom !== 'event'\n ) {\n return this.state.getSelectedItems().map(stateItem =>\n this.enrichItem({\n productId: stateItem.productId,\n price: stateItem.price,\n quantity: stateItem.quantity,\n currency: stateItem.currency,\n })\n );\n }\n\n if (this.calculateValueFrom === 'cart') {\n return this.state.getSelectedItems().map(stateItem =>\n this.enrichItem({\n productId: stateItem.productId,\n price: stateItem.price,\n quantity: stateItem.quantity,\n currency: stateItem.currency,\n })\n );\n }\n\n if (this.calculateValueFrom === 'catalog') {\n const fromState = this.state.getSelectedItems();\n if (fromState.length > 0) {\n return fromState.map(stateItem =>\n this.enrichItem({\n productId: stateItem.productId,\n price: stateItem.price,\n quantity: stateItem.quantity,\n currency: stateItem.currency,\n })\n );\n }\n return this.catalog.list().map(product =>\n this.enrichItem({\n productId: product.id,\n price: product.price,\n quantity: product.quantity ?? 1,\n currency: product.currency,\n productName: product.name,\n sku: product.sku,\n category: product.category,\n })\n );\n }\n\n // event / manual sem items no payload → sem items\n return [];\n }\n\n private enrichItem(item: ResolvedCommerceItem): ResolvedCommerceItem {\n const productId =\n item.productId ?? this.lookupIdBySku(item.sku) ?? undefined;\n const catalog = productId\n ? this.catalog.getById(productId)\n : this.lookupProductBySku(item.sku);\n\n const resolvedId = productId ?? catalog?.id;\n\n return {\n ...item,\n ...(resolvedId ? { productId: resolvedId } : {}),\n productName: item.productName ?? catalog?.name,\n sku: item.sku ?? catalog?.sku,\n price: item.price ?? catalog?.price,\n quantity: item.quantity ?? catalog?.quantity ?? 1,\n currency: item.currency ?? catalog?.currency ?? this.defaultCurrency,\n category: item.category ?? catalog?.category,\n variant: item.variant ?? catalog?.variant,\n brand: item.brand ?? catalog?.brand,\n type: item.type ?? catalog?.type,\n metadata: item.metadata ?? catalog?.metadata,\n };\n }\n\n private toPixelItem(item: ResolvedCommerceItem): PixelItem {\n const pixel: PixelItem = {\n ...(item.productId ? { id: item.productId } : {}),\n ...(item.productName ? { name: item.productName } : {}),\n ...(item.category ? { category: item.category } : {}),\n ...(item.price !== undefined ? { price: item.price } : {}),\n ...(item.quantity !== undefined ? { quantity: item.quantity } : {}),\n };\n return pixel;\n }\n\n private normalizeLooseItem(\n item:\n | Record<string, unknown>\n | {\n productId?: string;\n id?: string;\n sku?: string;\n name?: string;\n productName?: string;\n price?: number;\n quantity?: number;\n currency?: string;\n category?: string;\n }\n ): ResolvedCommerceItem {\n return {\n productId:\n asString((item as { productId?: unknown }).productId) ??\n asString((item as { id?: unknown }).id),\n sku: asString((item as { sku?: unknown }).sku),\n productName:\n asString((item as { productName?: unknown }).productName) ??\n asString((item as { name?: unknown }).name),\n price: asNumber((item as { price?: unknown }).price),\n quantity: asNumber((item as { quantity?: unknown }).quantity),\n currency: asString((item as { currency?: unknown }).currency),\n category: asString((item as { category?: unknown }).category),\n };\n }\n\n private lookupIdBySku(sku: string | undefined): string | undefined {\n if (!sku) return undefined;\n return this.catalog.getBySku(sku)?.id;\n }\n\n private lookupProductBySku(sku: string | undefined) {\n if (!sku) return null;\n return this.catalog.getBySku(sku);\n }\n}\n\nfunction resolveCatalogItemIdentity(\n catalogProduct: import('@/config/shared/commerce').CommerceProduct | null,\n incoming: {\n id?: string;\n priceId?: string;\n productId?: string;\n offerId?: string;\n }\n): {\n id?: string;\n priceId?: string;\n productId?: string;\n offerId?: string;\n} {\n const meta = catalogProduct?.metadata ?? {};\n const metaPriceId = asString(meta.priceId);\n const metaProductId = asString(meta.productId);\n const metaOfferId = asString(meta.offerId);\n\n // Identidade Bemony (id/priceId/offerId) só quando priceId explícito ou metadata.\n // Catálogo genérico do Core continua só com productId.\n const priceId = incoming.priceId ?? metaPriceId;\n if (!priceId) {\n const productId = incoming.productId ?? catalogProduct?.id;\n return {\n ...(incoming.id ? { id: incoming.id } : {}),\n ...(productId ? { productId } : {}),\n ...(incoming.offerId ? { offerId: incoming.offerId } : {}),\n };\n }\n\n return {\n id: incoming.id ?? priceId,\n priceId,\n productId: metaProductId ?? incoming.productId ?? priceId,\n offerId: metaOfferId ?? incoming.offerId ?? priceId,\n };\n}\n\nfunction asString(value: unknown): string | undefined {\n if (typeof value !== 'string') return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction asNumber(value: unknown): number | undefined {\n if (typeof value !== 'number' || !Number.isFinite(value)) return undefined;\n return value;\n}\n\nfunction trim(value: string | undefined): string | undefined {\n if (typeof value !== 'string') return undefined;\n const t = value.trim();\n return t.length > 0 ? t : undefined;\n}\n","import type {\n CommerceConfig,\n CommerceEnrichmentSource,\n CommerceEventEnrichmentConfig,\n} from '@/config/shared/commerce';\nimport {\n DEFAULT_COMMERCE_CONFIG,\n DEFAULT_COMMERCE_ENRICHMENT,\n normalizeCalculateValueFrom,\n} from '@/config/shared/commerce';\nimport type { PixelItem } from '@/events/conversion';\n\nimport { CommerceResolver } from './CommerceResolver';\nimport { CommerceState } from './CommerceState';\nimport { OrderCalculator } from './OrderCalculator';\nimport { ProductCatalog } from './ProductCatalog';\n\nexport type CommerceEnrichmentEvent =\n | 'pageView'\n | 'viewContent'\n | 'lead'\n | 'addToCart'\n | 'removeFromCart'\n | 'initiateCheckout'\n | 'addPaymentInfo'\n | 'purchase';\n\nexport type PageViewCommercePayload = {\n readonly value?: number;\n readonly currency?: string;\n readonly items?: PixelItem[];\n readonly contentId?: string;\n readonly contentName?: string;\n};\n\n/**\n * Serviço compartilhado de commerce (root config).\n * Usado por Core (PAGE_VIEW) e Conversion sem dependência circular\n * entre os módulos.\n */\nexport class CommerceService {\n readonly enabled: boolean;\n\n readonly config: CommerceConfig;\n\n readonly catalog: ProductCatalog;\n\n readonly state: CommerceState;\n\n private readonly resolver: CommerceResolver;\n\n constructor(config: CommerceConfig | undefined) {\n this.config = {\n ...DEFAULT_COMMERCE_CONFIG,\n ...config,\n catalog: {\n products: config?.catalog?.products ?? [],\n },\n cart: {\n ...DEFAULT_COMMERCE_CONFIG.cart,\n ...config?.cart,\n initialItems: config?.cart?.initialItems\n ? config.cart.initialItems.map(item => ({ ...item }))\n : [],\n },\n mappings: {\n attributes: { ...(config?.mappings?.attributes ?? {}) },\n fields: { ...(config?.mappings?.fields ?? {}) },\n },\n enrichment: {\n ...DEFAULT_COMMERCE_ENRICHMENT,\n ...config?.enrichment,\n },\n };\n\n this.enabled = this.config.enabled === true;\n\n this.catalog = new ProductCatalog(this.config.catalog?.products, {\n defaultCurrency: this.config.currency,\n });\n\n this.state = new CommerceState(this.config.cart?.initialItems, {\n allowDynamicItems: this.config.cart?.allowDynamicItems !== false,\n });\n\n this.resolver = new CommerceResolver({\n catalog: this.catalog,\n state: this.state,\n calculator: new OrderCalculator(),\n defaultCurrency: this.config.currency,\n calculateValueFrom: normalizeCalculateValueFrom(\n this.config.cart?.calculateValueFrom\n ),\n });\n }\n\n getEnrichment(event: CommerceEnrichmentEvent): CommerceEventEnrichmentConfig {\n const fromConfig = this.config.enrichment?.[event];\n const fallback = DEFAULT_COMMERCE_ENRICHMENT[event];\n return {\n enabled: fromConfig?.enabled ?? fallback.enabled,\n source: fromConfig?.source ?? fallback.source,\n };\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n isEnrichmentEnabled(event: CommerceEnrichmentEvent): boolean {\n return this.enabled && this.getEnrichment(event).enabled === true;\n }\n\n getEnrichmentSource(\n event: CommerceEnrichmentEvent\n ): CommerceEnrichmentSource {\n return this.getEnrichment(event).source ?? 'event_or_cart';\n }\n\n /**\n * Resolve payload de commerce para um evento conversion.\n * Retorna null quando enrichment está desabilitado (caller usa payload original).\n */\n resolveForEvent(\n event: CommerceEnrichmentEvent,\n eventType:\n | 'ADD_TO_CART'\n | 'REMOVE_FROM_CART'\n | 'INITIATE_CHECKOUT'\n | 'PURCHASE'\n | 'VIEW_CONTENT'\n | 'ADD_PAYMENT_INFO',\n payload: Record<string, unknown> = {}\n ): Record<string, unknown> | null {\n if (!this.isEnrichmentEnabled(event)) return null;\n\n const result = this.resolver.resolve({\n eventType,\n payload,\n enrichmentSource: this.getEnrichmentSource(event),\n });\n\n return result.data;\n }\n\n /**\n * Payload de commerce para PAGE_VIEW quando enrichment.pageView.enabled.\n * Não depende de ConversionEngine.\n */\n resolvePageViewEnrichment(): PageViewCommercePayload | null {\n if (!this.isEnrichmentEnabled('pageView')) return null;\n\n const source = this.getEnrichment('pageView').source ?? 'cart';\n if (source === 'event') return null;\n\n const resolved = this.resolver.resolve({\n eventType: 'INITIATE_CHECKOUT',\n payload: {},\n });\n\n const items = (resolved.data.items as PixelItem[] | undefined) ?? [];\n const first = items[0];\n const contentId =\n first && typeof first.id === 'string' ? first.id : undefined;\n const contentName =\n first && typeof first.name === 'string' ? first.name : undefined;\n\n if (\n resolved.value === undefined &&\n !resolved.currency &&\n items.length === 0\n ) {\n return null;\n }\n\n return {\n ...(resolved.value !== undefined ? { value: resolved.value } : {}),\n ...(resolved.currency ? { currency: resolved.currency } : {}),\n ...(items.length > 0 ? { items } : {}),\n ...(contentId ? { contentId } : {}),\n ...(contentName ? { contentName } : {}),\n };\n }\n\n getResolver(): CommerceResolver {\n return this.resolver;\n }\n\n getCalculateValueFrom(): ReturnType<typeof normalizeCalculateValueFrom> {\n return normalizeCalculateValueFrom(this.config.cart?.calculateValueFrom);\n }\n\n getMappings() {\n return this.config.mappings;\n }\n}\n"],"mappings":"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","names":["DispatcherServiceImpl","logger","event","snapshot","index","listener","error","sanitizeDispatcherError","eventType","listenerIndex","name","message","BrowserMetadataServiceImpl","timezone","DEFAULT_FINGERPRINT_KEY","hashFingerprintInput","input","hash","index","positiveHash","secondaryHash","computeLightFingerprint","metadataService","metadata","components","FingerprintServiceImpl","storage","config","existing","fingerprint","createRandomSuffix","generateSessionId","DEFAULT_SESSION_KEY","SessionServiceImpl","storage","config","raw","now","ttlMs","data","sessionId","generateSessionId","previousSessionId","BrowserStorageAdapter","storage","key","value","predicate","keysToRemove","index","MemoryStorageAdapter","key","value","predicate","supportsNamespaceClear","adapter","StorageServiceImpl","namespace","prefix","key","raw","value","namespaceKeyPrefix","createStorageAdapter","persistence","mode","MemoryStorageAdapter","BrowserStorageAdapter","resolveStorageAdapterName","createRandomSuffix","generateVisitorId","DEFAULT_VISITOR_KEY","VisitorServiceImpl","storage","config","existing","visitorId","generateVisitorId","DEFAULT_ATTRIBUTION_CONFIG","ATTRIBUTION_STORAGE_KEY","BUILTIN_CLICK_PARAMS","ClickIdParser","customParams","params","result","customClickIds","key","value","fbclid","existingFbc","CookieCollector","cookies","result","map","cookieName","field","value","acc","part","rawKey","rest","AttributionCollector","options","ClickIdParser","CookieCollector","fromUrl","fromCookies","merged","customClickIds","fbc","existing","incoming","next","key","value","now","AttributionStore","storage","options","ATTRIBUTION_STORAGE_KEY","snapshot","anchor","AttributionServiceImpl","storage","config","DEFAULT_ATTRIBUTION_CONFIG","AttributionStore","AttributionCollector","stored","fresh","partial","ProductCatalog","products","options","id","product","sku","defaultCurrency","raw","currency","quantity","CommerceState","initialItems","options","item","productId","quantity","previous","metadata","next","normalized","current","selectedItems","OrderCalculator","input","items","item","value","currency","total","hasPriced","qty","DEFAULT_COMMERCE_ENRICHMENT","DEFAULT_COMMERCE_CONFIG","normalizeCalculateValueFrom","value","CommerceResolver","options","trim","normalizeCalculateValueFrom","input","payload","extracted","source","useCart","useCatalog","productId","asString","cartFallback","catalogProduct","resolvedId","stateItem","productName","price","asNumber","quantity","currency","identity","resolveCatalogItemIdentity","data","key","value","items","item","isPurchase","manualValue","manualCurrency","manualItems","resolvedItems","pixelItems","allowCalculatedValue","shouldCalculateValue","calc","atc","checkout","contentId","contentName","raw","enrichmentSource","fromState","product","catalog","sku","incoming","meta","metaPriceId","metaProductId","metaOfferId","priceId","trimmed","t","CommerceService","config","DEFAULT_COMMERCE_CONFIG","item","DEFAULT_COMMERCE_ENRICHMENT","ProductCatalog","CommerceState","CommerceResolver","OrderCalculator","normalizeCalculateValueFrom","event","fromConfig","fallback","eventType","payload","resolved","items","first","contentId","contentName"]}
@@ -1,6 +1,6 @@
1
- import { P as PixelConfig } from './pixel-DMwpppf_.mjs';
1
+ import { P as PixelConfig } from './pixel-_BSDpx4M.mjs';
2
2
  import { P as PixelLogger } from './PixelLogger-B21lEjep.mjs';
3
- import { P as PixelRuntimeServices } from './types-CgrabttM.mjs';
3
+ import { P as PixelRuntimeServices } from './types-D0KVsgzs.mjs';
4
4
 
5
5
  type PixelRuntimeContext = {
6
6
  readonly config: PixelConfig;
@@ -1,5 +1,5 @@
1
1
  import { P as PixelEvent, b as PixelItem, S as StorageService, B as BrowserMetadataService, c as BaseEventBuilder, A as AttributionService, U as UrlContextService } from './index-BxT2d-TK.mjs';
2
- import { a2 as CommerceProduct, X as CommerceCartItem, U as CommerceCalculateValueFrom, $ as CommerceEnrichmentSource, Z as CommerceConfig, a0 as CommerceEventEnrichmentConfig, aa as normalizeCalculateValueFrom, a1 as CommerceMappingsConfig } from './pixel-DMwpppf_.mjs';
2
+ import { ao as CommerceProduct, ai as CommerceCartItem, ag as CommerceCalculateValueFrom, al as CommerceEnrichmentSource, C as CommerceConfig, am as CommerceEventEnrichmentConfig, aw as normalizeCalculateValueFrom, an as CommerceMappingsConfig } from './pixel-_BSDpx4M.mjs';
3
3
 
4
4
  interface DispatcherService {
5
5
  dispatch(event: PixelEvent): void;
@@ -1,5 +1,5 @@
1
1
  import { P as PixelEvent, b as PixelItem, S as StorageService, B as BrowserMetadataService, c as BaseEventBuilder, A as AttributionService, U as UrlContextService } from './index-B8u_3PGG.js';
2
- import { a2 as CommerceProduct, X as CommerceCartItem, U as CommerceCalculateValueFrom, $ as CommerceEnrichmentSource, Z as CommerceConfig, a0 as CommerceEventEnrichmentConfig, aa as normalizeCalculateValueFrom, a1 as CommerceMappingsConfig } from './pixel-2uL4LSyC.js';
2
+ import { ao as CommerceProduct, ai as CommerceCartItem, ag as CommerceCalculateValueFrom, al as CommerceEnrichmentSource, C as CommerceConfig, am as CommerceEventEnrichmentConfig, aw as normalizeCalculateValueFrom, an as CommerceMappingsConfig } from './pixel-DNGbAN5C.js';
3
3
 
4
4
  interface DispatcherService {
5
5
  dispatch(event: PixelEvent): void;
@@ -1,6 +1,6 @@
1
- import { P as PixelConfig } from './pixel-2uL4LSyC.js';
1
+ import { P as PixelConfig } from './pixel-DNGbAN5C.js';
2
2
  import { P as PixelLogger } from './PixelLogger-B21lEjep.js';
3
- import { P as PixelRuntimeServices } from './types-fFcQ1apy.js';
3
+ import { P as PixelRuntimeServices } from './types-D3kJ9bfT.js';
4
4
 
5
5
  type PixelRuntimeContext = {
6
6
  readonly config: PixelConfig;