@rovela-ai/sdk 0.4.3 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (144) hide show
  1. package/dist/admin/components/AdminNav.d.ts.map +1 -1
  2. package/dist/admin/components/AdminNav.js +10 -1
  3. package/dist/admin/components/AdminNav.js.map +1 -1
  4. package/dist/admin/components/ExampleContentBanner.js +2 -2
  5. package/dist/admin/components/ExampleContentBanner.js.map +1 -1
  6. package/dist/admin/components/SetupGuide.d.ts.map +1 -1
  7. package/dist/admin/components/SetupGuide.js +4 -4
  8. package/dist/admin/components/SetupGuide.js.map +1 -1
  9. package/dist/admin/components/index.d.ts +0 -1
  10. package/dist/admin/components/index.d.ts.map +1 -1
  11. package/dist/admin/components/index.js +0 -1
  12. package/dist/admin/components/index.js.map +1 -1
  13. package/dist/admin/hooks/fetchAdminApi.d.ts.map +1 -1
  14. package/dist/admin/hooks/fetchAdminApi.js +6 -0
  15. package/dist/admin/hooks/fetchAdminApi.js.map +1 -1
  16. package/dist/admin/index.d.ts +1 -1
  17. package/dist/admin/index.d.ts.map +1 -1
  18. package/dist/admin/index.js +1 -1
  19. package/dist/admin/index.js.map +1 -1
  20. package/dist/admin/styles/admin-theme.css +11 -0
  21. package/dist/analytics/api/dashboard.d.ts +16 -0
  22. package/dist/analytics/api/dashboard.d.ts.map +1 -0
  23. package/dist/analytics/api/dashboard.js +37 -0
  24. package/dist/analytics/api/dashboard.js.map +1 -0
  25. package/dist/analytics/api/events.d.ts +23 -0
  26. package/dist/analytics/api/events.d.ts.map +1 -0
  27. package/dist/analytics/api/events.js +55 -0
  28. package/dist/analytics/api/events.js.map +1 -0
  29. package/dist/analytics/api/index.d.ts +15 -0
  30. package/dist/analytics/api/index.d.ts.map +1 -0
  31. package/dist/analytics/api/index.js +15 -0
  32. package/dist/analytics/api/index.js.map +1 -0
  33. package/dist/analytics/api/track.d.ts +20 -0
  34. package/dist/analytics/api/track.d.ts.map +1 -0
  35. package/dist/analytics/api/track.js +233 -0
  36. package/dist/analytics/api/track.js.map +1 -0
  37. package/dist/analytics/api/visitors.d.ts +19 -0
  38. package/dist/analytics/api/visitors.d.ts.map +1 -0
  39. package/dist/analytics/api/visitors.js +49 -0
  40. package/dist/analytics/api/visitors.js.map +1 -0
  41. package/dist/analytics/client/tracker.d.ts +51 -0
  42. package/dist/analytics/client/tracker.d.ts.map +1 -0
  43. package/dist/analytics/client/tracker.js +208 -0
  44. package/dist/analytics/client/tracker.js.map +1 -0
  45. package/dist/analytics/components/AnalyticsDashboard.d.ts +2 -0
  46. package/dist/analytics/components/AnalyticsDashboard.d.ts.map +1 -0
  47. package/dist/analytics/components/AnalyticsDashboard.js +26 -0
  48. package/dist/analytics/components/AnalyticsDashboard.js.map +1 -0
  49. package/dist/analytics/components/AnalyticsPeriodContext.d.ts +13 -0
  50. package/dist/analytics/components/AnalyticsPeriodContext.d.ts.map +1 -0
  51. package/dist/analytics/components/AnalyticsPeriodContext.js +28 -0
  52. package/dist/analytics/components/AnalyticsPeriodContext.js.map +1 -0
  53. package/dist/analytics/components/AnalyticsProvider.d.ts +22 -0
  54. package/dist/analytics/components/AnalyticsProvider.d.ts.map +1 -0
  55. package/dist/analytics/components/AnalyticsProvider.js +152 -0
  56. package/dist/analytics/components/AnalyticsProvider.js.map +1 -0
  57. package/dist/analytics/components/AnalyticsTabNav.d.ts +14 -0
  58. package/dist/analytics/components/AnalyticsTabNav.d.ts.map +1 -0
  59. package/dist/analytics/components/AnalyticsTabNav.js +42 -0
  60. package/dist/analytics/components/AnalyticsTabNav.js.map +1 -0
  61. package/dist/analytics/hooks/useAnalytics.d.ts +9 -0
  62. package/dist/analytics/hooks/useAnalytics.d.ts.map +1 -0
  63. package/dist/analytics/hooks/useAnalytics.js +8 -0
  64. package/dist/analytics/hooks/useAnalytics.js.map +1 -0
  65. package/dist/analytics/hooks/useAnalyticsDashboard.d.ts +9 -0
  66. package/dist/analytics/hooks/useAnalyticsDashboard.d.ts.map +1 -0
  67. package/dist/analytics/hooks/useAnalyticsDashboard.js +45 -0
  68. package/dist/analytics/hooks/useAnalyticsDashboard.js.map +1 -0
  69. package/dist/analytics/hooks/useEventsLog.d.ts +24 -0
  70. package/dist/analytics/hooks/useEventsLog.d.ts.map +1 -0
  71. package/dist/analytics/hooks/useEventsLog.js +85 -0
  72. package/dist/analytics/hooks/useEventsLog.js.map +1 -0
  73. package/dist/analytics/hooks/useVisitorsList.d.ts +20 -0
  74. package/dist/analytics/hooks/useVisitorsList.d.ts.map +1 -0
  75. package/dist/analytics/hooks/useVisitorsList.js +73 -0
  76. package/dist/analytics/hooks/useVisitorsList.js.map +1 -0
  77. package/dist/analytics/index.d.ts +44 -0
  78. package/dist/analytics/index.d.ts.map +1 -0
  79. package/dist/analytics/index.js +39 -0
  80. package/dist/analytics/index.js.map +1 -0
  81. package/dist/analytics/server/index.d.ts +10 -0
  82. package/dist/analytics/server/index.d.ts.map +1 -0
  83. package/dist/analytics/server/index.js +9 -0
  84. package/dist/analytics/server/index.js.map +1 -0
  85. package/dist/analytics/server/normalize.d.ts +23 -0
  86. package/dist/analytics/server/normalize.d.ts.map +1 -0
  87. package/dist/analytics/server/normalize.js +75 -0
  88. package/dist/analytics/server/normalize.js.map +1 -0
  89. package/dist/analytics/server/queries.d.ts +74 -0
  90. package/dist/analytics/server/queries.d.ts.map +1 -0
  91. package/dist/analytics/server/queries.js +470 -0
  92. package/dist/analytics/server/queries.js.map +1 -0
  93. package/dist/analytics/types.d.ts +186 -0
  94. package/dist/analytics/types.d.ts.map +1 -0
  95. package/dist/analytics/types.js +16 -0
  96. package/dist/analytics/types.js.map +1 -0
  97. package/dist/analytics/views/DashboardsView.d.ts +6 -0
  98. package/dist/analytics/views/DashboardsView.d.ts.map +1 -0
  99. package/dist/analytics/views/DashboardsView.js +93 -0
  100. package/dist/analytics/views/DashboardsView.js.map +1 -0
  101. package/dist/analytics/views/EventsView.d.ts +6 -0
  102. package/dist/analytics/views/EventsView.d.ts.map +1 -0
  103. package/dist/analytics/views/EventsView.js +85 -0
  104. package/dist/analytics/views/EventsView.js.map +1 -0
  105. package/dist/analytics/views/VisitorsView.d.ts +6 -0
  106. package/dist/analytics/views/VisitorsView.d.ts.map +1 -0
  107. package/dist/analytics/views/VisitorsView.js +57 -0
  108. package/dist/analytics/views/VisitorsView.js.map +1 -0
  109. package/dist/cart/store.d.ts.map +1 -1
  110. package/dist/cart/store.js +12 -0
  111. package/dist/cart/store.js.map +1 -1
  112. package/dist/checkout/components/CheckoutFlow.d.ts.map +1 -1
  113. package/dist/checkout/components/CheckoutFlow.js +26 -2
  114. package/dist/checkout/components/CheckoutFlow.js.map +1 -1
  115. package/dist/checkout/components/ShippingForm.js +10 -5
  116. package/dist/checkout/components/ShippingForm.js.map +1 -1
  117. package/dist/checkout/hooks/useCheckout.d.ts.map +1 -1
  118. package/dist/checkout/hooks/useCheckout.js +12 -1
  119. package/dist/checkout/hooks/useCheckout.js.map +1 -1
  120. package/dist/checkout/server/handle-webhook.js +15 -0
  121. package/dist/checkout/server/handle-webhook.js.map +1 -1
  122. package/dist/checkout/types.d.ts +13 -0
  123. package/dist/checkout/types.d.ts.map +1 -1
  124. package/dist/core/db/client.d.ts +14 -0
  125. package/dist/core/db/client.d.ts.map +1 -1
  126. package/dist/core/db/client.js +12 -0
  127. package/dist/core/db/client.js.map +1 -1
  128. package/dist/core/db/index.d.ts +2 -1
  129. package/dist/core/db/index.d.ts.map +1 -1
  130. package/dist/core/db/index.js +1 -1
  131. package/dist/core/db/index.js.map +1 -1
  132. package/dist/core/db/queries.d.ts +8 -7
  133. package/dist/core/db/queries.d.ts.map +1 -1
  134. package/dist/core/db/queries.js +80 -0
  135. package/dist/core/db/queries.js.map +1 -1
  136. package/dist/core/db/schema.d.ts +340 -4
  137. package/dist/core/db/schema.d.ts.map +1 -1
  138. package/dist/core/db/schema.js +55 -1
  139. package/dist/core/db/schema.js.map +1 -1
  140. package/dist/core/server/index.d.ts +2 -2
  141. package/dist/core/server/index.d.ts.map +1 -1
  142. package/dist/core/server/index.js +2 -0
  143. package/dist/core/server/index.js.map +1 -1
  144. package/package.json +25 -1
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @rovela-ai/sdk/analytics
3
+ *
4
+ * Storefront analytics module — internal GA4-shaped event tracker. See
5
+ * CLAUDE.md §46 for architecture.
6
+ *
7
+ * Public entry points:
8
+ *
9
+ * - `<AnalyticsProvider>` — mount inside the customer branch of
10
+ * LayoutContent.tsx. Auto-fires page_view + session_start, gates on
11
+ * cookie consent, excludes admin sessions.
12
+ * - `useAnalytics()` — storefront-component hook for manual events
13
+ * (add_to_cart, begin_checkout, etc.).
14
+ * - `<AnalyticsDashboard>` — admin dashboard UI, mount at
15
+ * app/admin/(dashboard)/analytics/page.tsx.
16
+ *
17
+ * Sub-paths:
18
+ * - `@rovela-ai/sdk/analytics/server` — recordEvent, getAnalyticsDashboard,
19
+ * getTrafficSummary7d (server-only).
20
+ * - `@rovela-ai/sdk/analytics/api/track` — POST handler.
21
+ * - `@rovela-ai/sdk/analytics/api/dashboard` — GET handler.
22
+ */
23
+ export { AnalyticsProvider, useAnalytics } from './components/AnalyticsProvider';
24
+ export type { AnalyticsProviderProps } from './components/AnalyticsProvider';
25
+ export { AnalyticsTabNav } from './components/AnalyticsTabNav';
26
+ export type { AnalyticsTabNavProps } from './components/AnalyticsTabNav';
27
+ export { AnalyticsPeriodProvider, useAnalyticsPeriod, } from './components/AnalyticsPeriodContext';
28
+ export type { AnalyticsPeriodProviderProps } from './components/AnalyticsPeriodContext';
29
+ export { DashboardsView } from './views/DashboardsView';
30
+ export type { DashboardsViewProps } from './views/DashboardsView';
31
+ export { EventsView } from './views/EventsView';
32
+ export type { EventsViewProps } from './views/EventsView';
33
+ export { VisitorsView } from './views/VisitorsView';
34
+ export type { VisitorsViewProps } from './views/VisitorsView';
35
+ export { AnalyticsDashboard } from './components/AnalyticsDashboard';
36
+ export { useAnalyticsDashboard } from './hooks/useAnalyticsDashboard';
37
+ export type { UseAnalyticsDashboardReturn } from './hooks/useAnalyticsDashboard';
38
+ export { useEventsLog } from './hooks/useEventsLog';
39
+ export type { UseEventsLogOptions, UseEventsLogReturn, } from './hooks/useEventsLog';
40
+ export { useVisitorsList } from './hooks/useVisitorsList';
41
+ export type { UseVisitorsListOptions, UseVisitorsListReturn, } from './hooks/useVisitorsList';
42
+ export { emitEvent, getVisitorId, getSessionId } from './client/tracker';
43
+ export type { AnalyticsEventKind, AnalyticsPayload, AnalyticsWireEvent, AnalyticsCommon, AnalyticsIdentity, AnalyticsPeriod, AnalyticsSortDir, AnalyticsOverview, AnalyticsOverviewWithDeltas, AnalyticsTrendPoint, AnalyticsTopPage, AnalyticsTopProduct, AnalyticsSourceBucket, AnalyticsDeviceBucket, AnalyticsDashboardPayload, AnalyticsTrafficSummary, AnalyticsEventLogRow, AnalyticsEventsLogPage, AnalyticsVisitorRow, AnalyticsVisitorsPage, } from './types';
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analytics/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAChF,YAAY,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAG5E,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAC9D,YAAY,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAA;AAExE,OAAO,EACL,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,qCAAqC,CAAA;AAC5C,YAAY,EAAE,4BAA4B,EAAE,MAAM,qCAAqC,CAAA;AAEvF,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AACvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAEjE,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEzD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,YAAY,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAI7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AACrE,YAAY,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAA;AAEhF,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACnD,YAAY,EACV,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,YAAY,EACV,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAGxE,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EACjB,2BAA2B,EAC3B,mBAAmB,EACnB,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,EACrB,yBAAyB,EACzB,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,SAAS,CAAA"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @rovela-ai/sdk/analytics
3
+ *
4
+ * Storefront analytics module — internal GA4-shaped event tracker. See
5
+ * CLAUDE.md §46 for architecture.
6
+ *
7
+ * Public entry points:
8
+ *
9
+ * - `<AnalyticsProvider>` — mount inside the customer branch of
10
+ * LayoutContent.tsx. Auto-fires page_view + session_start, gates on
11
+ * cookie consent, excludes admin sessions.
12
+ * - `useAnalytics()` — storefront-component hook for manual events
13
+ * (add_to_cart, begin_checkout, etc.).
14
+ * - `<AnalyticsDashboard>` — admin dashboard UI, mount at
15
+ * app/admin/(dashboard)/analytics/page.tsx.
16
+ *
17
+ * Sub-paths:
18
+ * - `@rovela-ai/sdk/analytics/server` — recordEvent, getAnalyticsDashboard,
19
+ * getTrafficSummary7d (server-only).
20
+ * - `@rovela-ai/sdk/analytics/api/track` — POST handler.
21
+ * - `@rovela-ai/sdk/analytics/api/dashboard` — GET handler.
22
+ */
23
+ // Client surface
24
+ export { AnalyticsProvider, useAnalytics } from './components/AnalyticsProvider';
25
+ // Tab shell + views (route-per-tab pattern)
26
+ export { AnalyticsTabNav } from './components/AnalyticsTabNav';
27
+ export { AnalyticsPeriodProvider, useAnalyticsPeriod, } from './components/AnalyticsPeriodContext';
28
+ export { DashboardsView } from './views/DashboardsView';
29
+ export { EventsView } from './views/EventsView';
30
+ export { VisitorsView } from './views/VisitorsView';
31
+ // Back-compat: legacy single-page dashboard (now a thin shell over the
32
+ // tab nav + DashboardsView).
33
+ export { AnalyticsDashboard } from './components/AnalyticsDashboard';
34
+ export { useAnalyticsDashboard } from './hooks/useAnalyticsDashboard';
35
+ export { useEventsLog } from './hooks/useEventsLog';
36
+ export { useVisitorsList } from './hooks/useVisitorsList';
37
+ // Low-level client primitives (rare; useful for non-React surfaces)
38
+ export { emitEvent, getVisitorId, getSessionId } from './client/tracker';
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/analytics/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,iBAAiB;AACjB,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAA;AAGhF,4CAA4C;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAA;AAG9D,OAAO,EACL,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,qCAAqC,CAAA;AAG5C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAGvD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGnD,uEAAuE;AACvE,6BAA6B;AAC7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAA;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAA;AAGrE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAMnD,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAMzD,oEAAoE;AACpE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @rovela-ai/sdk/analytics/server
3
+ *
4
+ * Server-only entry point. Re-exports the read/write helpers + normalizers.
5
+ * Safe to import from API routes, webhook handlers, and platform-side code.
6
+ */
7
+ export { recordEvent, getAnalyticsDashboard, getTrafficSummary7d, getEventsLog, getVisitorsList, periodToDays, } from './queries';
8
+ export type { GetEventsLogOptions, GetVisitorsListOptions, } from './queries';
9
+ export { isBotUserAgent, deviceFromUserAgent, referrerHost, normalizePath, clip, safeCountry, } from './normalize';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/analytics/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,WAAW,CAAA;AAElB,YAAY,EACV,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,WAAW,GACZ,MAAM,aAAa,CAAA"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @rovela-ai/sdk/analytics/server
3
+ *
4
+ * Server-only entry point. Re-exports the read/write helpers + normalizers.
5
+ * Safe to import from API routes, webhook handlers, and platform-side code.
6
+ */
7
+ export { recordEvent, getAnalyticsDashboard, getTrafficSummary7d, getEventsLog, getVisitorsList, periodToDays, } from './queries';
8
+ export { isBotUserAgent, deviceFromUserAgent, referrerHost, normalizePath, clip, safeCountry, } from './normalize';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analytics/server/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,WAAW,EACX,qBAAqB,EACrB,mBAAmB,EACnB,YAAY,EACZ,eAAe,EACf,YAAY,GACb,MAAM,WAAW,CAAA;AAOlB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,YAAY,EACZ,aAAa,EACb,IAAI,EACJ,WAAW,GACZ,MAAM,aAAa,CAAA"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @rovela-ai/sdk/analytics/server/normalize
3
+ *
4
+ * Server-side normalizers for analytics event ingest. All pure functions —
5
+ * no I/O, no DB, no side effects. The track endpoint pipes the incoming
6
+ * request through these before INSERT to:
7
+ *
8
+ * - Strip PII (raw UA never stored, only device family)
9
+ * - Bound cardinality (referrer to host only, path to pathname only)
10
+ * - Reject bot traffic (cheap UA-pattern check)
11
+ */
12
+ export declare function isBotUserAgent(ua: string | null | undefined): boolean;
13
+ /** Derive coarse device family from UA. Returns null if UA is empty. */
14
+ export declare function deviceFromUserAgent(ua: string | null | undefined): 'mobile' | 'desktop' | 'tablet' | null;
15
+ /** Strip a URL to its host. Returns null for empty / unparsable input. */
16
+ export declare function referrerHost(referrer: string | null | undefined): string | null;
17
+ /** Drop query string + hash; keep pathname only. Cardinality-bounded. */
18
+ export declare function normalizePath(path: string | null | undefined): string;
19
+ /** Truncate any free-text field to a safe upper bound. */
20
+ export declare function clip(s: string | null | undefined, max?: number): string | null;
21
+ /** ISO-3166-1 alpha-2 sanity check. Returns null for anything else. */
22
+ export declare function safeCountry(c: string | null | undefined): string | null;
23
+ //# sourceMappingURL=normalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/analytics/server/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAGrE;AAED,wEAAwE;AACxE,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC5B,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,IAAI,CAQxC;AAED,0EAA0E;AAC1E,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAQ/E;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAarE;AAED,0DAA0D;AAC1D,wBAAgB,IAAI,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,SAAM,GAAG,MAAM,GAAG,IAAI,CAG3E;AAED,uEAAuE;AACvE,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAIvE"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * @rovela-ai/sdk/analytics/server/normalize
3
+ *
4
+ * Server-side normalizers for analytics event ingest. All pure functions —
5
+ * no I/O, no DB, no side effects. The track endpoint pipes the incoming
6
+ * request through these before INSERT to:
7
+ *
8
+ * - Strip PII (raw UA never stored, only device family)
9
+ * - Bound cardinality (referrer to host only, path to pathname only)
10
+ * - Reject bot traffic (cheap UA-pattern check)
11
+ */
12
+ /** Conservative UA regex — catches the long-tail without being aggressive
13
+ * enough to false-positive on real visitors. We accept some noise rather
14
+ * than miss real merchants browsing on niche mobile browsers. */
15
+ const BOT_UA = /bot|crawler|spider|HeadlessChrome|Lighthouse|preview|monitor|pingdom|gtmetrix/i;
16
+ export function isBotUserAgent(ua) {
17
+ if (!ua)
18
+ return true; // empty UA is almost always a bot
19
+ return BOT_UA.test(ua);
20
+ }
21
+ /** Derive coarse device family from UA. Returns null if UA is empty. */
22
+ export function deviceFromUserAgent(ua) {
23
+ if (!ua)
24
+ return null;
25
+ // Order matters — iPad UA contains "Mobile" historically, so tablet must win.
26
+ if (/iPad|Tablet|PlayBook|(?:Android(?!.*Mobile))/i.test(ua))
27
+ return 'tablet';
28
+ if (/Mobile|iP(hone|od)|Android|BlackBerry|IEMobile|Kindle|Silk|Opera M(ob|in)i/i.test(ua)) {
29
+ return 'mobile';
30
+ }
31
+ return 'desktop';
32
+ }
33
+ /** Strip a URL to its host. Returns null for empty / unparsable input. */
34
+ export function referrerHost(referrer) {
35
+ if (!referrer || referrer.length === 0)
36
+ return null;
37
+ try {
38
+ const url = new URL(referrer);
39
+ return url.host || null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ /** Drop query string + hash; keep pathname only. Cardinality-bounded. */
46
+ export function normalizePath(path) {
47
+ if (!path)
48
+ return '/';
49
+ try {
50
+ // URL parser is more permissive than splitting on '?' — handles cases like
51
+ // accidentally-included full URLs.
52
+ const url = new URL(path, 'http://_');
53
+ return url.pathname || '/';
54
+ }
55
+ catch {
56
+ // Manual split fallback for malformed strings.
57
+ const noQuery = path.split('?')[0];
58
+ const noHash = noQuery.split('#')[0];
59
+ return noHash || '/';
60
+ }
61
+ }
62
+ /** Truncate any free-text field to a safe upper bound. */
63
+ export function clip(s, max = 500) {
64
+ if (!s)
65
+ return null;
66
+ return s.length > max ? s.slice(0, max) : s;
67
+ }
68
+ /** ISO-3166-1 alpha-2 sanity check. Returns null for anything else. */
69
+ export function safeCountry(c) {
70
+ if (!c || c.length !== 2)
71
+ return null;
72
+ const up = c.toUpperCase();
73
+ return /^[A-Z]{2}$/.test(up) ? up : null;
74
+ }
75
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../../src/analytics/server/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;kEAEkE;AAClE,MAAM,MAAM,GAAG,gFAAgF,CAAA;AAE/F,MAAM,UAAU,cAAc,CAAC,EAA6B;IAC1D,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAA,CAAC,kCAAkC;IACvD,OAAO,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACxB,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,mBAAmB,CACjC,EAA6B;IAE7B,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAA;IACpB,8EAA8E;IAC9E,IAAI,+CAA+C,CAAC,IAAI,CAAC,EAAE,CAAC;QAAE,OAAO,QAAQ,CAAA;IAC7E,IAAI,6EAA6E,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QAC3F,OAAO,QAAQ,CAAA;IACjB,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,YAAY,CAAC,QAAmC;IAC9D,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACnD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAA;QAC7B,OAAO,GAAG,CAAC,IAAI,IAAI,IAAI,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAAC,IAA+B;IAC3D,IAAI,CAAC,IAAI;QAAE,OAAO,GAAG,CAAA;IACrB,IAAI,CAAC;QACH,2EAA2E;QAC3E,mCAAmC;QACnC,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAA;QACrC,OAAO,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;QAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QAClC,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;QACpC,OAAO,MAAM,IAAI,GAAG,CAAA;IACtB,CAAC;AACH,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,IAAI,CAAC,CAA4B,EAAE,GAAG,GAAG,GAAG;IAC1D,IAAI,CAAC,CAAC;QAAE,OAAO,IAAI,CAAA;IACnB,OAAO,CAAC,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC7C,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,WAAW,CAAC,CAA4B;IACtD,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IACrC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;IAC1B,OAAO,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AAC1C,CAAC"}
@@ -0,0 +1,74 @@
1
+ /**
2
+ * @rovela-ai/sdk/analytics/server/queries
3
+ *
4
+ * Per-store analytics read + write helpers. Reads from the store's own Neon
5
+ * branch via `getDb()` (no tenant filtering). Each read returns a typed
6
+ * payload ready for the dashboard.
7
+ *
8
+ * Writes are best-effort: `recordEvent` swallows failures so an analytics
9
+ * outage NEVER breaks customer flows (checkout, cart, browse). The endpoint
10
+ * + webhook callers rely on that contract.
11
+ */
12
+ import { type SdkDb } from '../../core/db/client';
13
+ import type { AnalyticsDashboardPayload, AnalyticsEventsLogPage, AnalyticsPeriod, AnalyticsSortDir, AnalyticsTrafficSummary, AnalyticsVisitorsPage, AnalyticsWireEvent } from '../types';
14
+ export declare function periodToDays(period: AnalyticsPeriod): number;
15
+ interface RecordEventInput {
16
+ event: AnalyticsWireEvent;
17
+ device: string | null;
18
+ country: string | null;
19
+ }
20
+ /**
21
+ * Insert a single event. Never throws — analytics MUST NEVER break the
22
+ * customer flow. The caller is the track endpoint OR the Stripe webhook
23
+ * wrapper; both have a "don't fail the user request on analytics failure"
24
+ * contract.
25
+ *
26
+ * For `purchase` / `refund` events, the partial unique index on `order_id`
27
+ * absorbs Stripe at-least-once webhook redelivery via ON CONFLICT.
28
+ */
29
+ export declare function recordEvent(input: RecordEventInput): Promise<void>;
30
+ /**
31
+ * Dashboard payload. Period-scoped current + prior windows for delta-vs-prior
32
+ * KPIs. All seven panels fan out in one Promise.all (~150ms warm Neon).
33
+ *
34
+ * @param db Optional Drizzle client. Default: `getDb()` (env DATABASE_URL).
35
+ * Platform-side passes `createDb(project.databaseUrl)` to read
36
+ * from a merchant's branch.
37
+ */
38
+ export declare function getAnalyticsDashboard(period: AnalyticsPeriod, db?: SdkDb): Promise<AnalyticsDashboardPayload>;
39
+ /**
40
+ * 7-day visitor + conversion summary for the Rovela platform's per-store
41
+ * Traffic card. Fast (3 small aggregates) — the platform fan-outs across
42
+ * every store the user can see, so we keep this tight.
43
+ */
44
+ export declare function getTrafficSummary7d(db?: SdkDb): Promise<AnalyticsTrafficSummary>;
45
+ /** Sort columns allowed on the events log. Tightly bounded — anything else
46
+ * is treated as the default 'ts'. */
47
+ type EventLogSortColumn = 'ts' | 'event' | 'path' | 'referrer' | 'country';
48
+ export interface GetEventsLogOptions {
49
+ period: AnalyticsPeriod;
50
+ /** Page cursor. Encoded as a stringified bigint (the previous page's last
51
+ * row id). null/undefined = first page. */
52
+ cursor?: string | null;
53
+ /** Page size. Default 50, capped at 200. */
54
+ limit?: number;
55
+ sortBy?: EventLogSortColumn;
56
+ sortDir?: AnalyticsSortDir;
57
+ /** When true, exclude `session_heartbeat` rows. Default false. The admin
58
+ * EventsView passes true by default with a toggle to flip. */
59
+ hideHeartbeats?: boolean;
60
+ }
61
+ export declare function getEventsLog(options: GetEventsLogOptions, db?: SdkDb): Promise<AnalyticsEventsLogPage>;
62
+ type VisitorSortColumn = 'last_seen' | 'first_seen' | 'sessions' | 'pageviews' | 'country';
63
+ export interface GetVisitorsListOptions {
64
+ period: AnalyticsPeriod;
65
+ /** Offset cursor (stringified integer). null/undefined = first page. */
66
+ cursor?: string | null;
67
+ /** Page size. Default 50, capped at 200. */
68
+ limit?: number;
69
+ sortBy?: VisitorSortColumn;
70
+ sortDir?: AnalyticsSortDir;
71
+ }
72
+ export declare function getVisitorsList(options: GetVisitorsListOptions, db?: SdkDb): Promise<AnalyticsVisitorsPage>;
73
+ export {};
74
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/analytics/server/queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAS,KAAK,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAExD,OAAO,KAAK,EACV,yBAAyB,EAGzB,sBAAsB,EAGtB,eAAe,EACf,gBAAgB,EAIhB,uBAAuB,EAGvB,qBAAqB,EACrB,kBAAkB,EACnB,MAAM,UAAU,CAAA;AAwBjB,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAE5D;AAWD,UAAU,gBAAgB;IACxB,KAAK,EAAE,kBAAkB,CAAA;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED;;;;;;;;GAQG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDxE;AA+JD;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,eAAe,EACvB,EAAE,CAAC,EAAE,KAAK,GACT,OAAO,CAAC,yBAAyB,CAAC,CAkDpC;AAMD;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,CAAC,EAAE,KAAK,GACT,OAAO,CAAC,uBAAuB,CAAC,CAoBlC;AAMD;sCACsC;AACtC,KAAK,kBAAkB,GAAG,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,CAAA;AAU1E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,eAAe,CAAA;IACvB;gDAC4C;IAC5C,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,kBAAkB,CAAA;IAC3B,OAAO,CAAC,EAAE,gBAAgB,CAAA;IAC1B;mEAC+D;IAC/D,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAmBD,wBAAsB,YAAY,CAChC,OAAO,EAAE,mBAAmB,EAC5B,EAAE,CAAC,EAAE,KAAK,GACT,OAAO,CAAC,sBAAsB,CAAC,CAiGjC;AAMD,KAAK,iBAAiB,GAClB,WAAW,GACX,YAAY,GACZ,UAAU,GACV,WAAW,GACX,SAAS,CAAA;AAUb,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,CAAA;IACvB,wEAAwE;IACxE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,4CAA4C;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,iBAAiB,CAAA;IAC1B,OAAO,CAAC,EAAE,gBAAgB,CAAA;CAC3B;AAmBD,wBAAsB,eAAe,CACnC,OAAO,EAAE,sBAAsB,EAC/B,EAAE,CAAC,EAAE,KAAK,GACT,OAAO,CAAC,qBAAqB,CAAC,CA4FhC"}