@octovise/react-native-sdk 1.0.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 (62) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/LICENSE +21 -0
  3. package/README.md +160 -0
  4. package/android/src/main/java/com/octovise/sdk/OctoFirebaseMessagingService.kt +72 -0
  5. package/android/src/main/java/com/octovise/sdk/OctoPushDismissReceiver.kt +54 -0
  6. package/android/src/main/java/com/octovise/sdk/OctoPushModule.kt +26 -0
  7. package/android/src/main/java/com/octovise/sdk/OctoPushNotificationBuilder.kt +142 -0
  8. package/dist/api.d.ts +38 -0
  9. package/dist/api.js +210 -0
  10. package/dist/carouselStart.d.ts +1 -0
  11. package/dist/carouselStart.js +6 -0
  12. package/dist/components/OctoErrorBoundary.d.ts +15 -0
  13. package/dist/components/OctoErrorBoundary.js +28 -0
  14. package/dist/components/OctoImage.d.ts +23 -0
  15. package/dist/components/OctoImage.js +69 -0
  16. package/dist/components/OctoMessage.d.ts +9 -0
  17. package/dist/components/OctoMessage.js +189 -0
  18. package/dist/components/OctoModal.d.ts +13 -0
  19. package/dist/components/OctoModal.js +179 -0
  20. package/dist/components/OctoProvider.d.ts +14 -0
  21. package/dist/components/OctoProvider.js +92 -0
  22. package/dist/components/OctoToast.d.ts +13 -0
  23. package/dist/components/OctoToast.js +392 -0
  24. package/dist/debug.d.ts +2 -0
  25. package/dist/debug.js +15 -0
  26. package/dist/imageFit.d.ts +8 -0
  27. package/dist/imageFit.js +31 -0
  28. package/dist/index.d.ts +11 -0
  29. package/dist/index.js +195 -0
  30. package/dist/latency.d.ts +17 -0
  31. package/dist/latency.js +11 -0
  32. package/dist/native.d.ts +1 -0
  33. package/dist/native.js +14 -0
  34. package/dist/navigation/reactNavigation.d.ts +12 -0
  35. package/dist/navigation/reactNavigation.js +24 -0
  36. package/dist/navigation/resolveCTA.d.ts +12 -0
  37. package/dist/navigation/resolveCTA.js +74 -0
  38. package/dist/push.d.ts +3 -0
  39. package/dist/push.js +129 -0
  40. package/dist/safeNavUrl.d.ts +2 -0
  41. package/dist/safeNavUrl.js +18 -0
  42. package/dist/screenStream.d.ts +17 -0
  43. package/dist/screenStream.js +126 -0
  44. package/dist/screenTargeting.d.ts +37 -0
  45. package/dist/screenTargeting.js +154 -0
  46. package/dist/session.d.ts +2 -0
  47. package/dist/session.js +22 -0
  48. package/dist/state.d.ts +8 -0
  49. package/dist/state.js +53 -0
  50. package/dist/telemetry.d.ts +6 -0
  51. package/dist/telemetry.js +65 -0
  52. package/dist/toastLayout.d.ts +2 -0
  53. package/dist/toastLayout.js +11 -0
  54. package/dist/types.d.ts +78 -0
  55. package/dist/types.js +7 -0
  56. package/dist/version.d.ts +1 -0
  57. package/dist/version.js +4 -0
  58. package/ios/OctoviseNotificationExtension/NotificationService.swift +128 -0
  59. package/ios/OctoviseSDK/OctoPushModule.m +6 -0
  60. package/ios/OctoviseSDK/OctoPushModule.swift +27 -0
  61. package/package.json +57 -0
  62. package/react-native.config.js +16 -0
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildLatencyBreakdown = buildLatencyBreakdown;
4
+ function buildLatencyBreakdown(t, m) {
5
+ return {
6
+ total_ms: m.impression - t.t0,
7
+ network_ms: t.tCheck - t.t0,
8
+ image_ms: m.hasImage ? Math.max(0, m.shown - m.showStart) : 0,
9
+ render_ms: Math.max(0, m.impression - m.shown),
10
+ };
11
+ }
@@ -0,0 +1 @@
1
+ export declare function configureNative(apiKey: string, userId: string, baseUrl: string): void;
package/dist/native.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.configureNative = configureNative;
4
+ const react_native_1 = require("react-native");
5
+ function configureNative(apiKey, userId, baseUrl) {
6
+ const mod = react_native_1.NativeModules['OctoPushModule'];
7
+ if (!mod || typeof mod.configure !== 'function')
8
+ return;
9
+ try {
10
+ mod.configure(apiKey, userId, baseUrl);
11
+ }
12
+ catch {
13
+ }
14
+ }
@@ -0,0 +1,12 @@
1
+ import type { NavAdapter } from '../types';
2
+ interface NavigationRefLike {
3
+ isReady?: () => boolean;
4
+ navigate: (name: string, params?: object) => void;
5
+ getCurrentRoute?: () => {
6
+ name?: string;
7
+ params?: Record<string, unknown>;
8
+ } | undefined;
9
+ addListener?: (type: string, callback: () => void) => () => void;
10
+ }
11
+ export declare function makeReactNavigationAdapter(navigationRef: NavigationRefLike): NavAdapter;
12
+ export {};
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.makeReactNavigationAdapter = makeReactNavigationAdapter;
4
+ function makeReactNavigationAdapter(navigationRef) {
5
+ return {
6
+ navigate(routeName, params) {
7
+ if (typeof navigationRef.isReady === 'function' && !navigationRef.isReady())
8
+ return;
9
+ navigationRef.navigate(routeName, params);
10
+ },
11
+ getCurrentScreen() {
12
+ return navigationRef.getCurrentRoute?.()?.name ?? null;
13
+ },
14
+ subscribeScreenChange(cb) {
15
+ if (typeof navigationRef.addListener !== 'function')
16
+ return () => { };
17
+ return navigationRef.addListener('state', () => {
18
+ const route = navigationRef.getCurrentRoute?.();
19
+ if (route?.name)
20
+ cb(route.name, route.params);
21
+ });
22
+ },
23
+ };
24
+ }
@@ -0,0 +1,12 @@
1
+ import type { NavAdapter } from '../types';
2
+ export interface ParsedOctoviseUrl {
3
+ routeName: string;
4
+ params: Record<string, string>;
5
+ }
6
+ export declare function parseOctoviseUrl(url: string): ParsedOctoviseUrl | null;
7
+ export interface CTAConfig {
8
+ nav?: NavAdapter;
9
+ onCTA?: (url: string) => void;
10
+ resolveRoute?: (routeToken: string) => string | null;
11
+ }
12
+ export declare function handleCTA(rawUrl: string | undefined | null, cfg: CTAConfig): void;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.parseOctoviseUrl = parseOctoviseUrl;
4
+ exports.handleCTA = handleCTA;
5
+ const safeNavUrl_1 = require("../safeNavUrl");
6
+ const SCHEME = 'octovise://';
7
+ function safeDecode(s) {
8
+ try {
9
+ return decodeURIComponent(s);
10
+ }
11
+ catch {
12
+ return s;
13
+ }
14
+ }
15
+ function parseOctoviseUrl(url) {
16
+ if (!url || !url.toLowerCase().startsWith(SCHEME))
17
+ return null;
18
+ let rest = url.slice(SCHEME.length);
19
+ let query = '';
20
+ const q = rest.indexOf('?');
21
+ if (q >= 0) {
22
+ query = rest.slice(q + 1);
23
+ rest = rest.slice(0, q);
24
+ }
25
+ let path = rest;
26
+ if (path.toLowerCase().startsWith('route/'))
27
+ path = path.slice('route/'.length);
28
+ const seg = path.split('/')[0];
29
+ if (!seg)
30
+ return null;
31
+ const params = {};
32
+ if (query) {
33
+ for (const pair of query.split('&')) {
34
+ if (!pair)
35
+ continue;
36
+ const eq = pair.indexOf('=');
37
+ const k = safeDecode(eq >= 0 ? pair.slice(0, eq) : pair);
38
+ const v = eq >= 0 ? safeDecode(pair.slice(eq + 1)) : '';
39
+ if (k)
40
+ params[k] = v;
41
+ }
42
+ }
43
+ return { routeName: safeDecode(seg), params };
44
+ }
45
+ function handleCTA(rawUrl, cfg) {
46
+ const safe = (0, safeNavUrl_1.safeNavUrl)(rawUrl);
47
+ if (!safe)
48
+ return;
49
+ const parsed = parseOctoviseUrl(safe);
50
+ if (parsed && cfg.nav) {
51
+ const screen = cfg.resolveRoute ? cfg.resolveRoute(parsed.routeName) : null;
52
+ if (screen) {
53
+ cfg.nav.navigate(screen, parsed.params);
54
+ return;
55
+ }
56
+ if (!/^\d+$/.test(parsed.routeName)) {
57
+ cfg.nav.navigate(parsed.routeName, parsed.params);
58
+ return;
59
+ }
60
+ }
61
+ if (cfg.onCTA) {
62
+ cfg.onCTA(safe);
63
+ return;
64
+ }
65
+ openExternal(safe);
66
+ }
67
+ function openExternal(url) {
68
+ try {
69
+ const { Linking } = require('react-native');
70
+ Linking.openURL(url).catch(() => { });
71
+ }
72
+ catch {
73
+ }
74
+ }
package/dist/push.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare function setupPush(): Promise<void>;
2
+ export declare function startPushListeners(onCTA?: (url: string) => void): void;
3
+ export declare function stopPushListeners(): void;
package/dist/push.js ADDED
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.setupPush = setupPush;
37
+ exports.startPushListeners = startPushListeners;
38
+ exports.stopPushListeners = stopPushListeners;
39
+ const react_native_1 = require("react-native");
40
+ const api = __importStar(require("./api"));
41
+ const types_1 = require("./types");
42
+ let messaging = null;
43
+ let unsubscribeOnMessage = null;
44
+ let unsubscribeOnOpen = null;
45
+ function getMessaging() {
46
+ if (!messaging) {
47
+ try {
48
+ messaging = require('@react-native-firebase/messaging').default;
49
+ }
50
+ catch {
51
+ console.warn('[OctoSDK] @react-native-firebase/messaging not installed. ' +
52
+ 'Push features require: npm install @react-native-firebase/messaging');
53
+ return null;
54
+ }
55
+ }
56
+ return messaging;
57
+ }
58
+ function isOctovise(data) {
59
+ return data?.source === 'octovise';
60
+ }
61
+ async function setupPush() {
62
+ const msg = getMessaging();
63
+ if (!msg)
64
+ return;
65
+ try {
66
+ const authStatus = await msg().requestPermission();
67
+ if (authStatus !== msg.AuthorizationStatus.AUTHORIZED &&
68
+ authStatus !== msg.AuthorizationStatus.PROVISIONAL) {
69
+ return;
70
+ }
71
+ const token = await msg().getToken();
72
+ if (token) {
73
+ await api.registerDevice(token);
74
+ }
75
+ msg().onTokenRefresh(async (newToken) => {
76
+ await api.registerDevice(newToken);
77
+ });
78
+ }
79
+ catch (err) {
80
+ console.warn('[OctoSDK] Push setup failed:', err);
81
+ }
82
+ }
83
+ function startPushListeners(onCTA) {
84
+ const msg = getMessaging();
85
+ if (!msg)
86
+ return;
87
+ unsubscribeOnMessage = msg().onMessage(async (remoteMessage) => {
88
+ if (!isOctovise(remoteMessage.data))
89
+ return;
90
+ const sendId = (0, types_1.parsePushSendId)(remoteMessage.data.send_id);
91
+ api.trackEvent(sendId, 'received', {
92
+ device: 'mobile',
93
+ platform: react_native_1.Platform.OS,
94
+ });
95
+ });
96
+ unsubscribeOnOpen = msg().onNotificationOpenedApp((remoteMessage) => {
97
+ if (!isOctovise(remoteMessage.data))
98
+ return;
99
+ const sendId = (0, types_1.parsePushSendId)(remoteMessage.data.send_id);
100
+ api.trackEvent(sendId, 'click', {
101
+ device: 'mobile',
102
+ platform: react_native_1.Platform.OS,
103
+ });
104
+ if (remoteMessage.data.deep_link && onCTA) {
105
+ onCTA(remoteMessage.data.deep_link);
106
+ }
107
+ });
108
+ msg()
109
+ .getInitialNotification()
110
+ .then((remoteMessage) => {
111
+ if (!remoteMessage || !isOctovise(remoteMessage.data))
112
+ return;
113
+ const sendId = (0, types_1.parsePushSendId)(remoteMessage.data.send_id);
114
+ api.trackEvent(sendId, 'click', {
115
+ device: 'mobile',
116
+ platform: react_native_1.Platform.OS,
117
+ });
118
+ if (remoteMessage.data.deep_link && onCTA) {
119
+ onCTA(remoteMessage.data.deep_link);
120
+ }
121
+ })
122
+ .catch(() => { });
123
+ }
124
+ function stopPushListeners() {
125
+ unsubscribeOnMessage?.();
126
+ unsubscribeOnOpen?.();
127
+ unsubscribeOnMessage = null;
128
+ unsubscribeOnOpen = null;
129
+ }
@@ -0,0 +1,2 @@
1
+ export declare function isUrlSafe(value: unknown): boolean;
2
+ export declare function safeNavUrl(value: unknown): string;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isUrlSafe = isUrlSafe;
4
+ exports.safeNavUrl = safeNavUrl;
5
+ const DANGEROUS_SCHEMES = /^\s*(javascript|vbscript|data):/i;
6
+ function isUrlSafe(value) {
7
+ if (value === null || value === undefined)
8
+ return false;
9
+ const s = String(value).trim();
10
+ if (s === '')
11
+ return false;
12
+ return !DANGEROUS_SCHEMES.test(s);
13
+ }
14
+ function safeNavUrl(value) {
15
+ if (!isUrlSafe(value))
16
+ return '';
17
+ return String(value).trim();
18
+ }
@@ -0,0 +1,17 @@
1
+ import type { ScreenViewWire } from './api';
2
+ export declare function record(screenName: string): void;
3
+ export declare function setEntity(entity: {
4
+ type?: string;
5
+ id?: number | string | null;
6
+ ref?: string | null;
7
+ } | null): void;
8
+ export declare function flush(): Promise<void>;
9
+ export declare function start(): void;
10
+ export declare function stop(): void;
11
+ export declare function __resetForTests(): void;
12
+ export declare function __getBuffer(): ScreenViewWire[];
13
+ export declare const __TEST_CONSTANTS: {
14
+ readonly FLUSH_INTERVAL_MS: 15000;
15
+ readonly FLUSH_SIZE: 20;
16
+ readonly MAX_BUFFER: 500;
17
+ };
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.__TEST_CONSTANTS = void 0;
37
+ exports.record = record;
38
+ exports.setEntity = setEntity;
39
+ exports.flush = flush;
40
+ exports.start = start;
41
+ exports.stop = stop;
42
+ exports.__resetForTests = __resetForTests;
43
+ exports.__getBuffer = __getBuffer;
44
+ const react_native_1 = require("react-native");
45
+ const api = __importStar(require("./api"));
46
+ const session = __importStar(require("./session"));
47
+ const screenTargeting = __importStar(require("./screenTargeting"));
48
+ const FLUSH_INTERVAL_MS = 15000;
49
+ const FLUSH_SIZE = 20;
50
+ const MAX_BUFFER = 500;
51
+ let buffer = [];
52
+ let timer = null;
53
+ let appStateSub = null;
54
+ let currentView = null;
55
+ function record(screenName) {
56
+ const payload = screenTargeting.buildScreenViewForName(screenName);
57
+ if (!payload) {
58
+ currentView = null;
59
+ return;
60
+ }
61
+ if (buffer.length >= MAX_BUFFER)
62
+ buffer.shift();
63
+ const view = {
64
+ ...payload,
65
+ session_id: session.currentSessionId(),
66
+ ts: new Date().toISOString(),
67
+ };
68
+ buffer.push(view);
69
+ currentView = view;
70
+ if (buffer.length >= FLUSH_SIZE)
71
+ void flush();
72
+ }
73
+ function setEntity(entity) {
74
+ if (!currentView)
75
+ return;
76
+ const norm = screenTargeting.normalizeEntity(entity);
77
+ currentView.entity_type = norm ? norm.entity_type : null;
78
+ currentView.entity_id = norm ? norm.entity_id : null;
79
+ currentView.reference = norm ? norm.reference : null;
80
+ }
81
+ async function flush() {
82
+ if (buffer.length === 0)
83
+ return;
84
+ const batch = buffer.splice(0, buffer.length);
85
+ currentView = null;
86
+ const ok = await api.trackScreenViews(batch);
87
+ if (!ok) {
88
+ buffer.unshift(...batch.slice(-MAX_BUFFER));
89
+ }
90
+ }
91
+ function start() {
92
+ if (timer)
93
+ return;
94
+ timer = setInterval(() => void flush(), FLUSH_INTERVAL_MS);
95
+ if (typeof timer.unref === 'function') {
96
+ timer.unref();
97
+ }
98
+ appStateSub = react_native_1.AppState.addEventListener('change', (next) => {
99
+ if (next !== 'active')
100
+ void flush();
101
+ });
102
+ }
103
+ function stop() {
104
+ if (timer) {
105
+ clearInterval(timer);
106
+ timer = null;
107
+ }
108
+ appStateSub?.remove();
109
+ appStateSub = null;
110
+ currentView = null;
111
+ void flush();
112
+ }
113
+ function __resetForTests() {
114
+ if (timer) {
115
+ clearInterval(timer);
116
+ timer = null;
117
+ }
118
+ appStateSub?.remove();
119
+ appStateSub = null;
120
+ buffer = [];
121
+ currentView = null;
122
+ }
123
+ function __getBuffer() {
124
+ return buffer;
125
+ }
126
+ exports.__TEST_CONSTANTS = { FLUSH_INTERVAL_MS, FLUSH_SIZE, MAX_BUFFER };
@@ -0,0 +1,37 @@
1
+ import type { RuleEntry } from './api';
2
+ export interface RouteEntry {
3
+ id: number;
4
+ name?: string;
5
+ device?: 'web' | 'mobile' | 'both';
6
+ mobile_screen?: string;
7
+ web_path?: string;
8
+ }
9
+ export declare function sync(): Promise<boolean>;
10
+ export declare function isSynced(): boolean;
11
+ export declare function getRoutes(): RouteEntry[];
12
+ export declare function getRules(): RuleEntry[];
13
+ export declare function resolveScreen(routeList: RouteEntry[], routeToken: string): string | null;
14
+ export declare function routeHasMobileDestination(routeList: RouteEntry[], url: string | undefined | null): boolean;
15
+ export declare function ctaHasMobileDestination(url: string | undefined | null): boolean;
16
+ export declare function matchRule(routeList: RouteEntry[], ruleList: RuleEntry[], screenName: string): RuleEntry | null;
17
+ export declare function routeForScreen(routeList: RouteEntry[], screenName: string): RouteEntry | null;
18
+ export interface ScreenViewPayload {
19
+ screen_id: number;
20
+ entity_type: string | null;
21
+ entity_id: number | null;
22
+ reference: string | null;
23
+ }
24
+ export declare function normalizeEntity(e: {
25
+ type?: string;
26
+ id?: number | string | null;
27
+ ref?: string | null;
28
+ } | null | undefined): {
29
+ entity_type: string;
30
+ entity_id: number | null;
31
+ reference: string | null;
32
+ } | null;
33
+ export declare function buildScreenView(routeList: RouteEntry[], screenName: string): ScreenViewPayload | null;
34
+ export declare function resolveScreenForRoute(routeToken: string): string | null;
35
+ export declare function matchRuleForScreen(screenName: string): RuleEntry | null;
36
+ export declare function buildScreenViewForName(screenName: string): ScreenViewPayload | null;
37
+ export declare function reset(): void;
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.sync = sync;
37
+ exports.isSynced = isSynced;
38
+ exports.getRoutes = getRoutes;
39
+ exports.getRules = getRules;
40
+ exports.resolveScreen = resolveScreen;
41
+ exports.routeHasMobileDestination = routeHasMobileDestination;
42
+ exports.ctaHasMobileDestination = ctaHasMobileDestination;
43
+ exports.matchRule = matchRule;
44
+ exports.routeForScreen = routeForScreen;
45
+ exports.normalizeEntity = normalizeEntity;
46
+ exports.buildScreenView = buildScreenView;
47
+ exports.resolveScreenForRoute = resolveScreenForRoute;
48
+ exports.matchRuleForScreen = matchRuleForScreen;
49
+ exports.buildScreenViewForName = buildScreenViewForName;
50
+ exports.reset = reset;
51
+ const api = __importStar(require("./api"));
52
+ const resolveCTA_1 = require("./navigation/resolveCTA");
53
+ const telemetry_1 = require("./telemetry");
54
+ let routes = [];
55
+ let rules = [];
56
+ let synced = false;
57
+ async function sync() {
58
+ const data = await api.fetchRules();
59
+ if (!data)
60
+ return false;
61
+ routes = Array.isArray(data.routes) ? data.routes : [];
62
+ rules = Array.isArray(data.rules) ? data.rules : [];
63
+ (0, telemetry_1.setMetricSampleDigits)(data.telemetry?.metric_sample_digits);
64
+ synced = true;
65
+ return true;
66
+ }
67
+ function isSynced() {
68
+ return synced;
69
+ }
70
+ function getRoutes() {
71
+ return routes;
72
+ }
73
+ function getRules() {
74
+ return rules;
75
+ }
76
+ function resolveScreen(routeList, routeToken) {
77
+ if (!routeToken)
78
+ return null;
79
+ const byId = routeList.find((r) => String(r.id) === String(routeToken));
80
+ if (byId?.mobile_screen)
81
+ return byId.mobile_screen;
82
+ const byName = routeList.find((r) => r.name != null && r.name === routeToken);
83
+ return byName?.mobile_screen ?? null;
84
+ }
85
+ function routeHasMobileDestination(routeList, url) {
86
+ if (!url)
87
+ return false;
88
+ const parsed = (0, resolveCTA_1.parseOctoviseUrl)(url);
89
+ if (!parsed)
90
+ return true;
91
+ if (resolveScreen(routeList, parsed.routeName))
92
+ return true;
93
+ if (!/^\d+$/.test(parsed.routeName))
94
+ return true;
95
+ return false;
96
+ }
97
+ function ctaHasMobileDestination(url) {
98
+ return routeHasMobileDestination(routes, url);
99
+ }
100
+ function matchRule(routeList, ruleList, screenName) {
101
+ if (!screenName)
102
+ return null;
103
+ const idsForScreen = new Set(routeList.filter((r) => r.mobile_screen === screenName).map((r) => Number(r.id)));
104
+ if (idsForScreen.size === 0)
105
+ return null;
106
+ for (const rule of ruleList) {
107
+ const ts = rule.target_screens;
108
+ if (!ts || ts.length === 0)
109
+ continue;
110
+ if (ts.some((id) => idsForScreen.has(Number(id))))
111
+ return rule;
112
+ }
113
+ return null;
114
+ }
115
+ function routeForScreen(routeList, screenName) {
116
+ if (!screenName)
117
+ return null;
118
+ return routeList.find((r) => r.mobile_screen === screenName) ?? null;
119
+ }
120
+ function normalizeEntity(e) {
121
+ if (!e || typeof e.type !== 'string' || e.type.trim() === '')
122
+ return null;
123
+ const n = e.id == null ? Number.NaN : Number(e.id);
124
+ const entity_id = Number.isInteger(n) && n > 0 ? n : null;
125
+ const reference = typeof e.ref === 'string' && e.ref.trim() !== '' ? e.ref.slice(0, 128) : null;
126
+ if (entity_id === null && reference === null)
127
+ return null;
128
+ return { entity_type: e.type, entity_id, reference };
129
+ }
130
+ function buildScreenView(routeList, screenName) {
131
+ const route = routeForScreen(routeList, screenName);
132
+ if (!route)
133
+ return null;
134
+ return {
135
+ screen_id: route.id,
136
+ entity_type: null,
137
+ entity_id: null,
138
+ reference: null,
139
+ };
140
+ }
141
+ function resolveScreenForRoute(routeToken) {
142
+ return resolveScreen(routes, routeToken);
143
+ }
144
+ function matchRuleForScreen(screenName) {
145
+ return matchRule(routes, rules, screenName);
146
+ }
147
+ function buildScreenViewForName(screenName) {
148
+ return buildScreenView(routes, screenName);
149
+ }
150
+ function reset() {
151
+ routes = [];
152
+ rules = [];
153
+ synced = false;
154
+ }
@@ -0,0 +1,2 @@
1
+ export declare function currentSessionId(): string;
2
+ export declare function reset(): void;
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.currentSessionId = currentSessionId;
4
+ exports.reset = reset;
5
+ const SESSION_GAP_MS = 30 * 60 * 1000;
6
+ let sessionId = null;
7
+ let lastActivityAt = 0;
8
+ function generateId() {
9
+ return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
10
+ }
11
+ function currentSessionId() {
12
+ const now = Date.now();
13
+ if (!sessionId || now - lastActivityAt > SESSION_GAP_MS) {
14
+ sessionId = generateId();
15
+ }
16
+ lastActivityAt = now;
17
+ return sessionId;
18
+ }
19
+ function reset() {
20
+ sessionId = null;
21
+ lastActivityAt = 0;
22
+ }
@@ -0,0 +1,8 @@
1
+ export declare function canInit(): boolean;
2
+ export declare function markInit(): void;
3
+ export declare function isDuplicate(messageId: string | undefined): boolean;
4
+ export declare function setCurrentMessage(messageId: string | undefined): void;
5
+ export declare function clearCurrentMessage(): void;
6
+ export declare function startForegroundListener(onForeground: () => void): void;
7
+ export declare function stopForegroundListener(): void;
8
+ export declare function reset(): void;