@rovela-ai/sdk 0.4.3 → 0.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.
- package/dist/admin/components/AdminNav.d.ts.map +1 -1
- package/dist/admin/components/AdminNav.js +10 -1
- package/dist/admin/components/AdminNav.js.map +1 -1
- package/dist/admin/components/ExampleContentBanner.js +2 -2
- package/dist/admin/components/ExampleContentBanner.js.map +1 -1
- package/dist/admin/components/SetupGuide.d.ts.map +1 -1
- package/dist/admin/components/SetupGuide.js +4 -4
- package/dist/admin/components/SetupGuide.js.map +1 -1
- package/dist/admin/components/index.d.ts +0 -1
- package/dist/admin/components/index.d.ts.map +1 -1
- package/dist/admin/components/index.js +0 -1
- package/dist/admin/components/index.js.map +1 -1
- package/dist/admin/index.d.ts +1 -1
- package/dist/admin/index.d.ts.map +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/styles/admin-theme.css +11 -0
- package/dist/analytics/api/dashboard.d.ts +16 -0
- package/dist/analytics/api/dashboard.d.ts.map +1 -0
- package/dist/analytics/api/dashboard.js +37 -0
- package/dist/analytics/api/dashboard.js.map +1 -0
- package/dist/analytics/api/events.d.ts +23 -0
- package/dist/analytics/api/events.d.ts.map +1 -0
- package/dist/analytics/api/events.js +55 -0
- package/dist/analytics/api/events.js.map +1 -0
- package/dist/analytics/api/index.d.ts +15 -0
- package/dist/analytics/api/index.d.ts.map +1 -0
- package/dist/analytics/api/index.js +15 -0
- package/dist/analytics/api/index.js.map +1 -0
- package/dist/analytics/api/track.d.ts +20 -0
- package/dist/analytics/api/track.d.ts.map +1 -0
- package/dist/analytics/api/track.js +233 -0
- package/dist/analytics/api/track.js.map +1 -0
- package/dist/analytics/api/visitors.d.ts +19 -0
- package/dist/analytics/api/visitors.d.ts.map +1 -0
- package/dist/analytics/api/visitors.js +49 -0
- package/dist/analytics/api/visitors.js.map +1 -0
- package/dist/analytics/client/tracker.d.ts +51 -0
- package/dist/analytics/client/tracker.d.ts.map +1 -0
- package/dist/analytics/client/tracker.js +208 -0
- package/dist/analytics/client/tracker.js.map +1 -0
- package/dist/analytics/components/AnalyticsDashboard.d.ts +2 -0
- package/dist/analytics/components/AnalyticsDashboard.d.ts.map +1 -0
- package/dist/analytics/components/AnalyticsDashboard.js +26 -0
- package/dist/analytics/components/AnalyticsDashboard.js.map +1 -0
- package/dist/analytics/components/AnalyticsPeriodContext.d.ts +13 -0
- package/dist/analytics/components/AnalyticsPeriodContext.d.ts.map +1 -0
- package/dist/analytics/components/AnalyticsPeriodContext.js +28 -0
- package/dist/analytics/components/AnalyticsPeriodContext.js.map +1 -0
- package/dist/analytics/components/AnalyticsProvider.d.ts +22 -0
- package/dist/analytics/components/AnalyticsProvider.d.ts.map +1 -0
- package/dist/analytics/components/AnalyticsProvider.js +152 -0
- package/dist/analytics/components/AnalyticsProvider.js.map +1 -0
- package/dist/analytics/components/AnalyticsTabNav.d.ts +17 -0
- package/dist/analytics/components/AnalyticsTabNav.d.ts.map +1 -0
- package/dist/analytics/components/AnalyticsTabNav.js +42 -0
- package/dist/analytics/components/AnalyticsTabNav.js.map +1 -0
- package/dist/analytics/hooks/useAnalytics.d.ts +9 -0
- package/dist/analytics/hooks/useAnalytics.d.ts.map +1 -0
- package/dist/analytics/hooks/useAnalytics.js +8 -0
- package/dist/analytics/hooks/useAnalytics.js.map +1 -0
- package/dist/analytics/hooks/useAnalyticsDashboard.d.ts +9 -0
- package/dist/analytics/hooks/useAnalyticsDashboard.d.ts.map +1 -0
- package/dist/analytics/hooks/useAnalyticsDashboard.js +45 -0
- package/dist/analytics/hooks/useAnalyticsDashboard.js.map +1 -0
- package/dist/analytics/hooks/useEventsLog.d.ts +24 -0
- package/dist/analytics/hooks/useEventsLog.d.ts.map +1 -0
- package/dist/analytics/hooks/useEventsLog.js +81 -0
- package/dist/analytics/hooks/useEventsLog.js.map +1 -0
- package/dist/analytics/hooks/useVisitorsList.d.ts +20 -0
- package/dist/analytics/hooks/useVisitorsList.d.ts.map +1 -0
- package/dist/analytics/hooks/useVisitorsList.js +69 -0
- package/dist/analytics/hooks/useVisitorsList.js.map +1 -0
- package/dist/analytics/index.d.ts +44 -0
- package/dist/analytics/index.d.ts.map +1 -0
- package/dist/analytics/index.js +39 -0
- package/dist/analytics/index.js.map +1 -0
- package/dist/analytics/server/index.d.ts +10 -0
- package/dist/analytics/server/index.d.ts.map +1 -0
- package/dist/analytics/server/index.js +9 -0
- package/dist/analytics/server/index.js.map +1 -0
- package/dist/analytics/server/normalize.d.ts +23 -0
- package/dist/analytics/server/normalize.d.ts.map +1 -0
- package/dist/analytics/server/normalize.js +75 -0
- package/dist/analytics/server/normalize.js.map +1 -0
- package/dist/analytics/server/queries.d.ts +74 -0
- package/dist/analytics/server/queries.d.ts.map +1 -0
- package/dist/analytics/server/queries.js +470 -0
- package/dist/analytics/server/queries.js.map +1 -0
- package/dist/analytics/types.d.ts +186 -0
- package/dist/analytics/types.d.ts.map +1 -0
- package/dist/analytics/types.js +16 -0
- package/dist/analytics/types.js.map +1 -0
- package/dist/analytics/views/DashboardsView.d.ts +6 -0
- package/dist/analytics/views/DashboardsView.d.ts.map +1 -0
- package/dist/analytics/views/DashboardsView.js +93 -0
- package/dist/analytics/views/DashboardsView.js.map +1 -0
- package/dist/analytics/views/EventsView.d.ts +6 -0
- package/dist/analytics/views/EventsView.d.ts.map +1 -0
- package/dist/analytics/views/EventsView.js +85 -0
- package/dist/analytics/views/EventsView.js.map +1 -0
- package/dist/analytics/views/VisitorsView.d.ts +6 -0
- package/dist/analytics/views/VisitorsView.d.ts.map +1 -0
- package/dist/analytics/views/VisitorsView.js +57 -0
- package/dist/analytics/views/VisitorsView.js.map +1 -0
- package/dist/cart/store.d.ts.map +1 -1
- package/dist/cart/store.js +12 -0
- package/dist/cart/store.js.map +1 -1
- package/dist/checkout/components/CheckoutFlow.d.ts.map +1 -1
- package/dist/checkout/components/CheckoutFlow.js +26 -2
- package/dist/checkout/components/CheckoutFlow.js.map +1 -1
- package/dist/checkout/components/ShippingForm.js +10 -5
- package/dist/checkout/components/ShippingForm.js.map +1 -1
- package/dist/checkout/hooks/useCheckout.d.ts.map +1 -1
- package/dist/checkout/hooks/useCheckout.js +12 -1
- package/dist/checkout/hooks/useCheckout.js.map +1 -1
- package/dist/checkout/server/handle-webhook.js +15 -0
- package/dist/checkout/server/handle-webhook.js.map +1 -1
- package/dist/checkout/types.d.ts +13 -0
- package/dist/checkout/types.d.ts.map +1 -1
- package/dist/core/db/client.d.ts +14 -0
- package/dist/core/db/client.d.ts.map +1 -1
- package/dist/core/db/client.js +12 -0
- package/dist/core/db/client.js.map +1 -1
- package/dist/core/db/index.d.ts +2 -1
- package/dist/core/db/index.d.ts.map +1 -1
- package/dist/core/db/index.js +1 -1
- package/dist/core/db/index.js.map +1 -1
- package/dist/core/db/queries.d.ts +8 -7
- package/dist/core/db/queries.d.ts.map +1 -1
- package/dist/core/db/queries.js +80 -0
- package/dist/core/db/queries.js.map +1 -1
- package/dist/core/db/schema.d.ts +340 -4
- package/dist/core/db/schema.d.ts.map +1 -1
- package/dist/core/db/schema.js +55 -1
- package/dist/core/db/schema.js.map +1 -1
- package/dist/core/server/index.d.ts +2 -2
- package/dist/core/server/index.d.ts.map +1 -1
- package/dist/core/server/index.js +2 -0
- package/dist/core/server/index.js.map +1 -1
- 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"}
|