@sonordev/site-kit 3.3.1 → 3.5.0

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 (257) hide show
  1. package/README.md +2 -2
  2. package/agent-manifest.json +13 -1
  3. package/dist/AnalyticsProvider-35EDQA5V.js +31 -0
  4. package/dist/{AnalyticsProvider-PLGTU56K.js.map → AnalyticsProvider-35EDQA5V.js.map} +1 -1
  5. package/dist/AnalyticsProvider-V5CWTWWO.mjs +10 -0
  6. package/dist/{AnalyticsProvider-3MZ3O5OB.mjs.map → AnalyticsProvider-V5CWTWWO.mjs.map} +1 -1
  7. package/dist/ChatWidget-2OK6DD66.js +19 -0
  8. package/dist/{ChatWidget-FQARJMGU.js.map → ChatWidget-2OK6DD66.js.map} +1 -1
  9. package/dist/ChatWidget-WNT6VNJK.mjs +10 -0
  10. package/dist/{ChatWidget-7JHVRNVE.mjs.map → ChatWidget-WNT6VNJK.mjs.map} +1 -1
  11. package/dist/EngageWidget-7RZIC426.js +18 -0
  12. package/dist/{EngageWidget-DQ62NQPU.js.map → EngageWidget-7RZIC426.js.map} +1 -1
  13. package/dist/EngageWidget-GWME22IP.mjs +9 -0
  14. package/dist/{EngageWidget-VXQOZOYA.mjs.map → EngageWidget-GWME22IP.mjs.map} +1 -1
  15. package/dist/{SignalCore-3SG3LFQL.js → SignalCore-DK4HQBPY.js} +62 -43
  16. package/dist/SignalCore-DK4HQBPY.js.map +1 -0
  17. package/dist/{SignalCore-BKG66B4C.mjs → SignalCore-TW4YA3BW.mjs} +56 -37
  18. package/dist/SignalCore-TW4YA3BW.mjs.map +1 -0
  19. package/dist/SitemapSync-7PXQMF5A.mjs +8 -0
  20. package/dist/{SitemapSync-IO2VOR23.mjs.map → SitemapSync-7PXQMF5A.mjs.map} +1 -1
  21. package/dist/SitemapSync-O3J2DPV7.js +17 -0
  22. package/dist/{SitemapSync-DWX7I6MX.js.map → SitemapSync-O3J2DPV7.js.map} +1 -1
  23. package/dist/analytics/index.js +14 -12
  24. package/dist/analytics/index.mjs +7 -5
  25. package/dist/blog/index.d.mts +3 -3
  26. package/dist/blog/index.d.ts +3 -3
  27. package/dist/blog/index.js +11 -15
  28. package/dist/blog/index.js.map +1 -1
  29. package/dist/blog/index.mjs +2 -2
  30. package/dist/blog/index.mjs.map +1 -1
  31. package/dist/blog/server-ui.d.mts +1 -1
  32. package/dist/blog/server-ui.d.ts +1 -1
  33. package/dist/blog/server-ui.js +198 -9
  34. package/dist/blog/server-ui.js.map +1 -1
  35. package/dist/blog/server-ui.mjs +198 -2
  36. package/dist/blog/server-ui.mjs.map +1 -1
  37. package/dist/blog/server.d.mts +27 -8
  38. package/dist/blog/server.d.ts +27 -8
  39. package/dist/blog/server.js +45 -43
  40. package/dist/blog/server.mjs +3 -1
  41. package/dist/{chunk-QW3T6WH2.mjs → chunk-2NA5CAK5.mjs} +3 -3
  42. package/dist/{chunk-QW3T6WH2.mjs.map → chunk-2NA5CAK5.mjs.map} +1 -1
  43. package/dist/{chunk-WN5A3KSY.mjs → chunk-34IUDOBC.mjs} +2 -2
  44. package/dist/{chunk-WN5A3KSY.mjs.map → chunk-34IUDOBC.mjs.map} +1 -1
  45. package/dist/{chunk-3WRE7ZDC.js → chunk-3KEZ2YHQ.js} +8 -8
  46. package/dist/{chunk-3WRE7ZDC.js.map → chunk-3KEZ2YHQ.js.map} +1 -1
  47. package/dist/{chunk-NQ3K4NWX.mjs → chunk-5WQHWBCW.mjs} +11 -30
  48. package/dist/chunk-5WQHWBCW.mjs.map +1 -0
  49. package/dist/chunk-6EDVCUAG.mjs +29 -0
  50. package/dist/chunk-6EDVCUAG.mjs.map +1 -0
  51. package/dist/{chunk-ZFF3BKNE.mjs → chunk-6JVDIW5L.mjs} +4 -4
  52. package/dist/{chunk-ZFF3BKNE.mjs.map → chunk-6JVDIW5L.mjs.map} +1 -1
  53. package/dist/{chunk-7TX5BKVA.js → chunk-6T4NVCAT.js} +2 -2
  54. package/dist/{chunk-7TX5BKVA.js.map → chunk-6T4NVCAT.js.map} +1 -1
  55. package/dist/{chunk-OC64AHKN.mjs → chunk-7FZWMAI2.mjs} +3 -3
  56. package/dist/{chunk-OC64AHKN.mjs.map → chunk-7FZWMAI2.mjs.map} +1 -1
  57. package/dist/{chunk-EE6SFAZP.mjs → chunk-AX4AROLH.mjs} +5 -14
  58. package/dist/chunk-AX4AROLH.mjs.map +1 -0
  59. package/dist/chunk-BNJH2RFU.mjs +139 -0
  60. package/dist/chunk-BNJH2RFU.mjs.map +1 -0
  61. package/dist/{chunk-WZHWWOUC.js → chunk-BX6FFL2Y.js} +6 -16
  62. package/dist/chunk-BX6FFL2Y.js.map +1 -0
  63. package/dist/chunk-CGCYZJYX.mjs +41 -0
  64. package/dist/chunk-CGCYZJYX.mjs.map +1 -0
  65. package/dist/{chunk-PIV54R2O.js → chunk-CTPE3G5W.js} +5 -5
  66. package/dist/{chunk-PIV54R2O.js.map → chunk-CTPE3G5W.js.map} +1 -1
  67. package/dist/chunk-CXDIWBIQ.js +78 -0
  68. package/dist/chunk-CXDIWBIQ.js.map +1 -0
  69. package/dist/chunk-DWVF7SEK.mjs +35 -0
  70. package/dist/chunk-DWVF7SEK.mjs.map +1 -0
  71. package/dist/{chunk-C4JAMON3.js → chunk-EH7QQU6P.js} +15 -15
  72. package/dist/{chunk-C4JAMON3.js.map → chunk-EH7QQU6P.js.map} +1 -1
  73. package/dist/chunk-EU2UGO25.js +52 -0
  74. package/dist/chunk-EU2UGO25.js.map +1 -0
  75. package/dist/{chunk-X4OPM3SK.mjs → chunk-GU5OTUQS.mjs} +5 -14
  76. package/dist/chunk-GU5OTUQS.mjs.map +1 -0
  77. package/dist/{chunk-SH4VZDVX.mjs → chunk-GUXB3QH7.mjs} +38 -67
  78. package/dist/chunk-GUXB3QH7.mjs.map +1 -0
  79. package/dist/{chunk-JD6LV6JZ.mjs → chunk-HRJ65XKY.mjs} +3 -3
  80. package/dist/{chunk-JD6LV6JZ.mjs.map → chunk-HRJ65XKY.mjs.map} +1 -1
  81. package/dist/chunk-IBMOX3YE.mjs +48 -0
  82. package/dist/chunk-IBMOX3YE.mjs.map +1 -0
  83. package/dist/{chunk-TXEOLHMC.js → chunk-IMDSDDRU.js} +4 -4
  84. package/dist/{chunk-TXEOLHMC.js.map → chunk-IMDSDDRU.js.map} +1 -1
  85. package/dist/{chunk-25YPXQBA.mjs → chunk-INGAARGC.mjs} +8 -25
  86. package/dist/chunk-INGAARGC.mjs.map +1 -0
  87. package/dist/{chunk-3AG6O3IA.mjs → chunk-LZSHZVBE.mjs} +49 -5
  88. package/dist/chunk-LZSHZVBE.mjs.map +1 -0
  89. package/dist/chunk-MJDYY6S3.mjs +76 -0
  90. package/dist/chunk-MJDYY6S3.mjs.map +1 -0
  91. package/dist/{chunk-BMKZHXWQ.js → chunk-MMON6EVI.js} +3 -194
  92. package/dist/chunk-MMON6EVI.js.map +1 -0
  93. package/dist/chunk-NB4MK2Q5.js +18 -0
  94. package/dist/chunk-NB4MK2Q5.js.map +1 -0
  95. package/dist/{chunk-DIXWP4BO.mjs → chunk-NBI5AV6U.mjs} +3 -3
  96. package/dist/{chunk-DIXWP4BO.mjs.map → chunk-NBI5AV6U.mjs.map} +1 -1
  97. package/dist/chunk-NI7OY4FW.mjs +16 -0
  98. package/dist/chunk-NI7OY4FW.mjs.map +1 -0
  99. package/dist/chunk-NME3SQCB.js +8 -0
  100. package/dist/{chunk-3X2YPJU5.js.map → chunk-NME3SQCB.js.map} +1 -1
  101. package/dist/{chunk-4JMXBIUC.js → chunk-PE2A3ON5.js} +16 -35
  102. package/dist/chunk-PE2A3ON5.js.map +1 -0
  103. package/dist/{chunk-BOWR5QEV.js → chunk-PWIBFSXK.js} +14 -14
  104. package/dist/{chunk-BOWR5QEV.js.map → chunk-PWIBFSXK.js.map} +1 -1
  105. package/dist/{chunk-4ROFY6PM.js → chunk-Q2SPOBHU.js} +61 -17
  106. package/dist/chunk-Q2SPOBHU.js.map +1 -0
  107. package/dist/chunk-QGPYFC6G.mjs +6 -0
  108. package/dist/{chunk-K6YGF2KJ.mjs.map → chunk-QGPYFC6G.mjs.map} +1 -1
  109. package/dist/{chunk-FSYXHIAI.js → chunk-SQGDDITI.js} +14 -14
  110. package/dist/{chunk-FSYXHIAI.js.map → chunk-SQGDDITI.js.map} +1 -1
  111. package/dist/{chunk-S2N3NSC7.mjs → chunk-STTSIODQ.mjs} +5 -5
  112. package/dist/{chunk-S2N3NSC7.mjs.map → chunk-STTSIODQ.mjs.map} +1 -1
  113. package/dist/{chunk-QRIGY6EM.js → chunk-T3RPPS25.js} +7 -7
  114. package/dist/{chunk-QRIGY6EM.js.map → chunk-T3RPPS25.js.map} +1 -1
  115. package/dist/{chunk-DNW7FTJD.js → chunk-TBMFLLRV.js} +9 -9
  116. package/dist/{chunk-DNW7FTJD.js.map → chunk-TBMFLLRV.js.map} +1 -1
  117. package/dist/{chunk-YFYMOQAX.js → chunk-TJS6FPR7.js} +14 -31
  118. package/dist/chunk-TJS6FPR7.js.map +1 -0
  119. package/dist/chunk-TPL2IHFI.js +43 -0
  120. package/dist/chunk-TPL2IHFI.js.map +1 -0
  121. package/dist/chunk-TRTT4PND.js +38 -0
  122. package/dist/chunk-TRTT4PND.js.map +1 -0
  123. package/dist/{chunk-QFWBAGBT.mjs → chunk-UFOOVODL.mjs} +3 -3
  124. package/dist/{chunk-QFWBAGBT.mjs.map → chunk-UFOOVODL.mjs.map} +1 -1
  125. package/dist/chunk-UXEB6UAR.js +147 -0
  126. package/dist/chunk-UXEB6UAR.js.map +1 -0
  127. package/dist/{chunk-MLD3EGM2.mjs → chunk-V37Z65NF.mjs} +3 -3
  128. package/dist/{chunk-MLD3EGM2.mjs.map → chunk-V37Z65NF.mjs.map} +1 -1
  129. package/dist/chunk-VJMPIRSD.js +31 -0
  130. package/dist/chunk-VJMPIRSD.js.map +1 -0
  131. package/dist/chunk-VX3WK77I.mjs +126 -0
  132. package/dist/chunk-VX3WK77I.mjs.map +1 -0
  133. package/dist/{chunk-AB2VYIYU.mjs → chunk-WTR7QJ32.mjs} +4 -194
  134. package/dist/chunk-WTR7QJ32.mjs.map +1 -0
  135. package/dist/{chunk-IB4FRJDV.js → chunk-XAWB2HFQ.js} +37 -67
  136. package/dist/chunk-XAWB2HFQ.js.map +1 -0
  137. package/dist/{chunk-3BNFUMLL.js → chunk-XB57AM6T.js} +5 -14
  138. package/dist/chunk-XB57AM6T.js.map +1 -0
  139. package/dist/chunk-XY4NJJEX.js +129 -0
  140. package/dist/chunk-XY4NJJEX.js.map +1 -0
  141. package/dist/{chunk-FMQHK6MM.js → chunk-Y4U3OCKH.js} +3 -3
  142. package/dist/{chunk-FMQHK6MM.js.map → chunk-Y4U3OCKH.js.map} +1 -1
  143. package/dist/{chunk-ZYIONE7A.mjs → chunk-YKPAFEJ4.mjs} +4 -4
  144. package/dist/{chunk-ZYIONE7A.mjs.map → chunk-YKPAFEJ4.mjs.map} +1 -1
  145. package/dist/{chunk-7OROUYZH.mjs → chunk-YSDJ7HI3.mjs} +4 -4
  146. package/dist/{chunk-7OROUYZH.mjs.map → chunk-YSDJ7HI3.mjs.map} +1 -1
  147. package/dist/{chunk-PCDAVHVX.js → chunk-ZY3G7JGT.js} +8 -8
  148. package/dist/{chunk-PCDAVHVX.js.map → chunk-ZY3G7JGT.js.map} +1 -1
  149. package/dist/cli/index.js +2 -2
  150. package/dist/cli/index.mjs +1 -1
  151. package/dist/client/index.d.mts +15 -1
  152. package/dist/client/index.d.ts +15 -1
  153. package/dist/client/index.js +21 -6
  154. package/dist/client/index.js.map +1 -1
  155. package/dist/client/index.mjs +19 -1
  156. package/dist/client/index.mjs.map +1 -1
  157. package/dist/commerce/index.js +53 -51
  158. package/dist/commerce/index.mjs +8 -6
  159. package/dist/engage/index.js +11 -9
  160. package/dist/engage/index.js.map +1 -1
  161. package/dist/engage/index.mjs +8 -6
  162. package/dist/engage/index.mjs.map +1 -1
  163. package/dist/fleet/index.js +8 -7
  164. package/dist/fleet/index.mjs +4 -3
  165. package/dist/forms/index.js +14 -12
  166. package/dist/forms/index.js.map +1 -1
  167. package/dist/forms/index.mjs +6 -4
  168. package/dist/forms/index.mjs.map +1 -1
  169. package/dist/images/index.js +11 -10
  170. package/dist/images/index.mjs +4 -3
  171. package/dist/index.d.mts +2 -1
  172. package/dist/index.d.ts +2 -1
  173. package/dist/index.js +75 -64
  174. package/dist/index.js.map +1 -1
  175. package/dist/index.mjs +13 -10
  176. package/dist/index.mjs.map +1 -1
  177. package/dist/landing/index.d.mts +21 -0
  178. package/dist/landing/index.d.ts +21 -0
  179. package/dist/landing/index.js +21 -0
  180. package/dist/landing/index.js.map +1 -0
  181. package/dist/landing/index.mjs +4 -0
  182. package/dist/landing/index.mjs.map +1 -0
  183. package/dist/layout/client.js +11 -8
  184. package/dist/layout/client.mjs +10 -7
  185. package/dist/layout/index.js +13 -54
  186. package/dist/layout/index.js.map +1 -1
  187. package/dist/layout/index.mjs +11 -52
  188. package/dist/layout/index.mjs.map +1 -1
  189. package/dist/llms/index.js +12 -12
  190. package/dist/llms/index.mjs +2 -2
  191. package/dist/maps/index.js +5 -4
  192. package/dist/maps/index.js.map +1 -1
  193. package/dist/maps/index.mjs +3 -2
  194. package/dist/maps/index.mjs.map +1 -1
  195. package/dist/metadata-D_GiY8LJ.d.mts +36 -0
  196. package/dist/metadata-D_GiY8LJ.d.ts +36 -0
  197. package/dist/middleware/index.js +2 -8
  198. package/dist/middleware/index.js.map +1 -1
  199. package/dist/middleware/index.mjs +2 -8
  200. package/dist/middleware/index.mjs.map +1 -1
  201. package/dist/seo/client.js +5 -4
  202. package/dist/seo/client.mjs +4 -3
  203. package/dist/seo/index.js +5 -4
  204. package/dist/seo/index.js.map +1 -1
  205. package/dist/seo/index.mjs +4 -3
  206. package/dist/seo/index.mjs.map +1 -1
  207. package/dist/seo-pages/contract.js +6 -5
  208. package/dist/seo-pages/contract.js.map +1 -1
  209. package/dist/seo-pages/contract.mjs +2 -1
  210. package/dist/seo-pages/contract.mjs.map +1 -1
  211. package/dist/server/index.d.mts +34 -1
  212. package/dist/server/index.d.ts +34 -1
  213. package/dist/server/index.js +6 -0
  214. package/dist/server/index.mjs +2 -0
  215. package/dist/signal/index.js +11 -11
  216. package/dist/signal/index.mjs +2 -2
  217. package/dist/sitemap/index.js +2 -2
  218. package/dist/sitemap/index.mjs +1 -1
  219. package/dist/sites/contract.d.mts +36 -12
  220. package/dist/sites/contract.d.ts +36 -12
  221. package/dist/sites/contract.js +12 -11
  222. package/dist/sites/contract.mjs +2 -1
  223. package/dist/sync/index.js +16 -15
  224. package/dist/sync/index.mjs +4 -3
  225. package/dist/{types-DYOumpUT.d.mts → types-8IcjVMDa.d.mts} +1 -1
  226. package/dist/{types-DYOumpUT.d.ts → types-8IcjVMDa.d.ts} +1 -1
  227. package/package.json +11 -1
  228. package/dist/AnalyticsProvider-3MZ3O5OB.mjs +0 -8
  229. package/dist/AnalyticsProvider-PLGTU56K.js +0 -29
  230. package/dist/ChatWidget-7JHVRNVE.mjs +0 -8
  231. package/dist/ChatWidget-FQARJMGU.js +0 -17
  232. package/dist/EngageWidget-DQ62NQPU.js +0 -16
  233. package/dist/EngageWidget-VXQOZOYA.mjs +0 -7
  234. package/dist/SignalCore-3SG3LFQL.js.map +0 -1
  235. package/dist/SignalCore-BKG66B4C.mjs.map +0 -1
  236. package/dist/SitemapSync-DWX7I6MX.js +0 -16
  237. package/dist/SitemapSync-IO2VOR23.mjs +0 -7
  238. package/dist/chunk-25YPXQBA.mjs.map +0 -1
  239. package/dist/chunk-3AG6O3IA.mjs.map +0 -1
  240. package/dist/chunk-3BNFUMLL.js.map +0 -1
  241. package/dist/chunk-3X2YPJU5.js +0 -8
  242. package/dist/chunk-4JMXBIUC.js.map +0 -1
  243. package/dist/chunk-4ROFY6PM.js.map +0 -1
  244. package/dist/chunk-AB2VYIYU.mjs.map +0 -1
  245. package/dist/chunk-BMKZHXWQ.js.map +0 -1
  246. package/dist/chunk-EE6SFAZP.mjs.map +0 -1
  247. package/dist/chunk-GUU3AEFM.mjs +0 -259
  248. package/dist/chunk-GUU3AEFM.mjs.map +0 -1
  249. package/dist/chunk-IB4FRJDV.js.map +0 -1
  250. package/dist/chunk-K6YGF2KJ.mjs +0 -6
  251. package/dist/chunk-KPKZBIAQ.js +0 -264
  252. package/dist/chunk-KPKZBIAQ.js.map +0 -1
  253. package/dist/chunk-NQ3K4NWX.mjs.map +0 -1
  254. package/dist/chunk-SH4VZDVX.mjs.map +0 -1
  255. package/dist/chunk-WZHWWOUC.js.map +0 -1
  256. package/dist/chunk-X4OPM3SK.mjs.map +0 -1
  257. package/dist/chunk-YFYMOQAX.js.map +0 -1
@@ -1,19 +1,25 @@
1
1
  /**
2
- * @sonordev/site-kit/sites/contractMulti-site "site" dimension host contract (v1)
2
+ * @sonordev/site-kit/sites — normalizeSiteHost (leaf module)
3
3
  *
4
- * Single source of truth for normalizing and comparing sub-site host values
5
- * (the multi-site `site` dimension, see CLAUDE.md). Same pattern as
6
- * `@sonordev/site-kit/llms/contract` and `@sonordev/site-kit/slots/contract`:
7
- * site-kit owns the canonical logic; the Nest APIs keep byte-identical inline
8
- * mirrors (sonor-api `src/common/utils/site-host.ts`, signal-api
9
- * `src/shared/utils/seo-page-pick.util.ts`) guarded by the shared drift-test
10
- * vectors in `contract.test.ts` — so a divergent copy fails CI on either side.
4
+ * Deliberately its own file, not part of `./contract`, so browser code can pull
5
+ * in the normalizer WITHOUT the rest of the contract surface.
11
6
  *
12
- * Pure string logic only (no Node built-ins) so it is safe in the browser:
13
- * site-kit itself normalizes `__SITE_KIT_SITE__` with `normalizeSiteHost`.
7
+ * `publishCredential` (which every client entry that publishes a credential
8
+ * imports) needs exactly this one function. When it lived in `./contract`, the
9
+ * bundler emitted that whole module as one shared chunk — `SITE_HOST_JSON_SCHEMA`,
10
+ * `SITE_HOST_CONTRACT_VERSION`, `stripWww`, `sameSite`, `hostFromUrl`,
11
+ * `isNormalizedSiteHost` and all — into `client`, `layout/client` and every
12
+ * other entry that touched it. That was ~750B gzipped of agent-facing contract
13
+ * metadata shipped to browsers for a 14-line string normalizer, and it is what
14
+ * pushed those entries over their bundle budgets.
15
+ *
16
+ * `./contract` re-exports this, so the public `@sonordev/site-kit/sites/contract`
17
+ * surface and the cross-repo drift tests are unchanged. Keep the implementation
18
+ * HERE — the Nest APIs mirror this exact logic (sonor-api
19
+ * `src/common/utils/site-host.ts`, signal-api `src/shared/utils/seo-page-pick.util.ts`).
20
+ *
21
+ * Pure string logic only (no Node built-ins) so it is safe in the browser.
14
22
  */
15
- /** Bump on breaking changes to the normalized host shape. */
16
- declare const SITE_HOST_CONTRACT_VERSION: 1;
17
23
  /**
18
24
  * normalizeSiteHost — canonical normalizer for a sub-site host value before it
19
25
  * is persisted or used as a filter.
@@ -26,6 +32,24 @@ declare const SITE_HOST_CONTRACT_VERSION: 1;
26
32
  * for www-insensitive equality.
27
33
  */
28
34
  declare function normalizeSiteHost(site?: string | null): string | null;
35
+
36
+ /**
37
+ * @sonordev/site-kit/sites/contract — Multi-site "site" dimension host contract (v1)
38
+ *
39
+ * Single source of truth for normalizing and comparing sub-site host values
40
+ * (the multi-site `site` dimension, see CLAUDE.md). Same pattern as
41
+ * `@sonordev/site-kit/llms/contract` and `@sonordev/site-kit/slots/contract`:
42
+ * site-kit owns the canonical logic; the Nest APIs keep byte-identical inline
43
+ * mirrors (sonor-api `src/common/utils/site-host.ts`, signal-api
44
+ * `src/shared/utils/seo-page-pick.util.ts`) guarded by the shared drift-test
45
+ * vectors in `contract.test.ts` — so a divergent copy fails CI on either side.
46
+ *
47
+ * Pure string logic only (no Node built-ins) so it is safe in the browser:
48
+ * site-kit itself normalizes `__SITE_KIT_SITE__` with `normalizeSiteHost`.
49
+ */
50
+ /** Bump on breaking changes to the normalized host shape. */
51
+ declare const SITE_HOST_CONTRACT_VERSION: 1;
52
+
29
53
  /** Strip a leading `www.` from a host ("www.tps.com" → "tps.com"). */
30
54
  declare function stripWww(host: string): string;
31
55
  /**
@@ -1,19 +1,25 @@
1
1
  /**
2
- * @sonordev/site-kit/sites/contractMulti-site "site" dimension host contract (v1)
2
+ * @sonordev/site-kit/sites — normalizeSiteHost (leaf module)
3
3
  *
4
- * Single source of truth for normalizing and comparing sub-site host values
5
- * (the multi-site `site` dimension, see CLAUDE.md). Same pattern as
6
- * `@sonordev/site-kit/llms/contract` and `@sonordev/site-kit/slots/contract`:
7
- * site-kit owns the canonical logic; the Nest APIs keep byte-identical inline
8
- * mirrors (sonor-api `src/common/utils/site-host.ts`, signal-api
9
- * `src/shared/utils/seo-page-pick.util.ts`) guarded by the shared drift-test
10
- * vectors in `contract.test.ts` — so a divergent copy fails CI on either side.
4
+ * Deliberately its own file, not part of `./contract`, so browser code can pull
5
+ * in the normalizer WITHOUT the rest of the contract surface.
11
6
  *
12
- * Pure string logic only (no Node built-ins) so it is safe in the browser:
13
- * site-kit itself normalizes `__SITE_KIT_SITE__` with `normalizeSiteHost`.
7
+ * `publishCredential` (which every client entry that publishes a credential
8
+ * imports) needs exactly this one function. When it lived in `./contract`, the
9
+ * bundler emitted that whole module as one shared chunk — `SITE_HOST_JSON_SCHEMA`,
10
+ * `SITE_HOST_CONTRACT_VERSION`, `stripWww`, `sameSite`, `hostFromUrl`,
11
+ * `isNormalizedSiteHost` and all — into `client`, `layout/client` and every
12
+ * other entry that touched it. That was ~750B gzipped of agent-facing contract
13
+ * metadata shipped to browsers for a 14-line string normalizer, and it is what
14
+ * pushed those entries over their bundle budgets.
15
+ *
16
+ * `./contract` re-exports this, so the public `@sonordev/site-kit/sites/contract`
17
+ * surface and the cross-repo drift tests are unchanged. Keep the implementation
18
+ * HERE — the Nest APIs mirror this exact logic (sonor-api
19
+ * `src/common/utils/site-host.ts`, signal-api `src/shared/utils/seo-page-pick.util.ts`).
20
+ *
21
+ * Pure string logic only (no Node built-ins) so it is safe in the browser.
14
22
  */
15
- /** Bump on breaking changes to the normalized host shape. */
16
- declare const SITE_HOST_CONTRACT_VERSION: 1;
17
23
  /**
18
24
  * normalizeSiteHost — canonical normalizer for a sub-site host value before it
19
25
  * is persisted or used as a filter.
@@ -26,6 +32,24 @@ declare const SITE_HOST_CONTRACT_VERSION: 1;
26
32
  * for www-insensitive equality.
27
33
  */
28
34
  declare function normalizeSiteHost(site?: string | null): string | null;
35
+
36
+ /**
37
+ * @sonordev/site-kit/sites/contract — Multi-site "site" dimension host contract (v1)
38
+ *
39
+ * Single source of truth for normalizing and comparing sub-site host values
40
+ * (the multi-site `site` dimension, see CLAUDE.md). Same pattern as
41
+ * `@sonordev/site-kit/llms/contract` and `@sonordev/site-kit/slots/contract`:
42
+ * site-kit owns the canonical logic; the Nest APIs keep byte-identical inline
43
+ * mirrors (sonor-api `src/common/utils/site-host.ts`, signal-api
44
+ * `src/shared/utils/seo-page-pick.util.ts`) guarded by the shared drift-test
45
+ * vectors in `contract.test.ts` — so a divergent copy fails CI on either side.
46
+ *
47
+ * Pure string logic only (no Node built-ins) so it is safe in the browser:
48
+ * site-kit itself normalizes `__SITE_KIT_SITE__` with `normalizeSiteHost`.
49
+ */
50
+ /** Bump on breaking changes to the normalized host shape. */
51
+ declare const SITE_HOST_CONTRACT_VERSION: 1;
52
+
29
53
  /** Strip a leading `www.` from a host ("www.tps.com" → "tps.com"). */
30
54
  declare function stripWww(host: string): string;
31
55
  /**
@@ -1,37 +1,38 @@
1
1
  'use strict';
2
2
 
3
- var chunkWZHWWOUC_js = require('../chunk-WZHWWOUC.js');
3
+ var chunkBX6FFL2Y_js = require('../chunk-BX6FFL2Y.js');
4
+ var chunkNB4MK2Q5_js = require('../chunk-NB4MK2Q5.js');
4
5
  require('../chunk-ZSMWDLMK.js');
5
6
 
6
7
 
7
8
 
8
9
  Object.defineProperty(exports, "SITE_HOST_CONTRACT_VERSION", {
9
10
  enumerable: true,
10
- get: function () { return chunkWZHWWOUC_js.SITE_HOST_CONTRACT_VERSION; }
11
+ get: function () { return chunkBX6FFL2Y_js.SITE_HOST_CONTRACT_VERSION; }
11
12
  });
12
13
  Object.defineProperty(exports, "SITE_HOST_JSON_SCHEMA", {
13
14
  enumerable: true,
14
- get: function () { return chunkWZHWWOUC_js.SITE_HOST_JSON_SCHEMA; }
15
+ get: function () { return chunkBX6FFL2Y_js.SITE_HOST_JSON_SCHEMA; }
15
16
  });
16
17
  Object.defineProperty(exports, "hostFromUrl", {
17
18
  enumerable: true,
18
- get: function () { return chunkWZHWWOUC_js.hostFromUrl; }
19
+ get: function () { return chunkBX6FFL2Y_js.hostFromUrl; }
19
20
  });
20
21
  Object.defineProperty(exports, "isNormalizedSiteHost", {
21
22
  enumerable: true,
22
- get: function () { return chunkWZHWWOUC_js.isNormalizedSiteHost; }
23
- });
24
- Object.defineProperty(exports, "normalizeSiteHost", {
25
- enumerable: true,
26
- get: function () { return chunkWZHWWOUC_js.normalizeSiteHost; }
23
+ get: function () { return chunkBX6FFL2Y_js.isNormalizedSiteHost; }
27
24
  });
28
25
  Object.defineProperty(exports, "sameSite", {
29
26
  enumerable: true,
30
- get: function () { return chunkWZHWWOUC_js.sameSite; }
27
+ get: function () { return chunkBX6FFL2Y_js.sameSite; }
31
28
  });
32
29
  Object.defineProperty(exports, "stripWww", {
33
30
  enumerable: true,
34
- get: function () { return chunkWZHWWOUC_js.stripWww; }
31
+ get: function () { return chunkBX6FFL2Y_js.stripWww; }
32
+ });
33
+ Object.defineProperty(exports, "normalizeSiteHost", {
34
+ enumerable: true,
35
+ get: function () { return chunkNB4MK2Q5_js.normalizeSiteHost; }
35
36
  });
36
37
  //# sourceMappingURL=contract.js.map
37
38
  //# sourceMappingURL=contract.js.map
@@ -1,4 +1,5 @@
1
- export { SITE_HOST_CONTRACT_VERSION, SITE_HOST_JSON_SCHEMA, hostFromUrl, isNormalizedSiteHost, normalizeSiteHost, sameSite, stripWww } from '../chunk-X4OPM3SK.mjs';
1
+ export { SITE_HOST_CONTRACT_VERSION, SITE_HOST_JSON_SCHEMA, hostFromUrl, isNormalizedSiteHost, sameSite, stripWww } from '../chunk-GU5OTUQS.mjs';
2
+ export { normalizeSiteHost } from '../chunk-NI7OY4FW.mjs';
2
3
  import '../chunk-4XPGGLVP.mjs';
3
4
  //# sourceMappingURL=contract.mjs.map
4
5
  //# sourceMappingURL=contract.mjs.map
@@ -1,59 +1,60 @@
1
1
  'use strict';
2
2
 
3
- var chunkDNW7FTJD_js = require('../chunk-DNW7FTJD.js');
4
- require('../chunk-KPKZBIAQ.js');
5
- require('../chunk-3X2YPJU5.js');
3
+ var chunkTBMFLLRV_js = require('../chunk-TBMFLLRV.js');
4
+ require('../chunk-XY4NJJEX.js');
5
+ require('../chunk-UXEB6UAR.js');
6
+ require('../chunk-NME3SQCB.js');
6
7
  require('../chunk-ZSMWDLMK.js');
7
8
 
8
9
 
9
10
 
10
11
  Object.defineProperty(exports, "BookingWidget", {
11
12
  enumerable: true,
12
- get: function () { return chunkDNW7FTJD_js.BookingWidget; }
13
+ get: function () { return chunkTBMFLLRV_js.BookingWidget; }
13
14
  });
14
15
  Object.defineProperty(exports, "createBooking", {
15
16
  enumerable: true,
16
- get: function () { return chunkDNW7FTJD_js.createBooking; }
17
+ get: function () { return chunkTBMFLLRV_js.createBooking; }
17
18
  });
18
19
  Object.defineProperty(exports, "createSlotHold", {
19
20
  enumerable: true,
20
- get: function () { return chunkDNW7FTJD_js.createSlotHold; }
21
+ get: function () { return chunkTBMFLLRV_js.createSlotHold; }
21
22
  });
22
23
  Object.defineProperty(exports, "detectTimezone", {
23
24
  enumerable: true,
24
- get: function () { return chunkDNW7FTJD_js.detectTimezone; }
25
+ get: function () { return chunkTBMFLLRV_js.detectTimezone; }
25
26
  });
26
27
  Object.defineProperty(exports, "fetchAvailability", {
27
28
  enumerable: true,
28
- get: function () { return chunkDNW7FTJD_js.fetchAvailability; }
29
+ get: function () { return chunkTBMFLLRV_js.fetchAvailability; }
29
30
  });
30
31
  Object.defineProperty(exports, "fetchAvailableDates", {
31
32
  enumerable: true,
32
- get: function () { return chunkDNW7FTJD_js.fetchAvailableDates; }
33
+ get: function () { return chunkTBMFLLRV_js.fetchAvailableDates; }
33
34
  });
34
35
  Object.defineProperty(exports, "fetchBookingTypeDetails", {
35
36
  enumerable: true,
36
- get: function () { return chunkDNW7FTJD_js.fetchBookingTypeDetails; }
37
+ get: function () { return chunkTBMFLLRV_js.fetchBookingTypeDetails; }
37
38
  });
38
39
  Object.defineProperty(exports, "fetchBookingTypes", {
39
40
  enumerable: true,
40
- get: function () { return chunkDNW7FTJD_js.fetchBookingTypes; }
41
+ get: function () { return chunkTBMFLLRV_js.fetchBookingTypes; }
41
42
  });
42
43
  Object.defineProperty(exports, "formatDate", {
43
44
  enumerable: true,
44
- get: function () { return chunkDNW7FTJD_js.formatDate; }
45
+ get: function () { return chunkTBMFLLRV_js.formatDate; }
45
46
  });
46
47
  Object.defineProperty(exports, "formatDuration", {
47
48
  enumerable: true,
48
- get: function () { return chunkDNW7FTJD_js.formatDuration; }
49
+ get: function () { return chunkTBMFLLRV_js.formatDuration; }
49
50
  });
50
51
  Object.defineProperty(exports, "formatTime", {
51
52
  enumerable: true,
52
- get: function () { return chunkDNW7FTJD_js.formatTime; }
53
+ get: function () { return chunkTBMFLLRV_js.formatTime; }
53
54
  });
54
55
  Object.defineProperty(exports, "releaseSlotHold", {
55
56
  enumerable: true,
56
- get: function () { return chunkDNW7FTJD_js.releaseSlotHold; }
57
+ get: function () { return chunkTBMFLLRV_js.releaseSlotHold; }
57
58
  });
58
59
  //# sourceMappingURL=index.js.map
59
60
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,7 @@
1
- export { BookingWidget, createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, releaseSlotHold } from '../chunk-OC64AHKN.mjs';
2
- import '../chunk-GUU3AEFM.mjs';
3
- import '../chunk-K6YGF2KJ.mjs';
1
+ export { BookingWidget, createBooking, createSlotHold, detectTimezone, fetchAvailability, fetchAvailableDates, fetchBookingTypeDetails, fetchBookingTypes, formatDate, formatDuration, formatTime, releaseSlotHold } from '../chunk-7FZWMAI2.mjs';
2
+ import '../chunk-VX3WK77I.mjs';
3
+ import '../chunk-BNJH2RFU.mjs';
4
+ import '../chunk-QGPYFC6G.mjs';
4
5
  import '../chunk-4XPGGLVP.mjs';
5
6
  //# sourceMappingURL=index.mjs.map
6
7
  //# sourceMappingURL=index.mjs.map
@@ -259,4 +259,4 @@ interface BlogAnalytics {
259
259
  created_at: string;
260
260
  }
261
261
 
262
- export type { AuthorCardProps as A, BlogPost as B, ClusterNavigation as C, RelatedPostsProps as R, TopicCluster as T, BlogAuthor as a, BlogCategory as b, AuthorPageProps as c, TableOfContentsProps as d, BlogTag as e, BlogListOptions as f, BlogListResult as g, BlogPostProps as h, BlogPostRenderProps as i, BlogListProps as j, BlogListRenderProps as k, TocItem as l, BlogAnalytics as m };
262
+ export type { AuthorCardProps as A, BlogAuthor as B, ClusterNavigation as C, RelatedPostsProps as R, TopicCluster as T, BlogPost as a, BlogCategory as b, AuthorPageProps as c, TableOfContentsProps as d, BlogTag as e, BlogListOptions as f, BlogListResult as g, BlogPostProps as h, BlogPostRenderProps as i, BlogListProps as j, BlogListRenderProps as k, TocItem as l, BlogAnalytics as m };
@@ -259,4 +259,4 @@ interface BlogAnalytics {
259
259
  created_at: string;
260
260
  }
261
261
 
262
- export type { AuthorCardProps as A, BlogPost as B, ClusterNavigation as C, RelatedPostsProps as R, TopicCluster as T, BlogAuthor as a, BlogCategory as b, AuthorPageProps as c, TableOfContentsProps as d, BlogTag as e, BlogListOptions as f, BlogListResult as g, BlogPostProps as h, BlogPostRenderProps as i, BlogListProps as j, BlogListRenderProps as k, TocItem as l, BlogAnalytics as m };
262
+ export type { AuthorCardProps as A, BlogAuthor as B, ClusterNavigation as C, RelatedPostsProps as R, TopicCluster as T, BlogPost as a, BlogCategory as b, AuthorPageProps as c, TableOfContentsProps as d, BlogTag as e, BlogListOptions as f, BlogListResult as g, BlogPostProps as h, BlogPostRenderProps as i, BlogListProps as j, BlogListRenderProps as k, TocItem as l, BlogAnalytics as m };
package/package.json CHANGED
@@ -1,8 +1,12 @@
1
1
  {
2
2
  "name": "@sonordev/site-kit",
3
- "version": "3.3.1",
3
+ "version": "3.5.0",
4
4
  "description": "Complete client-side integration kit for Sonor - SEO, Analytics, Engage, Forms, Blog",
5
5
  "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/upforge-dev/site-kit.git"
9
+ },
6
10
  "sideEffects": [
7
11
  "**/*.css"
8
12
  ],
@@ -185,6 +189,11 @@
185
189
  "import": "./dist/site-config/index.mjs",
186
190
  "require": "./dist/site-config/index.js"
187
191
  },
192
+ "./landing": {
193
+ "types": "./dist/landing/index.d.ts",
194
+ "import": "./dist/landing/index.mjs",
195
+ "require": "./dist/landing/index.js"
196
+ },
188
197
  "./layout": {
189
198
  "types": "./dist/layout/index.d.ts",
190
199
  "import": "./dist/layout/index.mjs",
@@ -248,6 +257,7 @@
248
257
  "test:integration:setup": "playwright install chromium",
249
258
  "clean": "rm -rf dist",
250
259
  "typecheck": "tsc --noEmit",
260
+ "version": "node scripts/sync-version.cjs && git add src/shared/version.ts",
251
261
  "prepublishOnly": "rm -rf dist && NODE_OPTIONS=--max-old-space-size=8192 tsup && node scripts/gen-agent-manifest.cjs && node scripts/verify-dts.cjs && node scripts/prepublish-integration.cjs"
252
262
  },
253
263
  "peerDependencies": {
@@ -1,8 +0,0 @@
1
- export { AnalyticsProvider, useAnalytics, useAnalyticsOptional, useTrackEvent } from './chunk-3AG6O3IA.mjs';
2
- import './chunk-3DPXOZAU.mjs';
3
- import './chunk-EE6SFAZP.mjs';
4
- import './chunk-GUU3AEFM.mjs';
5
- import './chunk-K6YGF2KJ.mjs';
6
- import './chunk-4XPGGLVP.mjs';
7
- //# sourceMappingURL=AnalyticsProvider-3MZ3O5OB.mjs.map
8
- //# sourceMappingURL=AnalyticsProvider-3MZ3O5OB.mjs.map
@@ -1,29 +0,0 @@
1
- 'use strict';
2
-
3
- var chunk4ROFY6PM_js = require('./chunk-4ROFY6PM.js');
4
- require('./chunk-HMFFAUCD.js');
5
- require('./chunk-3BNFUMLL.js');
6
- require('./chunk-KPKZBIAQ.js');
7
- require('./chunk-3X2YPJU5.js');
8
- require('./chunk-ZSMWDLMK.js');
9
-
10
-
11
-
12
- Object.defineProperty(exports, "AnalyticsProvider", {
13
- enumerable: true,
14
- get: function () { return chunk4ROFY6PM_js.AnalyticsProvider; }
15
- });
16
- Object.defineProperty(exports, "useAnalytics", {
17
- enumerable: true,
18
- get: function () { return chunk4ROFY6PM_js.useAnalytics; }
19
- });
20
- Object.defineProperty(exports, "useAnalyticsOptional", {
21
- enumerable: true,
22
- get: function () { return chunk4ROFY6PM_js.useAnalyticsOptional; }
23
- });
24
- Object.defineProperty(exports, "useTrackEvent", {
25
- enumerable: true,
26
- get: function () { return chunk4ROFY6PM_js.useTrackEvent; }
27
- });
28
- //# sourceMappingURL=AnalyticsProvider-PLGTU56K.js.map
29
- //# sourceMappingURL=AnalyticsProvider-PLGTU56K.js.map
@@ -1,8 +0,0 @@
1
- export { ChatWidget } from './chunk-ZYIONE7A.mjs';
2
- import './chunk-25YPXQBA.mjs';
3
- import './chunk-X3S6KXAP.mjs';
4
- import './chunk-GUU3AEFM.mjs';
5
- import './chunk-K6YGF2KJ.mjs';
6
- import './chunk-4XPGGLVP.mjs';
7
- //# sourceMappingURL=ChatWidget-7JHVRNVE.mjs.map
8
- //# sourceMappingURL=ChatWidget-7JHVRNVE.mjs.map
@@ -1,17 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkC4JAMON3_js = require('./chunk-C4JAMON3.js');
4
- require('./chunk-YFYMOQAX.js');
5
- require('./chunk-V6NVBFEP.js');
6
- require('./chunk-KPKZBIAQ.js');
7
- require('./chunk-3X2YPJU5.js');
8
- require('./chunk-ZSMWDLMK.js');
9
-
10
-
11
-
12
- Object.defineProperty(exports, "ChatWidget", {
13
- enumerable: true,
14
- get: function () { return chunkC4JAMON3_js.ChatWidget; }
15
- });
16
- //# sourceMappingURL=ChatWidget-FQARJMGU.js.map
17
- //# sourceMappingURL=ChatWidget-FQARJMGU.js.map
@@ -1,16 +0,0 @@
1
- 'use strict';
2
-
3
- var chunk3WRE7ZDC_js = require('./chunk-3WRE7ZDC.js');
4
- require('./chunk-3BNFUMLL.js');
5
- require('./chunk-KPKZBIAQ.js');
6
- require('./chunk-3X2YPJU5.js');
7
- require('./chunk-ZSMWDLMK.js');
8
-
9
-
10
-
11
- Object.defineProperty(exports, "EngageWidget", {
12
- enumerable: true,
13
- get: function () { return chunk3WRE7ZDC_js.EngageWidget; }
14
- });
15
- //# sourceMappingURL=EngageWidget-DQ62NQPU.js.map
16
- //# sourceMappingURL=EngageWidget-DQ62NQPU.js.map
@@ -1,7 +0,0 @@
1
- export { EngageWidget } from './chunk-S2N3NSC7.mjs';
2
- import './chunk-EE6SFAZP.mjs';
3
- import './chunk-GUU3AEFM.mjs';
4
- import './chunk-K6YGF2KJ.mjs';
5
- import './chunk-4XPGGLVP.mjs';
6
- //# sourceMappingURL=EngageWidget-VXQOZOYA.mjs.map
7
- //# sourceMappingURL=EngageWidget-VXQOZOYA.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/signal/SignalCore.tsx"],"names":["useState","useRef","getOrCreateVisitorId","getOrCreateSessionId","useEffect","useCallback","sonorFetch"],"mappings":"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","file":"SignalCore-3SG3LFQL.js","sourcesContent":["/**\n * @sonordev/site-kit/signal - SignalCore\n *\n * The heavy half of SignalBridge: config fetching, SSE streaming, experiment\n * assignment, event queue/flush, and behavioral tracking. Mounted by the\n * SignalBridge shell as a CHILDLESS lazy sibling — it never wraps page\n * content, so the signal machinery stays out of the server-render path and\n * off the critical hydration chunk. It reports state up to the shell via\n * `onState` and registers its imperative API via `onRegister`.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\n// Single source of truth for visitor/session IDs (storage keys _sk_vid/_sk_sid)\n// — shared with Analytics and Engage. Do NOT re-fork ID logic into this module.\nimport { getOrCreateVisitorId, getOrCreateSessionId } from '../shared/identity'\n// Canonical client transport — the same wrapper Analytics/Forms/Engage route\n// through (see shared/sonorFetch header). It gives every request a per-attempt\n// AbortSignal timeout, so a hung API aborts cleanly instead of being left to log\n// net::ERR_TIMED_OUT — the console error that fails Lighthouse best-practices.\n// It also sets x-api-key from the `apiKey` option, so callers drop the header.\nimport { sonorFetch } from '../shared/sonorFetch'\nimport type {\n SignalConfig,\n SignalEvent,\n SignalOutcome,\n ExperimentAssignment,\n} from './types'\n\n// ============================================\n// Shell ↔ core contract\n// ============================================\n\nexport interface SignalCoreApi {\n trackEvent: (event: Partial<SignalEvent>) => void\n trackOutcome: (outcome: SignalOutcome) => void\n getExperiment: (experimentId: string) => ExperimentAssignment | null\n refreshConfig: () => Promise<void>\n}\n\nexport interface SignalCoreState {\n config: SignalConfig | null\n loading: boolean\n error: Error | null\n}\n\nexport interface SignalCoreProps {\n enabled: boolean\n realtime: boolean\n experiments: boolean\n behaviorTracking: boolean\n externalVisitorId?: string\n externalSessionId?: string\n pageMetadataRef?: React.RefObject<Record<string, unknown> | null>\n /** Called with the imperative API on mount, and with null on unmount. */\n onRegister: (api: SignalCoreApi | null) => void\n /** Called whenever config/loading/error change, so the shell can re-render consumers. */\n onState: (state: SignalCoreState) => void\n}\n\n// ============================================\n// Utility Functions\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n const apiKey = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_KEY__\n : undefined\n return { apiUrl, apiKey }\n}\n\n// A visitor's console must stay clean (Lighthouse \"errors logged to the console\"\n// best-practice) — Signal's diagnostics only surface when the site opts into\n// debug via SiteKitClientProviders' __SITE_KIT_DEBUG__ global, mirroring how\n// AnalyticsProvider gates every one of its logs behind its `debug` prop.\nfunction isDebug(): boolean {\n return typeof window !== 'undefined' && !!(window as any).__SITE_KIT_DEBUG__\n}\n\nfunction getDeviceType(): 'desktop' | 'mobile' | 'tablet' {\n if (typeof window === 'undefined') return 'desktop'\n const ua = navigator.userAgent\n if (/tablet|ipad|playbook|silk/i.test(ua)) return 'tablet'\n if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) return 'mobile'\n return 'desktop'\n}\n\nfunction getBrowser(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Firefox')) return 'Firefox'\n if (ua.includes('Edg')) return 'Edge'\n if (ua.includes('Chrome')) return 'Chrome'\n if (ua.includes('Safari')) return 'Safari'\n return 'Other'\n}\n\nfunction getOS(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Windows')) return 'Windows'\n if (ua.includes('Mac')) return 'macOS'\n if (ua.includes('iPhone') || ua.includes('iPad')) return 'iOS'\n if (ua.includes('Android')) return 'Android'\n if (ua.includes('Linux')) return 'Linux'\n return 'Other'\n}\n\n// ============================================\n// SignalCore Component (childless)\n// ============================================\n\nexport function SignalCore({\n enabled,\n realtime,\n experiments,\n behaviorTracking,\n externalVisitorId,\n externalSessionId,\n pageMetadataRef,\n onRegister,\n onState,\n}: SignalCoreProps) {\n const [config, setConfig] = useState<SignalConfig | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<Error | null>(null)\n\n // Refs for SSE and tracking\n const eventSourceRef = useRef<EventSource | null>(null)\n const eventQueueRef = useRef<Partial<SignalEvent>[]>([])\n const flushTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const assignmentsRef = useRef<Map<string, ExperimentAssignment>>(new Map())\n\n // Behavioral tracking state\n const pageLoadTimeRef = useRef<number>(Date.now())\n const scrollDepthRef = useRef<number>(0)\n const clickCountRef = useRef<number>(0)\n\n const { apiUrl, apiKey } = getApiConfig()\n\n // Use external IDs from shared identity, fall back to the shared generators\n const resolvedVisitorId = externalVisitorId || getOrCreateVisitorId()\n const resolvedSessionId = externalSessionId || getOrCreateSessionId()\n\n // Mirror state up to the shell so context consumers re-render\n useEffect(() => {\n onState({ config, loading, error })\n }, [config, loading, error, onState])\n\n // ============================================\n // Experiment Assignment\n // ============================================\n\n const loadExperimentAssignment = useCallback(async (experimentId: string): Promise<ExperimentAssignment | null> => {\n // Check localStorage first\n const storageKey = `_signal_exp_${experimentId}`\n const stored = localStorage.getItem(storageKey)\n\n if (stored) {\n try {\n const assignment = JSON.parse(stored) as ExperimentAssignment\n if (assignment.expires > Date.now()) {\n assignmentsRef.current.set(experimentId, assignment)\n return assignment\n }\n } catch {\n // Invalid stored data, continue to fetch\n }\n }\n\n // Fetch from API — idempotent read, so the transport's default retries apply.\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/signal/experiment/${experimentId}`,\n {\n headers: {\n 'x-visitor-id': resolvedVisitorId,\n },\n },\n { apiKey },\n )\n\n if (!response.ok) return null\n\n const assignment = await response.json() as ExperimentAssignment\n\n // Store assignment\n localStorage.setItem(storageKey, JSON.stringify(assignment))\n assignmentsRef.current.set(experimentId, assignment)\n\n return assignment\n } catch (err) {\n if (isDebug()) console.error('[Signal] Experiment assignment error:', err)\n return null\n }\n }, [apiUrl, apiKey])\n\n const getExperiment = useCallback((experimentId: string): ExperimentAssignment | null => {\n return assignmentsRef.current.get(experimentId) || null\n }, [])\n\n // ============================================\n // Config Fetching\n // ============================================\n\n const fetchConfig = useCallback(async () => {\n if (!apiKey || !enabled) {\n setLoading(false)\n return\n }\n\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/signal/config`,\n {\n headers: {\n 'x-visitor-id': resolvedVisitorId,\n },\n },\n { apiKey },\n )\n\n if (!response.ok) {\n throw new Error(`Failed to fetch Signal config: ${response.statusText}`)\n }\n\n const data = await response.json()\n setConfig(data.config)\n setError(null)\n\n // Load experiment assignments\n if (experiments && data.config?.experiments) {\n for (const exp of data.config.experiments) {\n if (exp.status === 'running') {\n await loadExperimentAssignment(exp.id)\n }\n }\n }\n } catch (err) {\n if (isDebug()) console.error('[Signal] Config fetch error:', err)\n setError(err as Error)\n } finally {\n setLoading(false)\n }\n }, [apiUrl, apiKey, enabled, experiments, resolvedVisitorId, loadExperimentAssignment])\n\n // ============================================\n // SSE Real-time Updates\n // ============================================\n\n const connectSSE = useCallback(() => {\n if (!apiKey || !enabled || !realtime) return\n\n // Close existing connection\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n }\n\n const url = `${apiUrl}/api/public/signal/stream?key=${apiKey}`\n const eventSource = new EventSource(url)\n\n eventSource.addEventListener('config_update', (e) => {\n try {\n const { config: newConfig, version } = JSON.parse(e.data)\n setConfig(prev => {\n if (prev?.version !== version) {\n if (isDebug()) console.log('[Signal] Config updated to version:', version)\n return newConfig\n }\n return prev\n })\n } catch (err) {\n if (isDebug()) console.error('[Signal] SSE parse error:', err)\n }\n })\n\n eventSource.addEventListener('experiment_update', (e) => {\n try {\n const { experiment_id, action } = JSON.parse(e.data)\n if (action === 'started' || action === 'updated') {\n loadExperimentAssignment(experiment_id)\n } else if (action === 'stopped') {\n assignmentsRef.current.delete(experiment_id)\n }\n } catch (err) {\n if (isDebug()) console.error('[Signal] Experiment update error:', err)\n }\n })\n\n eventSource.onerror = () => {\n if (isDebug()) console.warn('[Signal] SSE connection error, reconnecting...')\n eventSource.close()\n // Reconnect after 5 seconds\n setTimeout(connectSSE, 5000)\n }\n\n eventSourceRef.current = eventSource\n }, [apiUrl, apiKey, enabled, realtime, loadExperimentAssignment])\n\n // ============================================\n // Event Tracking\n // ============================================\n\n const flushEvents = useCallback(async () => {\n if (eventQueueRef.current.length === 0) return\n\n const events = [...eventQueueRef.current]\n eventQueueRef.current = []\n\n try {\n // retries: 0 — fire-and-forget tracking; a retried flush after a lost\n // response would double-count events. The transport still aborts a hung\n // request at its timeout (no net::ERR_TIMED_OUT).\n await sonorFetch(\n `${apiUrl}/api/public/signal/events`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n events,\n }),\n },\n { apiKey, retries: 0 },\n )\n } catch (err) {\n // Re-queue failed events\n eventQueueRef.current = [...events, ...eventQueueRef.current]\n if (isDebug()) console.error('[Signal] Event flush error:', err)\n }\n }, [apiUrl, apiKey])\n\n const trackEvent = useCallback((event: Partial<SignalEvent>) => {\n if (!enabled || !apiKey) return\n\n // Enrich event with context\n const enrichedEvent: Partial<SignalEvent> = {\n ...event,\n page_url: window.location.href,\n page_path: window.location.pathname,\n referrer: document.referrer,\n device_type: getDeviceType(),\n browser: getBrowser(),\n os: getOS(),\n viewport_width: window.innerWidth,\n viewport_height: window.innerHeight,\n time_on_page: Date.now() - pageLoadTimeRef.current,\n scroll_depth: scrollDepthRef.current,\n click_count: clickCountRef.current,\n experiments: Array.from(assignmentsRef.current.values()).map(a => ({\n experiment_id: a.experiment_id,\n variant_key: a.variant_key,\n })),\n // Merge page metadata from Analytics if available\n page_metadata: pageMetadataRef?.current ?? undefined,\n timestamp: new Date().toISOString(),\n }\n\n eventQueueRef.current.push(enrichedEvent)\n\n // Debounce flush\n if (flushTimeoutRef.current) {\n clearTimeout(flushTimeoutRef.current)\n }\n flushTimeoutRef.current = setTimeout(flushEvents, 1000)\n }, [enabled, apiKey, flushEvents])\n\n // ============================================\n // Outcome Tracking\n // ============================================\n\n const trackOutcome = useCallback(async (outcome: SignalOutcome) => {\n if (!enabled || !apiKey) return\n\n try {\n // retries: 0 — fire-and-forget conversion signal; never double-fire on a\n // lost response. Still aborts a hung request at the transport timeout.\n await sonorFetch(\n `${apiUrl}/api/public/signal/outcome`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...outcome,\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n experiments: Array.from(assignmentsRef.current.keys()),\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n }),\n },\n { apiKey, retries: 0 },\n )\n } catch (err) {\n if (isDebug()) console.error('[Signal] Outcome tracking error:', err)\n }\n }, [apiUrl, apiKey, enabled])\n\n // ============================================\n // Behavioral Tracking\n // ============================================\n\n useEffect(() => {\n if (!behaviorTracking || typeof window === 'undefined') return\n\n // Track scroll depth\n const handleScroll = () => {\n const scrollTop = window.scrollY\n const docHeight = document.documentElement.scrollHeight - window.innerHeight\n const depth = docHeight > 0 ? Math.round((scrollTop / docHeight) * 100) : 0\n scrollDepthRef.current = Math.max(scrollDepthRef.current, depth)\n }\n\n // Track clicks\n const handleClick = () => {\n clickCountRef.current++\n }\n\n window.addEventListener('scroll', handleScroll, { passive: true })\n window.addEventListener('click', handleClick)\n\n // Flush on visibility change or page hide.\n // `pagehide` (not `beforeunload`): fires on iOS Safari, bfcache-safe.\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'hidden') {\n flushEvents()\n }\n }\n\n document.addEventListener('visibilitychange', handleVisibilityChange)\n window.addEventListener('pagehide', flushEvents)\n\n return () => {\n window.removeEventListener('scroll', handleScroll)\n window.removeEventListener('click', handleClick)\n document.removeEventListener('visibilitychange', handleVisibilityChange)\n window.removeEventListener('pagehide', flushEvents)\n }\n }, [behaviorTracking, flushEvents])\n\n // ============================================\n // Initialization + shell registration\n // ============================================\n\n useEffect(() => {\n fetchConfig()\n }, [fetchConfig])\n\n useEffect(() => {\n if (config && realtime) {\n connectSSE()\n }\n\n return () => {\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n }\n }\n }, [config, realtime, connectSSE])\n\n // Hand the imperative API to the shell; buffered calls drain on register.\n useEffect(() => {\n onRegister({\n trackEvent,\n trackOutcome: (outcome: SignalOutcome) => { void trackOutcome(outcome) },\n getExperiment,\n refreshConfig: fetchConfig,\n })\n return () => onRegister(null)\n }, [onRegister, trackEvent, trackOutcome, getExperiment, fetchConfig])\n\n return null\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/signal/SignalCore.tsx"],"names":[],"mappings":"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","file":"SignalCore-BKG66B4C.mjs","sourcesContent":["/**\n * @sonordev/site-kit/signal - SignalCore\n *\n * The heavy half of SignalBridge: config fetching, SSE streaming, experiment\n * assignment, event queue/flush, and behavioral tracking. Mounted by the\n * SignalBridge shell as a CHILDLESS lazy sibling — it never wraps page\n * content, so the signal machinery stays out of the server-render path and\n * off the critical hydration chunk. It reports state up to the shell via\n * `onState` and registers its imperative API via `onRegister`.\n */\n\n'use client'\n\nimport { useCallback, useEffect, useRef, useState } from 'react'\n// Single source of truth for visitor/session IDs (storage keys _sk_vid/_sk_sid)\n// — shared with Analytics and Engage. Do NOT re-fork ID logic into this module.\nimport { getOrCreateVisitorId, getOrCreateSessionId } from '../shared/identity'\n// Canonical client transport — the same wrapper Analytics/Forms/Engage route\n// through (see shared/sonorFetch header). It gives every request a per-attempt\n// AbortSignal timeout, so a hung API aborts cleanly instead of being left to log\n// net::ERR_TIMED_OUT — the console error that fails Lighthouse best-practices.\n// It also sets x-api-key from the `apiKey` option, so callers drop the header.\nimport { sonorFetch } from '../shared/sonorFetch'\nimport type {\n SignalConfig,\n SignalEvent,\n SignalOutcome,\n ExperimentAssignment,\n} from './types'\n\n// ============================================\n// Shell ↔ core contract\n// ============================================\n\nexport interface SignalCoreApi {\n trackEvent: (event: Partial<SignalEvent>) => void\n trackOutcome: (outcome: SignalOutcome) => void\n getExperiment: (experimentId: string) => ExperimentAssignment | null\n refreshConfig: () => Promise<void>\n}\n\nexport interface SignalCoreState {\n config: SignalConfig | null\n loading: boolean\n error: Error | null\n}\n\nexport interface SignalCoreProps {\n enabled: boolean\n realtime: boolean\n experiments: boolean\n behaviorTracking: boolean\n externalVisitorId?: string\n externalSessionId?: string\n pageMetadataRef?: React.RefObject<Record<string, unknown> | null>\n /** Called with the imperative API on mount, and with null on unmount. */\n onRegister: (api: SignalCoreApi | null) => void\n /** Called whenever config/loading/error change, so the shell can re-render consumers. */\n onState: (state: SignalCoreState) => void\n}\n\n// ============================================\n// Utility Functions\n// ============================================\n\nfunction getApiConfig() {\n const apiUrl = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_URL__ || 'https://api.sonor.io'\n : 'https://api.sonor.io'\n const apiKey = typeof window !== 'undefined'\n ? (window as any).__SITE_KIT_API_KEY__\n : undefined\n return { apiUrl, apiKey }\n}\n\n// A visitor's console must stay clean (Lighthouse \"errors logged to the console\"\n// best-practice) — Signal's diagnostics only surface when the site opts into\n// debug via SiteKitClientProviders' __SITE_KIT_DEBUG__ global, mirroring how\n// AnalyticsProvider gates every one of its logs behind its `debug` prop.\nfunction isDebug(): boolean {\n return typeof window !== 'undefined' && !!(window as any).__SITE_KIT_DEBUG__\n}\n\nfunction getDeviceType(): 'desktop' | 'mobile' | 'tablet' {\n if (typeof window === 'undefined') return 'desktop'\n const ua = navigator.userAgent\n if (/tablet|ipad|playbook|silk/i.test(ua)) return 'tablet'\n if (/mobile|iphone|ipod|android|blackberry|opera mini|iemobile/i.test(ua)) return 'mobile'\n return 'desktop'\n}\n\nfunction getBrowser(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Firefox')) return 'Firefox'\n if (ua.includes('Edg')) return 'Edge'\n if (ua.includes('Chrome')) return 'Chrome'\n if (ua.includes('Safari')) return 'Safari'\n return 'Other'\n}\n\nfunction getOS(): string {\n if (typeof window === 'undefined') return 'unknown'\n const ua = navigator.userAgent\n if (ua.includes('Windows')) return 'Windows'\n if (ua.includes('Mac')) return 'macOS'\n if (ua.includes('iPhone') || ua.includes('iPad')) return 'iOS'\n if (ua.includes('Android')) return 'Android'\n if (ua.includes('Linux')) return 'Linux'\n return 'Other'\n}\n\n// ============================================\n// SignalCore Component (childless)\n// ============================================\n\nexport function SignalCore({\n enabled,\n realtime,\n experiments,\n behaviorTracking,\n externalVisitorId,\n externalSessionId,\n pageMetadataRef,\n onRegister,\n onState,\n}: SignalCoreProps) {\n const [config, setConfig] = useState<SignalConfig | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<Error | null>(null)\n\n // Refs for SSE and tracking\n const eventSourceRef = useRef<EventSource | null>(null)\n const eventQueueRef = useRef<Partial<SignalEvent>[]>([])\n const flushTimeoutRef = useRef<NodeJS.Timeout | null>(null)\n const assignmentsRef = useRef<Map<string, ExperimentAssignment>>(new Map())\n\n // Behavioral tracking state\n const pageLoadTimeRef = useRef<number>(Date.now())\n const scrollDepthRef = useRef<number>(0)\n const clickCountRef = useRef<number>(0)\n\n const { apiUrl, apiKey } = getApiConfig()\n\n // Use external IDs from shared identity, fall back to the shared generators\n const resolvedVisitorId = externalVisitorId || getOrCreateVisitorId()\n const resolvedSessionId = externalSessionId || getOrCreateSessionId()\n\n // Mirror state up to the shell so context consumers re-render\n useEffect(() => {\n onState({ config, loading, error })\n }, [config, loading, error, onState])\n\n // ============================================\n // Experiment Assignment\n // ============================================\n\n const loadExperimentAssignment = useCallback(async (experimentId: string): Promise<ExperimentAssignment | null> => {\n // Check localStorage first\n const storageKey = `_signal_exp_${experimentId}`\n const stored = localStorage.getItem(storageKey)\n\n if (stored) {\n try {\n const assignment = JSON.parse(stored) as ExperimentAssignment\n if (assignment.expires > Date.now()) {\n assignmentsRef.current.set(experimentId, assignment)\n return assignment\n }\n } catch {\n // Invalid stored data, continue to fetch\n }\n }\n\n // Fetch from API — idempotent read, so the transport's default retries apply.\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/signal/experiment/${experimentId}`,\n {\n headers: {\n 'x-visitor-id': resolvedVisitorId,\n },\n },\n { apiKey },\n )\n\n if (!response.ok) return null\n\n const assignment = await response.json() as ExperimentAssignment\n\n // Store assignment\n localStorage.setItem(storageKey, JSON.stringify(assignment))\n assignmentsRef.current.set(experimentId, assignment)\n\n return assignment\n } catch (err) {\n if (isDebug()) console.error('[Signal] Experiment assignment error:', err)\n return null\n }\n }, [apiUrl, apiKey])\n\n const getExperiment = useCallback((experimentId: string): ExperimentAssignment | null => {\n return assignmentsRef.current.get(experimentId) || null\n }, [])\n\n // ============================================\n // Config Fetching\n // ============================================\n\n const fetchConfig = useCallback(async () => {\n if (!apiKey || !enabled) {\n setLoading(false)\n return\n }\n\n try {\n const response = await sonorFetch(\n `${apiUrl}/api/public/signal/config`,\n {\n headers: {\n 'x-visitor-id': resolvedVisitorId,\n },\n },\n { apiKey },\n )\n\n if (!response.ok) {\n throw new Error(`Failed to fetch Signal config: ${response.statusText}`)\n }\n\n const data = await response.json()\n setConfig(data.config)\n setError(null)\n\n // Load experiment assignments\n if (experiments && data.config?.experiments) {\n for (const exp of data.config.experiments) {\n if (exp.status === 'running') {\n await loadExperimentAssignment(exp.id)\n }\n }\n }\n } catch (err) {\n if (isDebug()) console.error('[Signal] Config fetch error:', err)\n setError(err as Error)\n } finally {\n setLoading(false)\n }\n }, [apiUrl, apiKey, enabled, experiments, resolvedVisitorId, loadExperimentAssignment])\n\n // ============================================\n // SSE Real-time Updates\n // ============================================\n\n const connectSSE = useCallback(() => {\n if (!apiKey || !enabled || !realtime) return\n\n // Close existing connection\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n }\n\n const url = `${apiUrl}/api/public/signal/stream?key=${apiKey}`\n const eventSource = new EventSource(url)\n\n eventSource.addEventListener('config_update', (e) => {\n try {\n const { config: newConfig, version } = JSON.parse(e.data)\n setConfig(prev => {\n if (prev?.version !== version) {\n if (isDebug()) console.log('[Signal] Config updated to version:', version)\n return newConfig\n }\n return prev\n })\n } catch (err) {\n if (isDebug()) console.error('[Signal] SSE parse error:', err)\n }\n })\n\n eventSource.addEventListener('experiment_update', (e) => {\n try {\n const { experiment_id, action } = JSON.parse(e.data)\n if (action === 'started' || action === 'updated') {\n loadExperimentAssignment(experiment_id)\n } else if (action === 'stopped') {\n assignmentsRef.current.delete(experiment_id)\n }\n } catch (err) {\n if (isDebug()) console.error('[Signal] Experiment update error:', err)\n }\n })\n\n eventSource.onerror = () => {\n if (isDebug()) console.warn('[Signal] SSE connection error, reconnecting...')\n eventSource.close()\n // Reconnect after 5 seconds\n setTimeout(connectSSE, 5000)\n }\n\n eventSourceRef.current = eventSource\n }, [apiUrl, apiKey, enabled, realtime, loadExperimentAssignment])\n\n // ============================================\n // Event Tracking\n // ============================================\n\n const flushEvents = useCallback(async () => {\n if (eventQueueRef.current.length === 0) return\n\n const events = [...eventQueueRef.current]\n eventQueueRef.current = []\n\n try {\n // retries: 0 — fire-and-forget tracking; a retried flush after a lost\n // response would double-count events. The transport still aborts a hung\n // request at its timeout (no net::ERR_TIMED_OUT).\n await sonorFetch(\n `${apiUrl}/api/public/signal/events`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n events,\n }),\n },\n { apiKey, retries: 0 },\n )\n } catch (err) {\n // Re-queue failed events\n eventQueueRef.current = [...events, ...eventQueueRef.current]\n if (isDebug()) console.error('[Signal] Event flush error:', err)\n }\n }, [apiUrl, apiKey])\n\n const trackEvent = useCallback((event: Partial<SignalEvent>) => {\n if (!enabled || !apiKey) return\n\n // Enrich event with context\n const enrichedEvent: Partial<SignalEvent> = {\n ...event,\n page_url: window.location.href,\n page_path: window.location.pathname,\n referrer: document.referrer,\n device_type: getDeviceType(),\n browser: getBrowser(),\n os: getOS(),\n viewport_width: window.innerWidth,\n viewport_height: window.innerHeight,\n time_on_page: Date.now() - pageLoadTimeRef.current,\n scroll_depth: scrollDepthRef.current,\n click_count: clickCountRef.current,\n experiments: Array.from(assignmentsRef.current.values()).map(a => ({\n experiment_id: a.experiment_id,\n variant_key: a.variant_key,\n })),\n // Merge page metadata from Analytics if available\n page_metadata: pageMetadataRef?.current ?? undefined,\n timestamp: new Date().toISOString(),\n }\n\n eventQueueRef.current.push(enrichedEvent)\n\n // Debounce flush\n if (flushTimeoutRef.current) {\n clearTimeout(flushTimeoutRef.current)\n }\n flushTimeoutRef.current = setTimeout(flushEvents, 1000)\n }, [enabled, apiKey, flushEvents])\n\n // ============================================\n // Outcome Tracking\n // ============================================\n\n const trackOutcome = useCallback(async (outcome: SignalOutcome) => {\n if (!enabled || !apiKey) return\n\n try {\n // retries: 0 — fire-and-forget conversion signal; never double-fire on a\n // lost response. Still aborts a hung request at the transport timeout.\n await sonorFetch(\n `${apiUrl}/api/public/signal/outcome`,\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n ...outcome,\n visitor_id: resolvedVisitorId,\n session_id: resolvedSessionId,\n experiments: Array.from(assignmentsRef.current.keys()),\n page_url: window.location.href,\n timestamp: new Date().toISOString(),\n }),\n },\n { apiKey, retries: 0 },\n )\n } catch (err) {\n if (isDebug()) console.error('[Signal] Outcome tracking error:', err)\n }\n }, [apiUrl, apiKey, enabled])\n\n // ============================================\n // Behavioral Tracking\n // ============================================\n\n useEffect(() => {\n if (!behaviorTracking || typeof window === 'undefined') return\n\n // Track scroll depth\n const handleScroll = () => {\n const scrollTop = window.scrollY\n const docHeight = document.documentElement.scrollHeight - window.innerHeight\n const depth = docHeight > 0 ? Math.round((scrollTop / docHeight) * 100) : 0\n scrollDepthRef.current = Math.max(scrollDepthRef.current, depth)\n }\n\n // Track clicks\n const handleClick = () => {\n clickCountRef.current++\n }\n\n window.addEventListener('scroll', handleScroll, { passive: true })\n window.addEventListener('click', handleClick)\n\n // Flush on visibility change or page hide.\n // `pagehide` (not `beforeunload`): fires on iOS Safari, bfcache-safe.\n const handleVisibilityChange = () => {\n if (document.visibilityState === 'hidden') {\n flushEvents()\n }\n }\n\n document.addEventListener('visibilitychange', handleVisibilityChange)\n window.addEventListener('pagehide', flushEvents)\n\n return () => {\n window.removeEventListener('scroll', handleScroll)\n window.removeEventListener('click', handleClick)\n document.removeEventListener('visibilitychange', handleVisibilityChange)\n window.removeEventListener('pagehide', flushEvents)\n }\n }, [behaviorTracking, flushEvents])\n\n // ============================================\n // Initialization + shell registration\n // ============================================\n\n useEffect(() => {\n fetchConfig()\n }, [fetchConfig])\n\n useEffect(() => {\n if (config && realtime) {\n connectSSE()\n }\n\n return () => {\n if (eventSourceRef.current) {\n eventSourceRef.current.close()\n }\n }\n }, [config, realtime, connectSSE])\n\n // Hand the imperative API to the shell; buffered calls drain on register.\n useEffect(() => {\n onRegister({\n trackEvent,\n trackOutcome: (outcome: SignalOutcome) => { void trackOutcome(outcome) },\n getExperiment,\n refreshConfig: fetchConfig,\n })\n return () => onRegister(null)\n }, [onRegister, trackEvent, trackOutcome, getExperiment, fetchConfig])\n\n return null\n}\n"]}
@@ -1,16 +0,0 @@
1
- 'use strict';
2
-
3
- var chunkPIV54R2O_js = require('./chunk-PIV54R2O.js');
4
- require('./chunk-JEOKDUPQ.js');
5
- require('./chunk-KPKZBIAQ.js');
6
- require('./chunk-3X2YPJU5.js');
7
- require('./chunk-ZSMWDLMK.js');
8
-
9
-
10
-
11
- Object.defineProperty(exports, "SitemapSync", {
12
- enumerable: true,
13
- get: function () { return chunkPIV54R2O_js.SitemapSync; }
14
- });
15
- //# sourceMappingURL=SitemapSync-DWX7I6MX.js.map
16
- //# sourceMappingURL=SitemapSync-DWX7I6MX.js.map
@@ -1,7 +0,0 @@
1
- export { SitemapSync } from './chunk-QW3T6WH2.mjs';
2
- import './chunk-QJU6HBSK.mjs';
3
- import './chunk-GUU3AEFM.mjs';
4
- import './chunk-K6YGF2KJ.mjs';
5
- import './chunk-4XPGGLVP.mjs';
6
- //# sourceMappingURL=SitemapSync-IO2VOR23.mjs.map
7
- //# sourceMappingURL=SitemapSync-IO2VOR23.mjs.map