@tolinku/react-native-sdk 0.1.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/debug.ts","../src/client.ts","../src/validation.ts","../src/analytics.ts","../src/referrals.ts","../src/deferred.ts","../src/storage.ts","../src/Tolinku.ts","../src/messages/components.tsx","../src/messages/MessageModal.tsx","../src/messages/MessageProvider.tsx"],"names":["jsx","TouchableOpacity","Text"],"mappings":"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","file":"index.mjs","sourcesContent":["/** SDK version */\nexport const SDK_VERSION = '0.1.0';\n\n/** Configuration options for the Tolinku SDK */\nexport interface TolinkuConfig {\n /** Your Tolinku publishable API key (starts with tolk_pub_) */\n apiKey: string;\n /** Base URL of your Tolinku domain. Defaults to https://api.tolinku.com */\n baseUrl?: string;\n /** Enable debug logging to the console. Defaults to false. */\n debug?: boolean;\n /** Request timeout in milliseconds. Defaults to 30000 (30 seconds). */\n timeout?: number;\n}\n\n/** Resolved configuration with all defaults applied */\nexport interface ResolvedTolinkuConfig {\n apiKey: string;\n baseUrl: string;\n debug: boolean;\n timeout: number;\n}\n\n/** Properties for custom event tracking */\nexport interface TrackProperties {\n campaign?: string;\n source?: string;\n medium?: string;\n platform?: string;\n [key: string]: string | undefined;\n}\n\n/** Options for creating a referral */\nexport interface CreateReferralOptions {\n userId: string;\n metadata?: Record<string, string>;\n userName?: string;\n}\n\n/** Response from creating a referral */\nexport interface CreateReferralResult {\n referral_code: string;\n referral_url: string | null;\n referral_id: string;\n}\n\n/** Options for completing a referral */\nexport interface CompleteReferralOptions {\n code: string;\n referredUserId: string;\n milestone?: string;\n referredUserName?: string;\n}\n\n/** Response from completing a referral */\nexport interface CompleteReferralResult {\n referral: {\n id: string;\n referrer_id: string;\n referred_user_id: string;\n status: string;\n milestone: string;\n completed_at: string;\n reward_type: string | null;\n reward_value: string | null;\n };\n}\n\n/** Options for updating a referral milestone */\nexport interface MilestoneOptions {\n code: string;\n milestone: string;\n}\n\n/** Response from updating a milestone */\nexport interface MilestoneResult {\n referral: {\n id: string;\n referral_code: string;\n milestone: string;\n status: string;\n reward_type: string | null;\n reward_value: string | null;\n };\n}\n\n/** Referral info returned by GET /api/referral/:code */\nexport interface ReferralInfo {\n referrer_id: string;\n status: string;\n milestone: string;\n milestone_history: Array<{ milestone: string; timestamp: string }>;\n reward_type: string | null;\n reward_value: string | null;\n reward_claimed: boolean;\n created_at: string;\n}\n\n/** Leaderboard entry */\nexport interface LeaderboardEntry {\n referrer_id: string;\n referrer_name: string | null;\n total: number;\n completed: number;\n pending: number;\n total_reward_value: string | null;\n}\n\n/** Deferred deep link result */\nexport interface DeferredLink {\n deep_link_path: string;\n appspace_id: string;\n referrer_id?: string;\n referral_code?: string;\n}\n\n/** Options for claiming deferred link by signals */\nexport interface ClaimBySignalsOptions {\n appspaceId: string;\n timezone?: string;\n language?: string;\n screenWidth?: number;\n screenHeight?: number;\n}\n\n/** In-app message from the API */\nexport interface Message {\n id: string;\n name: string;\n title: string;\n body: string | null;\n trigger: string;\n trigger_value: string | null;\n content: MessageContent | null;\n background_color: string;\n priority: number;\n dismiss_days: number | null;\n max_impressions: number | null;\n min_interval_hours: number | null;\n}\n\n/** Puck component content tree */\nexport interface MessageContent {\n root: { props: Record<string, unknown> };\n content: MessageComponent[];\n}\n\n/** A single Puck component */\nexport interface MessageComponent {\n type: string;\n props: Record<string, unknown>;\n}\n\n/** Options for showing an in-app message */\nexport interface ShowMessageOptions {\n trigger?: string;\n triggerValue?: string;\n onDismiss?: (messageId: string) => void;\n onButtonPress?: (action: string, messageId: string) => void;\n}\n","/** Global debug flag, controlled by Tolinku.init({ debug: true }) */\nlet _debugEnabled = false;\n\nexport function setDebugEnabled(enabled: boolean): void {\n _debugEnabled = enabled;\n}\n\nexport function isDebugEnabled(): boolean {\n return _debugEnabled;\n}\n\n/** Log a message to the console if debug mode is enabled. */\nexport function debugLog(message: string): void {\n if (_debugEnabled) {\n console.log(`[TolinkuSDK] ${message}`);\n }\n}\n\n/** Log a warning to the console if debug mode is enabled. */\nexport function debugWarn(message: string): void {\n if (_debugEnabled) {\n console.warn(`[TolinkuSDK] ${message}`);\n }\n}\n","import type { ResolvedTolinkuConfig } from './types';\nimport { SDK_VERSION } from './types';\nimport { debugLog } from './debug';\n\n/** Maximum number of retry attempts after the initial request. */\nconst MAX_RETRIES = 3;\n/** Base delay in milliseconds before the first retry. */\nconst BASE_DELAY_MS = 500;\n/** Maximum random jitter added to each retry delay, in milliseconds. */\nconst MAX_JITTER_MS = 250;\n\nexport class HttpClient {\n private baseUrl: string;\n private apiKey: string;\n private timeout: number;\n\n /** Set of AbortControllers for in-flight requests. Used by destroy() to cancel all. */\n private pendingControllers: Set<AbortController> = new Set();\n private destroyed = false;\n\n constructor(config: ResolvedTolinkuConfig) {\n this.baseUrl = config.baseUrl.replace(/\\/+$/, '');\n this.apiKey = config.apiKey;\n this.timeout = config.timeout;\n }\n\n async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n let url = this.baseUrl + path;\n if (params) {\n const qs = new URLSearchParams(params).toString();\n if (qs) url += '?' + qs;\n }\n\n return this.executeWithRetry<T>(url, {\n method: 'GET',\n headers: this.authenticatedHeaders(),\n });\n }\n\n async post<T>(path: string, body?: Record<string, unknown>): Promise<T> {\n return this.executeWithRetry<T>(this.baseUrl + path, {\n method: 'POST',\n headers: {\n ...this.authenticatedHeaders(),\n 'Content-Type': 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n /** GET without API key auth (for public endpoints like deferred claim) */\n async getPublic<T>(path: string, params?: Record<string, string>): Promise<T> {\n let url = this.baseUrl + path;\n if (params) {\n const qs = new URLSearchParams(params).toString();\n if (qs) url += '?' + qs;\n }\n\n return this.executeWithRetry<T>(url, {\n method: 'GET',\n headers: this.publicHeaders(),\n });\n }\n\n /** POST without API key auth (for public endpoints like deferred claim) */\n async postPublic<T>(path: string, body?: Record<string, unknown>): Promise<T> {\n return this.executeWithRetry<T>(this.baseUrl + path, {\n method: 'POST',\n headers: {\n ...this.publicHeaders(),\n 'Content-Type': 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n }\n\n /**\n * Abort all in-flight requests and mark the client as destroyed.\n * After calling this, all future requests will throw immediately.\n */\n abort(): void {\n this.destroyed = true;\n for (const controller of this.pendingControllers) {\n controller.abort();\n }\n this.pendingControllers.clear();\n }\n\n private authenticatedHeaders(): Record<string, string> {\n return {\n 'X-API-Key': this.apiKey,\n 'Accept': 'application/json',\n 'User-Agent': `TolinkuReactNativeSDK/${SDK_VERSION}`,\n };\n }\n\n private publicHeaders(): Record<string, string> {\n return {\n 'Accept': 'application/json',\n 'User-Agent': `TolinkuReactNativeSDK/${SDK_VERSION}`,\n };\n }\n\n /**\n * Execute a fetch request with retry logic. Retries on:\n * - Network errors (fetch throws)\n * - HTTP 429 (Too Many Requests), respecting the Retry-After header\n * - HTTP 5xx (server errors)\n *\n * Does NOT retry on 4xx errors (except 429).\n * Uses exponential backoff: BASE_DELAY_MS * 2^attempt + random jitter (0..MAX_JITTER_MS).\n */\n private async executeWithRetry<T>(\n url: string,\n init: RequestInit\n ): Promise<T> {\n if (this.destroyed) {\n throw new TolinkuError('Tolinku: client has been destroyed. Call Tolinku.init() to reinitialize.', 0);\n }\n\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {\n const controller = new AbortController();\n this.pendingControllers.add(controller);\n\n // Set up timeout\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const res = await fetch(url, {\n ...init,\n signal: controller.signal,\n });\n\n clearTimeout(timeoutId);\n this.pendingControllers.delete(controller);\n\n if (res.ok) {\n return res.json();\n }\n\n // Parse error body\n const errorBody = await res.json().catch(() => ({ error: res.statusText }));\n const errorMessage = errorBody.error || res.statusText;\n const errorCode = errorBody.code;\n\n // Determine if we should retry\n const isRetryable = res.status === 429 || (res.status >= 500 && res.status < 600);\n\n if (!isRetryable || attempt === MAX_RETRIES) {\n throw new TolinkuError(errorMessage, res.status, errorCode);\n }\n\n lastError = new TolinkuError(errorMessage, res.status, errorCode);\n\n // Calculate delay: respect Retry-After for 429, otherwise exponential backoff\n let delayMs: number;\n if (res.status === 429) {\n const retryAfter = res.headers.get('Retry-After');\n const retryAfterSeconds = retryAfter ? parseInt(retryAfter, 10) : NaN;\n if (!isNaN(retryAfterSeconds) && retryAfterSeconds > 0) {\n delayMs = retryAfterSeconds * 1000;\n } else {\n delayMs = BASE_DELAY_MS * Math.pow(2, attempt);\n }\n } else {\n delayMs = BASE_DELAY_MS * Math.pow(2, attempt);\n }\n\n const jitter = Math.random() * MAX_JITTER_MS;\n const totalDelay = delayMs + jitter;\n\n debugLog(`Retry ${attempt + 1}/${MAX_RETRIES} after ${Math.round(totalDelay)}ms (status=${res.status})`);\n\n await sleep(totalDelay);\n } catch (err) {\n clearTimeout(timeoutId);\n this.pendingControllers.delete(controller);\n\n // If the client was destroyed, rethrow immediately\n if (this.destroyed) {\n throw new TolinkuError('Tolinku: request aborted (client destroyed).', 0);\n }\n\n // AbortController timeout\n if (err instanceof DOMException && err.name === 'AbortError') {\n const timeoutErr = new TolinkuError(`Tolinku: request timed out after ${this.timeout}ms`, 0);\n if (attempt === MAX_RETRIES) throw timeoutErr;\n lastError = timeoutErr;\n } else if (err instanceof TolinkuError) {\n // Already a TolinkuError (from the non-retryable branch above); rethrow\n throw err;\n } else {\n // Network error; retry\n if (attempt === MAX_RETRIES) {\n throw new TolinkuError(\n `Tolinku: network error after ${MAX_RETRIES + 1} attempts: ${(err as Error).message}`,\n 0\n );\n }\n lastError = err as Error;\n }\n\n const delayMs = BASE_DELAY_MS * Math.pow(2, attempt);\n const jitter = Math.random() * MAX_JITTER_MS;\n const totalDelay = delayMs + jitter;\n\n debugLog(`Retry ${attempt + 1}/${MAX_RETRIES} after ${Math.round(totalDelay)}ms (${(err as Error).message})`);\n\n await sleep(totalDelay);\n }\n }\n\n // Should not reach here, but just in case\n throw lastError || new TolinkuError('Tolinku: request failed after retries', 0);\n }\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport class TolinkuError extends Error {\n status: number;\n code: string | undefined;\n\n constructor(message: string, status: number, code?: string) {\n super(message);\n this.name = 'TolinkuError';\n this.status = status;\n this.code = code;\n }\n}\n","/**\n * Check if a URL is safe to open or render. Only allows http: and https: protocols.\n * Blocks javascript:, data:, file:, and other potentially dangerous protocols.\n */\nexport function isSafeUrl(url: string): boolean {\n if (!url || typeof url !== 'string') return false;\n\n // Trim whitespace to prevent bypass via leading spaces\n const trimmed = url.trim();\n if (!trimmed) return false;\n\n try {\n const parsed = new URL(trimmed);\n return parsed.protocol === 'http:' || parsed.protocol === 'https:';\n } catch {\n // If URL cannot be parsed, it's not safe to open\n return false;\n }\n}\n\n/**\n * Validate that a base URL uses HTTPS, with exceptions for local development.\n * Throws an error if the URL is invalid.\n */\nexport function validateBaseUrl(baseUrl: string): void {\n if (!baseUrl || typeof baseUrl !== 'string') {\n throw new Error('Tolinku: baseUrl must be a non-empty string.');\n }\n\n const trimmed = baseUrl.trim();\n\n // Allow local development URLs over HTTP\n const isLocalDev =\n trimmed.startsWith('http://localhost') ||\n trimmed.startsWith('http://127.0.0.1') ||\n trimmed.startsWith('http://10.') ||\n /^http:\\/\\/172\\.(1[6-9]|2\\d|3[01])\\./.test(trimmed) ||\n trimmed.startsWith('http://192.168.');\n\n if (trimmed.startsWith('https://')) {\n return; // Valid HTTPS URL\n }\n\n if (isLocalDev) {\n return; // Valid local development URL\n }\n\n throw new Error(\n 'Tolinku: baseUrl must use HTTPS to protect your API key. Use https:// instead of http://. ' +\n 'Local development URLs (localhost, 127.0.0.1, 10.x, 172.16-31.x, 192.168.x) are exempt from this requirement.'\n );\n}\n\n/** Regex for valid custom event names (after the \"custom.\" prefix) */\nconst EVENT_NAME_REGEX = /^custom\\.[a-z0-9_]+$/;\n\n/**\n * Validate and normalize an event type name.\n * Auto-prefixes with \"custom.\" if missing.\n * Throws a descriptive error if the name is invalid.\n */\nexport function validateEventType(eventType: string): string {\n if (!eventType || typeof eventType !== 'string' || !eventType.trim()) {\n throw new Error('Tolinku: eventType must be a non-empty string.');\n }\n\n let normalized = eventType.trim();\n\n // Auto-prefix with \"custom.\" if not present\n if (!normalized.startsWith('custom.')) {\n normalized = 'custom.' + normalized;\n }\n\n if (!EVENT_NAME_REGEX.test(normalized)) {\n throw new Error(\n `Tolinku: invalid event type \"${normalized}\". ` +\n 'Event names must match the pattern \"custom.[a-z0-9_]+\". ' +\n 'Use only lowercase letters, digits, and underscores after the \"custom.\" prefix.'\n );\n }\n\n return normalized;\n}\n","import { AppState, type AppStateStatus, type NativeEventSubscription } from 'react-native';\nimport type { HttpClient } from './client';\nimport type { TrackProperties } from './types';\nimport { validateEventType } from './validation';\nimport { debugLog, debugWarn } from './debug';\n\n/** Number of events that triggers an automatic flush. */\nconst BATCH_SIZE = 10;\n/** Maximum time (ms) to wait before flushing after the first queued event. */\nconst FLUSH_INTERVAL_MS = 5000;\n/** Maximum number of events to keep in the queue to prevent unbounded growth. */\nconst MAX_QUEUE_SIZE = 1000;\n\ninterface QueuedEvent {\n event_type: string;\n properties: TrackProperties;\n}\n\nexport class Analytics {\n private client: HttpClient;\n private queue: QueuedEvent[] = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private appStateSubscription: NativeEventSubscription | null = null;\n private isFlushing = false;\n\n constructor(client: HttpClient) {\n this.client = client;\n\n // Listen for app going to background to flush events\n this.appStateSubscription = AppState.addEventListener(\n 'change',\n this.handleAppStateChange\n );\n }\n\n /**\n * Track a custom event. The event is added to the internal queue\n * and will be flushed automatically or when flush() is called.\n *\n * Event type must match /^custom\\.[a-z0-9_]+$/.\n * Auto-prefixes with \"custom.\" if missing.\n */\n async track(eventType: string, properties?: TrackProperties): Promise<void> {\n const normalizedType = validateEventType(eventType);\n\n const event: QueuedEvent = {\n event_type: normalizedType,\n properties: properties || {},\n };\n\n // Enforce max queue size\n if (this.queue.length >= MAX_QUEUE_SIZE) {\n debugWarn(\n `Analytics queue is full (${MAX_QUEUE_SIZE} events). Dropping oldest event to make room.`\n );\n this.queue.shift();\n }\n\n this.queue.push(event);\n\n if (this.queue.length >= BATCH_SIZE) {\n await this.flush();\n } else if (this.queue.length === 1) {\n // First event in the queue; start the flush timer\n this.startFlushTimer();\n }\n }\n\n /**\n * Immediately flush all queued events to the server.\n * If the queue is empty, this is a no-op.\n * If a flush is already in progress, this is a no-op to prevent race conditions.\n */\n async flush(): Promise<void> {\n if (this.queue.length === 0 || this.isFlushing) return;\n\n this.isFlushing = true;\n\n // Take a snapshot and clear the queue\n const eventsToSend = this.queue.splice(0, this.queue.length);\n this.cancelFlushTimer();\n\n try {\n debugLog(`Flushing ${eventsToSend.length} analytics event(s)`);\n const result = await this.client.post<{ ok: boolean; accepted?: number; errors?: string[] }>('/v1/api/analytics/batch', {\n events: eventsToSend,\n });\n if (result.errors && result.errors.length > 0) {\n debugWarn(`Batch partial failure: ${result.errors.join(', ')}`);\n }\n } catch (err) {\n debugWarn(`Failed to flush analytics events: ${(err as Error).message}`);\n // Re-enqueue events at the front (up to MAX_QUEUE_SIZE)\n const spaceLeft = MAX_QUEUE_SIZE - this.queue.length;\n if (spaceLeft > 0) {\n this.queue.unshift(...eventsToSend.slice(0, spaceLeft));\n }\n } finally {\n this.isFlushing = false;\n }\n }\n\n /**\n * Shut down the analytics module: flush remaining events, cancel the timer,\n * and remove the AppState listener.\n */\n async destroy(): Promise<void> {\n this.cancelFlushTimer();\n this.appStateSubscription?.remove();\n this.appStateSubscription = null;\n\n try {\n await this.flush();\n } catch {\n // Best-effort flush during shutdown\n }\n }\n\n private handleAppStateChange = (state: AppStateStatus): void => {\n if (state === 'background' || state === 'inactive') {\n // Fire-and-forget flush when going to background\n this.flush().catch(() => {});\n }\n };\n\n private startFlushTimer(): void {\n this.cancelFlushTimer();\n this.flushTimer = setTimeout(() => {\n this.flush().catch((err) => {\n debugWarn(`Timer flush failed: ${(err as Error).message}`);\n });\n }, FLUSH_INTERVAL_MS);\n }\n\n private cancelFlushTimer(): void {\n if (this.flushTimer !== null) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n }\n}\n","import type { HttpClient } from './client';\nimport type {\n CreateReferralOptions,\n CreateReferralResult,\n CompleteReferralOptions,\n CompleteReferralResult,\n MilestoneOptions,\n MilestoneResult,\n ReferralInfo,\n LeaderboardEntry,\n} from './types';\n\nexport class Referrals {\n constructor(private client: HttpClient) {}\n\n /** Create a new referral for a user */\n async create(options: CreateReferralOptions): Promise<CreateReferralResult> {\n if (!options.userId || !options.userId.trim()) {\n throw new Error('Tolinku: userId is required and must not be blank.');\n }\n\n return this.client.post('/v1/api/referral/create', {\n user_id: options.userId,\n metadata: options.metadata,\n user_name: options.userName,\n });\n }\n\n /** Get referral info by code */\n async get(code: string): Promise<ReferralInfo> {\n if (!code || !code.trim()) {\n throw new Error('Tolinku: referral code is required and must not be blank.');\n }\n\n return this.client.get(`/v1/api/referral/${encodeURIComponent(code)}`);\n }\n\n /** Complete a referral (mark as converted) */\n async complete(options: CompleteReferralOptions): Promise<CompleteReferralResult> {\n if (!options.code || !options.code.trim()) {\n throw new Error('Tolinku: referral code is required and must not be blank.');\n }\n if (!options.referredUserId || !options.referredUserId.trim()) {\n throw new Error('Tolinku: referredUserId is required and must not be blank.');\n }\n\n return this.client.post('/v1/api/referral/complete', {\n referral_code: options.code,\n referred_user_id: options.referredUserId,\n milestone: options.milestone,\n referred_user_name: options.referredUserName,\n });\n }\n\n /** Update a referral milestone */\n async milestone(options: MilestoneOptions): Promise<MilestoneResult> {\n if (!options.code || !options.code.trim()) {\n throw new Error('Tolinku: referral code is required and must not be blank.');\n }\n if (!options.milestone || !options.milestone.trim()) {\n throw new Error('Tolinku: milestone is required and must not be blank.');\n }\n\n return this.client.post('/v1/api/referral/milestone', {\n referral_code: options.code,\n milestone: options.milestone,\n });\n }\n\n /** Claim a referral reward */\n async claimReward(code: string): Promise<{ success: boolean; referral_code: string; reward_claimed: boolean }> {\n if (!code || !code.trim()) {\n throw new Error('Tolinku: referral code is required and must not be blank.');\n }\n\n return this.client.post('/v1/api/referral/claim-reward', {\n referral_code: code,\n });\n }\n\n /** Get the referral leaderboard */\n async leaderboard(limit: number = 25): Promise<{ leaderboard: LeaderboardEntry[] }> {\n return this.client.get('/v1/api/referral/leaderboard', {\n limit: String(limit),\n });\n }\n}\n","import { Dimensions } from 'react-native';\nimport type { HttpClient } from './client';\nimport type { DeferredLink, ClaimBySignalsOptions } from './types';\nimport { debugWarn } from './debug';\n\nexport class Deferred {\n constructor(private client: HttpClient) {}\n\n /** Claim a deferred deep link by referrer token (from Play Store referrer or clipboard) */\n async claimByToken(token: string): Promise<DeferredLink | null> {\n if (!token || !token.trim()) {\n throw new Error('Tolinku: token is required and must not be blank for claimByToken.');\n }\n\n try {\n return await this.client.getPublic<DeferredLink>('/v1/api/deferred/claim', { token });\n } catch (err) {\n debugWarn(`Deferred claimByToken failed: ${(err as Error).message}`);\n return null;\n }\n }\n\n /** Claim a deferred deep link by device signal matching */\n async claimBySignals(options: ClaimBySignalsOptions): Promise<DeferredLink | null> {\n if (!options.appspaceId || !options.appspaceId.trim()) {\n throw new Error('Tolinku: appspaceId is required and must not be blank for claimBySignals.');\n }\n\n try {\n const { width, height } = Dimensions.get('screen');\n const resolvedTimezone = options.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone;\n // React Native does not expose navigator.language in all environments,\n // so allow it to be passed explicitly or fall back to a sensible default.\n const resolvedLanguage = options.language || 'en';\n\n return await this.client.postPublic<DeferredLink>('/v1/api/deferred/claim-by-signals', {\n appspace_id: options.appspaceId,\n timezone: resolvedTimezone,\n language: resolvedLanguage,\n screen_width: options.screenWidth || width,\n screen_height: options.screenHeight || height,\n });\n } catch (err) {\n debugWarn(`Deferred claimBySignals failed: ${(err as Error).message}`);\n return null;\n }\n }\n}\n","import AsyncStorage from '@react-native-async-storage/async-storage';\n\nconst BASE_KEY = 'tolinku_message_dismissed';\nconst IMPRESSIONS_BASE_KEY = 'tolinku_message_impressions';\nconst LAST_SHOWN_BASE_KEY = 'tolinku_message_last_shown';\n\n/** Current namespace prefix, set when the SDK is initialized. */\nlet keyPrefix = BASE_KEY;\nlet impressionsKeyPrefix = IMPRESSIONS_BASE_KEY;\nlet lastShownKeyPrefix = LAST_SHOWN_BASE_KEY;\n\n/**\n * Set the storage namespace based on the API key.\n * This prevents collisions when the same app uses multiple Appspaces.\n * Uses a simple hash of the API key to keep storage keys short.\n */\nexport function setStorageNamespace(apiKey: string): void {\n const hash = simpleHash(apiKey);\n keyPrefix = `tolinku_${hash}_message_dismissed`;\n impressionsKeyPrefix = `tolinku_${hash}_message_impressions`;\n lastShownKeyPrefix = `tolinku_${hash}_message_last_shown`;\n}\n\n/** Reset to the default (un-namespaced) key. Used during destroy(). */\nexport function resetStorageNamespace(): void {\n keyPrefix = BASE_KEY;\n impressionsKeyPrefix = IMPRESSIONS_BASE_KEY;\n lastShownKeyPrefix = LAST_SHOWN_BASE_KEY;\n}\n\nasync function getStore(key: string): Promise<Record<string, string>> {\n try {\n const raw = await AsyncStorage.getItem(key);\n return raw ? JSON.parse(raw) : {};\n } catch {\n return {};\n }\n}\n\nasync function setStore(key: string, data: Record<string, string>): Promise<void> {\n try {\n await AsyncStorage.setItem(key, JSON.stringify(data));\n } catch {\n // Storage unavailable\n }\n}\n\nexport async function isMessageDismissed(messageId: string, dismissDays: number | null): Promise<boolean> {\n if (!dismissDays || dismissDays <= 0) return false;\n const data = await getStore(keyPrefix);\n const entry = data[messageId];\n if (!entry) return false;\n const dismissedAt = new Date(entry).getTime();\n return (Date.now() - dismissedAt) < (dismissDays * 86400000);\n}\n\nexport async function saveMessageDismissal(messageId: string): Promise<void> {\n const data = await getStore(keyPrefix);\n data[messageId] = new Date().toISOString();\n await setStore(keyPrefix, data);\n}\n\n/**\n * Check if a message should be suppressed based on max_impressions\n * or min_interval_hours. Returns true if the message should NOT be shown.\n */\nexport async function isMessageSuppressed(\n messageId: string,\n maxImpressions: number | null,\n minIntervalHours: number | null,\n): Promise<boolean> {\n // Check max impressions\n if (maxImpressions !== null && maxImpressions > 0) {\n const impressions = await getStore(impressionsKeyPrefix);\n const count = parseInt(impressions[messageId] || '0', 10);\n if (count >= maxImpressions) return true;\n }\n\n // Check min interval\n if (minIntervalHours !== null && minIntervalHours > 0) {\n const lastShown = await getStore(lastShownKeyPrefix);\n const entry = lastShown[messageId];\n if (entry) {\n const lastShownAt = new Date(entry).getTime();\n const intervalMs = minIntervalHours * 3600000;\n if ((Date.now() - lastShownAt) < intervalMs) return true;\n }\n }\n\n return false;\n}\n\n/** Record that a message was shown (increment impression count and update last-shown time). */\nexport async function recordMessageImpression(messageId: string): Promise<void> {\n // Increment impression count\n const impressions = await getStore(impressionsKeyPrefix);\n const count = parseInt(impressions[messageId] || '0', 10);\n impressions[messageId] = String(count + 1);\n await setStore(impressionsKeyPrefix, impressions);\n\n // Update last-shown timestamp\n const lastShown = await getStore(lastShownKeyPrefix);\n lastShown[messageId] = new Date().toISOString();\n await setStore(lastShownKeyPrefix, lastShown);\n}\n\n/**\n * Simple string hash (djb2 algorithm). Returns a short hex string.\n */\nfunction simpleHash(str: string): string {\n let hash = 5381;\n for (let i = 0; i < str.length; i++) {\n hash = ((hash << 5) + hash + str.charCodeAt(i)) & 0xffffffff;\n }\n return (hash >>> 0).toString(16);\n}\n","import { HttpClient } from './client';\nimport { Analytics } from './analytics';\nimport { Referrals } from './referrals';\nimport { Deferred } from './deferred';\nimport { validateBaseUrl } from './validation';\nimport { setDebugEnabled, debugLog, debugWarn } from './debug';\nimport { setStorageNamespace, resetStorageNamespace } from './storage';\nimport { SDK_VERSION } from './types';\nimport type { TolinkuConfig, ResolvedTolinkuConfig, TrackProperties } from './types';\n\n/**\n * Main Tolinku SDK singleton.\n *\n * Initialize once with Tolinku.init(), then use static methods for all operations.\n *\n * Example:\n * Tolinku.init({ apiKey: 'tolk_pub_...' });\n * await Tolinku.track('signup', { source: 'onboarding' });\n */\nexport class Tolinku {\n static readonly VERSION = SDK_VERSION;\n\n private static client: HttpClient | null = null;\n private static analyticsInstance: Analytics | null = null;\n private static referralsInstance: Referrals | null = null;\n private static deferredInstance: Deferred | null = null;\n private static _initialized = false;\n private static _userId: string | null = null;\n\n /**\n * Initialize the SDK. Must be called before any other method.\n *\n * If init() is called a second time without calling destroy() first,\n * a warning is logged and the existing instance is returned.\n */\n static init(config: TolinkuConfig): void {\n if (!config.apiKey) throw new Error('Tolinku: apiKey is required');\n\n // Double-init guard: warn and return if already configured\n if (Tolinku._initialized) {\n debugWarn(\n 'Tolinku.init() called while already initialized. ' +\n 'Call Tolinku.destroy() first if you need to reconfigure.'\n );\n // Also log to console even without debug mode, since this is a potential bug\n console.warn(\n '[TolinkuSDK] init() called while already initialized. ' +\n 'Call Tolinku.destroy() first if you need to reconfigure.'\n );\n return;\n }\n\n // Resolve defaults\n const baseUrl = config.baseUrl || 'https://api.tolinku.com';\n\n // Validate HTTPS\n validateBaseUrl(baseUrl);\n\n // Enable/disable debug logging\n setDebugEnabled(config.debug === true);\n\n const resolvedConfig: ResolvedTolinkuConfig = {\n apiKey: config.apiKey,\n baseUrl,\n debug: config.debug === true,\n timeout: config.timeout ?? 30000,\n };\n\n // Namespace storage keys by API key\n setStorageNamespace(config.apiKey);\n\n Tolinku.client = new HttpClient(resolvedConfig);\n Tolinku.analyticsInstance = new Analytics(Tolinku.client);\n Tolinku.referralsInstance = new Referrals(Tolinku.client);\n Tolinku.deferredInstance = new Deferred(Tolinku.client);\n Tolinku._initialized = true;\n\n debugLog(`Tolinku SDK v${SDK_VERSION} initialized (baseUrl=${baseUrl})`);\n }\n\n /** Check whether the SDK has been initialized. */\n static isConfigured(): boolean {\n return Tolinku._initialized;\n }\n\n /**\n * Set the user ID for segment targeting and analytics attribution.\n * Pass null to clear the user ID.\n */\n static setUserId(userId: string | null): void {\n Tolinku._userId = userId;\n }\n\n /** Get the current user ID, or null if not set. */\n static getUserId(): string | null {\n return Tolinku._userId;\n }\n\n /** Get the underlying HTTP client (used internally by MessageProvider) */\n static getClient(): HttpClient {\n if (!Tolinku.client) {\n throw new Error('Tolinku: SDK not initialized. Call Tolinku.init() first.');\n }\n return Tolinku.client;\n }\n\n /**\n * Track a custom event (shorthand for analytics.track).\n * Event type is auto-prefixed with \"custom.\" if not already.\n * Events are batched and flushed automatically.\n */\n static async track(eventType: string, properties?: TrackProperties): Promise<void> {\n if (!Tolinku.analyticsInstance) {\n throw new Error('Tolinku: SDK not initialized. Call Tolinku.init() first.');\n }\n const mergedProps = Tolinku._userId\n ? { user_id: Tolinku._userId, ...properties }\n : properties;\n return Tolinku.analyticsInstance.track(eventType, mergedProps);\n }\n\n /**\n * Immediately flush all queued analytics events to the server.\n */\n static async flush(): Promise<void> {\n if (!Tolinku.analyticsInstance) {\n throw new Error('Tolinku: SDK not initialized. Call Tolinku.init() first.');\n }\n return Tolinku.analyticsInstance.flush();\n }\n\n /** Referrals: create, complete, milestone, leaderboard, claimReward */\n static get referrals(): Referrals {\n if (!Tolinku.referralsInstance) {\n throw new Error('Tolinku: SDK not initialized. Call Tolinku.init() first.');\n }\n return Tolinku.referralsInstance;\n }\n\n /** Deferred deep links: claimByToken, claimBySignals */\n static get deferred(): Deferred {\n if (!Tolinku.deferredInstance) {\n throw new Error('Tolinku: SDK not initialized. Call Tolinku.init() first.');\n }\n return Tolinku.deferredInstance;\n }\n\n /**\n * Shut down the SDK and release resources.\n * Flushes remaining analytics events, cancels timers, removes listeners,\n * and aborts in-flight requests. After calling this, you must call init()\n * again before using the SDK.\n */\n static async destroy(): Promise<void> {\n debugLog('Tolinku SDK shutting down');\n\n // Flush and clean up analytics (timer, AppState listener)\n if (Tolinku.analyticsInstance) {\n await Tolinku.analyticsInstance.destroy();\n }\n\n // Abort all in-flight HTTP requests\n if (Tolinku.client) {\n Tolinku.client.abort();\n }\n\n // Reset storage namespace\n resetStorageNamespace();\n\n // Clear all references\n Tolinku.client = null;\n Tolinku.analyticsInstance = null;\n Tolinku.referralsInstance = null;\n Tolinku.deferredInstance = null;\n Tolinku._initialized = false;\n Tolinku._userId = null;\n\n // Reset debug mode\n setDebugEnabled(false);\n }\n}\n","import React from 'react';\nimport {\n Text,\n View,\n Image,\n TouchableOpacity,\n ImageBackground,\n Linking,\n type TextStyle,\n type ViewStyle,\n type ImageStyle,\n} from 'react-native';\nimport type { MessageComponent, ShowMessageOptions } from '../types';\nimport { isSafeUrl } from '../validation';\nimport { debugWarn } from '../debug';\n\ninterface ComponentRendererProps {\n component: MessageComponent;\n messageId: string;\n options: ShowMessageOptions;\n}\n\nexport function PuckComponentRenderer({ component, messageId, options }: ComponentRendererProps): React.ReactElement | null {\n const { props } = component;\n\n switch (component.type) {\n case 'Heading': {\n const style: TextStyle = {\n fontSize: (props.fontSize as number) || 28,\n fontWeight: '700',\n color: (props.color as string) || '#1B1B1B',\n textAlign: (props.alignment as TextStyle['textAlign']) || 'left',\n lineHeight: ((props.fontSize as number) || 28) * 1.2,\n marginBottom: 8,\n };\n return <Text style={style}>{(props.text as string) || ''}</Text>;\n }\n\n case 'TextBlock': {\n const style: TextStyle = {\n fontSize: (props.fontSize as number) || 15,\n color: (props.color as string) || '#555555',\n textAlign: (props.alignment as TextStyle['textAlign']) || 'left',\n lineHeight: ((props.fontSize as number) || 15) * 1.5,\n marginBottom: 8,\n };\n return <Text style={style}>{(props.content as string) || ''}</Text>;\n }\n\n case 'Image': {\n const imageUrl = (props.url as string) || '';\n\n // Skip rendering if URL is empty or not safe\n if (!imageUrl || !imageUrl.trim()) {\n debugWarn('Image component has empty URL, skipping render.');\n return null;\n }\n if (!isSafeUrl(imageUrl)) {\n debugWarn(`Image URL blocked (unsafe protocol): ${imageUrl}`);\n return null;\n }\n\n const widthRaw = (props.width as string) || '100%';\n let imageWidth: number | string = '100%';\n if (widthRaw.endsWith('px')) {\n imageWidth = parseInt(widthRaw, 10);\n } else if (widthRaw.endsWith('%')) {\n imageWidth = widthRaw;\n } else {\n const parsed = parseInt(widthRaw, 10);\n imageWidth = isNaN(parsed) ? '100%' : parsed;\n }\n\n const style: ImageStyle = {\n width: imageWidth as number,\n height: (props.height as number) || 200,\n borderRadius: (props.borderRadius as number) || 8,\n alignSelf: 'center',\n marginBottom: 8,\n };\n return (\n <Image\n source={{ uri: imageUrl }}\n style={style}\n resizeMode=\"cover\"\n accessibilityLabel={(props.alt as string) || ''}\n />\n );\n }\n\n case 'Button': {\n const handlePress = () => {\n const action = (props.action as string) || '';\n if (options.onButtonPress) {\n options.onButtonPress(action, messageId);\n } else if (action) {\n // Validate URL safety before opening\n if (!isSafeUrl(action)) {\n debugWarn(`Button action URL blocked (unsafe protocol): ${action}`);\n return;\n }\n Linking.openURL(action).catch(() => {});\n }\n };\n\n const containerStyle: ViewStyle = {\n backgroundColor: (props.bgColor as string) || '#1B1B1B',\n borderRadius: (props.borderRadius as number) || 8,\n paddingVertical: 10,\n paddingHorizontal: 20,\n marginVertical: 8,\n alignItems: 'center',\n ...(props.fullWidth ? { width: '100%' } : {}),\n };\n\n const textStyle: TextStyle = {\n color: (props.textColor as string) || '#ffffff',\n fontSize: (props.fontSize as number) || 16,\n fontWeight: '600',\n };\n\n return (\n <TouchableOpacity onPress={handlePress} style={containerStyle} activeOpacity={0.7}>\n <Text style={textStyle}>{(props.label as string) || 'Click'}</Text>\n </TouchableOpacity>\n );\n }\n\n case 'Section': {\n const children = (props.children as MessageComponent[]) || [];\n const containerStyle: ViewStyle = {\n backgroundColor: (props.bgColor as string) || undefined,\n padding: (props.padding as number) || 16,\n borderRadius: (props.borderRadius as number) || 0,\n marginVertical: 8,\n };\n\n const bgImage = (props.bgImage as string) || '';\n\n const content = children.map((child, index) => (\n <PuckComponentRenderer\n key={`${messageId}-section-${index}-${child.type}`}\n component={child}\n messageId={messageId}\n options={options}\n />\n ));\n\n if (bgImage) {\n // Validate background image URL\n if (!isSafeUrl(bgImage)) {\n debugWarn(`Section background image URL blocked (unsafe protocol): ${bgImage}`);\n return <View style={containerStyle}>{content}</View>;\n }\n\n return (\n <ImageBackground\n source={{ uri: bgImage }}\n style={containerStyle}\n resizeMode={(props.bgSize as string) === 'contain' ? 'contain' : 'cover'}\n imageStyle={{ borderRadius: (props.borderRadius as number) || 0 }}\n >\n {content}\n </ImageBackground>\n );\n }\n\n return <View style={containerStyle}>{content}</View>;\n }\n\n case 'Spacer': {\n const style: ViewStyle = {\n height: (props.height as number) || 24,\n };\n return <View style={style} />;\n }\n\n case 'Divider': {\n const style: ViewStyle = {\n borderTopWidth: (props.thickness as number) || 1,\n borderTopColor: (props.color as string) || '#e5e5e5',\n marginVertical: 8,\n };\n return <View style={style} />;\n }\n\n default:\n return null;\n }\n}\n","import React from 'react';\nimport {\n Modal,\n View,\n TouchableOpacity,\n Pressable,\n ScrollView,\n Text,\n StyleSheet,\n} from 'react-native';\nimport type { Message, ShowMessageOptions } from '../types';\nimport { saveMessageDismissal } from '../storage';\nimport { PuckComponentRenderer } from './components';\n\ninterface MessageModalProps {\n message: Message | null;\n visible: boolean;\n onClose: () => void;\n options: ShowMessageOptions;\n}\n\nexport function MessageModal({ message, visible, onClose, options }: MessageModalProps): React.ReactElement {\n if (!message) {\n return <></>;\n }\n\n const handleDismiss = async () => {\n await saveMessageDismissal(message.id);\n options.onDismiss?.(message.id);\n onClose();\n };\n\n return (\n <Modal\n visible={visible}\n transparent\n animationType=\"fade\"\n onRequestClose={handleDismiss}\n >\n <Pressable style={styles.overlay} onPress={handleDismiss}>\n <Pressable style={[styles.card, { backgroundColor: message.background_color || '#ffffff' }]} onPress={() => {}}>\n <TouchableOpacity\n onPress={handleDismiss}\n style={styles.closeButton}\n accessibilityLabel=\"Close message\"\n accessibilityRole=\"button\"\n >\n <Text style={styles.closeText}>{'\\u00d7'}</Text>\n </TouchableOpacity>\n\n <ScrollView\n style={styles.scrollContent}\n showsVerticalScrollIndicator={false}\n >\n {message.content?.content?.map((component, index) => (\n <PuckComponentRenderer\n key={`${message.id}-${index}-${component.type}`}\n component={component}\n messageId={message.id}\n options={options}\n />\n ))}\n </ScrollView>\n </Pressable>\n </Pressable>\n </Modal>\n );\n}\n\nconst styles = StyleSheet.create({\n overlay: {\n flex: 1,\n backgroundColor: 'rgba(0,0,0,0.5)',\n alignItems: 'center',\n justifyContent: 'center',\n },\n card: {\n position: 'relative',\n maxWidth: 375,\n width: '90%',\n maxHeight: '80%',\n borderRadius: 16,\n padding: 24,\n shadowColor: '#000',\n shadowOffset: { width: 0, height: 20 },\n shadowOpacity: 0.3,\n shadowRadius: 30,\n elevation: 10,\n },\n closeButton: {\n position: 'absolute',\n top: 12,\n right: 12,\n zIndex: 10,\n backgroundColor: 'rgba(0,0,0,0.1)',\n borderRadius: 14,\n width: 28,\n height: 28,\n alignItems: 'center',\n justifyContent: 'center',\n },\n closeText: {\n fontSize: 18,\n lineHeight: 20,\n opacity: 0.6,\n },\n scrollContent: {\n marginTop: 8,\n },\n});\n","import React, { useEffect, useState, useMemo, useCallback, useRef } from 'react';\nimport type { Message, ShowMessageOptions } from '../types';\nimport { isMessageDismissed, isMessageSuppressed, recordMessageImpression } from '../storage';\nimport { MessageModal } from './MessageModal';\nimport { Tolinku } from '../Tolinku';\nimport { debugWarn } from '../debug';\n\ninterface TolinkuMessagesProps {\n /** The trigger type to filter messages by (e.g. \"milestone\", \"event\") */\n trigger?: string;\n /** The trigger value to match (e.g. \"installed\", \"first_purchase\") */\n triggerValue?: string;\n /** Called when a message is dismissed */\n onDismiss?: (messageId: string) => void;\n /** Called when a button in the message is pressed */\n onButtonPress?: (action: string, messageId: string) => void;\n}\n\n/**\n * React component that fetches and displays in-app messages as a modal overlay.\n *\n * Place this component anywhere in your component tree. It will automatically\n * fetch messages matching the given trigger and display the highest-priority\n * non-dismissed message.\n *\n * Example:\n * <TolinkuMessages trigger=\"milestone\" triggerValue=\"installed\" />\n */\nexport function TolinkuMessages({\n trigger,\n triggerValue,\n onDismiss,\n onButtonPress,\n}: TolinkuMessagesProps): React.ReactElement {\n const [message, setMessage] = useState<Message | null>(null);\n const [visible, setVisible] = useState(false);\n\n // Stabilize callback refs so they don't trigger re-fetches\n const onDismissRef = useRef(onDismiss);\n onDismissRef.current = onDismiss;\n const onButtonPressRef = useRef(onButtonPress);\n onButtonPressRef.current = onButtonPress;\n\n // Memoize the options object to avoid unnecessary re-renders\n const options: ShowMessageOptions = useMemo(() => ({\n trigger,\n triggerValue,\n onDismiss: (messageId: string) => onDismissRef.current?.(messageId),\n onButtonPress: (action: string, messageId: string) => onButtonPressRef.current?.(action, messageId),\n }), [trigger, triggerValue]);\n\n useEffect(() => {\n let cancelled = false;\n\n async function fetchMessages() {\n try {\n const client = Tolinku.getClient();\n const params: Record<string, string> = {};\n if (trigger) params.trigger = trigger;\n const userId = Tolinku.getUserId();\n if (userId) params.user_id = userId;\n\n const data = await client.get<{ messages: Message[] }>('/v1/api/messages', params);\n if (cancelled || !data.messages || data.messages.length === 0) return;\n\n // Filter dismissed/suppressed messages and optionally by triggerValue\n const candidates: Message[] = [];\n for (const m of data.messages) {\n if (triggerValue && m.trigger_value !== triggerValue) continue;\n const dismissed = await isMessageDismissed(m.id, m.dismiss_days);\n if (dismissed) continue;\n const suppressed = await isMessageSuppressed(m.id, m.max_impressions, m.min_interval_hours);\n if (!suppressed) candidates.push(m);\n }\n\n // Sort by priority (highest first)\n candidates.sort((a, b) => b.priority - a.priority);\n\n if (candidates.length > 0 && !cancelled) {\n await recordMessageImpression(candidates[0].id);\n setMessage(candidates[0]);\n setVisible(true);\n }\n } catch (err) {\n debugWarn(`Failed to fetch messages: ${(err as Error).message}`);\n }\n }\n\n fetchMessages();\n\n return () => {\n cancelled = true;\n };\n }, [trigger, triggerValue]);\n\n const handleClose = useCallback(() => {\n setVisible(false);\n setMessage(null);\n }, []);\n\n return (\n <MessageModal\n message={message}\n visible={visible}\n onClose={handleClose}\n options={options}\n />\n );\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,102 @@
1
+ {
2
+ "name": "@tolinku/react-native-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Tolinku React Native SDK for deep linking, analytics, referrals, and in-app messages",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch",
21
+ "typecheck": "tsc --noEmit",
22
+ "clean": "rm -rf dist",
23
+ "test": "jest",
24
+ "test:watch": "jest --watch",
25
+ "prepublishOnly": "npm run build"
26
+ },
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "https://github.com/tolinku/react-native-sdk"
30
+ },
31
+ "homepage": "https://tolinku.com/docs",
32
+ "bugs": {
33
+ "url": "https://github.com/tolinku/react-native-sdk/issues"
34
+ },
35
+ "keywords": [
36
+ "tolinku",
37
+ "deep-linking",
38
+ "deferred-deep-links",
39
+ "react-native",
40
+ "analytics",
41
+ "referrals",
42
+ "universal-links",
43
+ "app-links",
44
+ "expo"
45
+ ],
46
+ "author": "Tolinku",
47
+ "license": "MIT",
48
+ "engines": {
49
+ "node": ">=18.0.0"
50
+ },
51
+ "peerDependencies": {
52
+ "@react-native-async-storage/async-storage": ">=1.19.0",
53
+ "react": ">=18.0.0",
54
+ "react-native": ">=0.72.0"
55
+ },
56
+ "peerDependenciesMeta": {
57
+ "@react-native-async-storage/async-storage": {
58
+ "optional": false
59
+ }
60
+ },
61
+ "devDependencies": {
62
+ "@react-native-async-storage/async-storage": "^1.23.0",
63
+ "@types/jest": "^29.5.14",
64
+ "@types/react": "^18.2.0",
65
+ "jest": "^29.7.0",
66
+ "react": "^18.2.0",
67
+ "react-native": "^0.73.0",
68
+ "ts-jest": "^29.4.6",
69
+ "tsup": "^8.0.0",
70
+ "typescript": "^5.4.0"
71
+ },
72
+ "jest": {
73
+ "testEnvironment": "node",
74
+ "moduleFileExtensions": [
75
+ "ts",
76
+ "tsx",
77
+ "js",
78
+ "jsx",
79
+ "json"
80
+ ],
81
+ "transform": {
82
+ "^.+\\.tsx?$": [
83
+ "ts-jest",
84
+ {
85
+ "tsconfig": {
86
+ "jsx": "react",
87
+ "esModuleInterop": true
88
+ }
89
+ }
90
+ ]
91
+ },
92
+ "testMatch": [
93
+ "**/__tests__/**/*.test.ts",
94
+ "**/__tests__/**/*.test.tsx"
95
+ ],
96
+ "collectCoverageFrom": [
97
+ "src/**/*.{ts,tsx}",
98
+ "!src/**/*.d.ts"
99
+ ]
100
+ },
101
+ "sideEffects": false
102
+ }