From ca1929213fde6b845078a6d152d063f0831ab5a8 Mon Sep 17 00:00:00 2001 From: Robert Eggl Date: Mon, 21 Oct 2024 11:42:53 +0200 Subject: [PATCH] feat(analytics): patch aptabase to detect MacOS sessions --- android/app/build.gradle | 2 +- bun.lockb | Bin 921344 -> 921416 bytes ios/NeulandNext.xcodeproj/project.pbxproj | 66 +++++++++--------- package.json | 7 +- patches/@aptabase%2Freact-native@0.3.10.patch | 45 ++++++++++++ 5 files changed, 83 insertions(+), 37 deletions(-) create mode 100644 patches/@aptabase%2Freact-native@0.3.10.patch diff --git a/android/app/build.gradle b/android/app/build.gradle index abb80f7b..ed847af4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -114,7 +114,7 @@ android { applicationId 'app.neuland' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 178 + versionCode 179 versionName "0.10.0" } signingConfigs { diff --git a/bun.lockb b/bun.lockb index c947694cce4104e80ee197804c68a918e2f91d85..7ddb73a86b991c9d5ba25b91357cb4f5c82c01fc 100755 GIT binary patch delta 452 zcmZpeXK`Yl#RNUY&?v!aCzI5v{xfb--X9R}?$_?dv1dHV}~7SmM@B{3ThZ2c(6wEgD4wTcElnG(6T zXU?>l5pXf>(51Pztuv>wuB@HH5Nxz$N%l-Ti7gW&_S{nuYF<)zu%f}%capW*_Sju4 z6Ji{Ajar2tZ79@Z-aRAwtj)uF`x8q)$|of(ER@*Qs=kQl<06hzdnEa;@=tZSn%3&J zQM&M~o#*SVDIRa?ANdpnTkLDs6=wxvHXvr-t}D)QV5$;hoS~(jsh$DD2L=WPc?O1t zzYa!OUo~J!1ohIy0kD`-IILK+L&)!e*`oXBnro8#Z!pH*Dnj zuxt9^BwmH>jyAm6A=8g^1DR(g@XoGLD@ZI!&PXlRcStNKNlZ#CPE|E>D@sjFF44_P zEXgcObuiE~)-#-*z{@Ajd4ZP?=ne*kAJZFn`IM)x;N?>gR7#6DnRMxgz5^dbZpZYC lynOQ|_x&!S((QPbz6+E)tLaaM4Be;oK$F^F1wBsuwi+Z}n$< zd3t(9G^4@xj5CY@&Xa$%7_`6OX98m8?JxLQOjkL`?|t~E?x6YR6Zem-`dZBwZ`#UI zw`{w@3^7%nu5)%Uyd;rq&3=9o{`)0@~Y;E1i z0h8Izzm_9{nbBx_#s&^`W=6yI37a{9m~;Dt&0Gu4GN!j1Hgaz_Y~=Z{YkJcpZiVfR zHoVy()0gb$QP_TF0`Kga=~H<51UOgl@_{WnF?}sBpE3)GJ^ef{pCYFKA4H;HIwK$7 P{ON`tSeqv|wDJM~(O-^d diff --git a/ios/NeulandNext.xcodeproj/project.pbxproj b/ios/NeulandNext.xcodeproj/project.pbxproj index 842bbfba..0d62afc4 100644 --- a/ios/NeulandNext.xcodeproj/project.pbxproj +++ b/ios/NeulandNext.xcodeproj/project.pbxproj @@ -7,11 +7,11 @@ objects = { /* Begin PBXBuildFile section */ - 06AE316AB9B841001A52222B /* libPods-NeulandNext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F26276C9CD131EE616EA55D4 /* libPods-NeulandNext.a */; }; 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; }; + 4515F873CC943B0D9681E944 /* libPods-NeulandNext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EACC65729D4A5EB31297381F /* libPods-NeulandNext.a */; }; 46AD202DD20E4BCD8524B837 /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = A729C136F36D44E2A045FA5C /* noop-file.swift */; }; A302539F5FBC47B6837A4DAF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = CBAD2D91DCBE4DFF953A4E6E /* InfoPlist.strings */; }; B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; }; @@ -22,6 +22,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 08321F24A200BED0FDCABAD1 /* Pods-NeulandNext.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NeulandNext.release.xcconfig"; path = "Target Support Files/Pods-NeulandNext/Pods-NeulandNext.release.xcconfig"; sourceTree = ""; }; 0ED34B5095F14BD0BE76A465 /* InfoPlist.strings */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 0F4BDE9C54AB417897742C65 /* NeulandNext-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "NeulandNext-Bridging-Header.h"; path = "NeulandNext/NeulandNext-Bridging-Header.h"; sourceTree = ""; }; 13B07F961A680F5B00A75B9A /* NeulandNext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NeulandNext.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -30,15 +31,14 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = NeulandNext/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NeulandNext/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = NeulandNext/main.m; sourceTree = ""; }; - 7F6E627C5227537BCD391D2D /* Pods-NeulandNext.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NeulandNext.release.xcconfig"; path = "Target Support Files/Pods-NeulandNext/Pods-NeulandNext.release.xcconfig"; sourceTree = ""; }; A729C136F36D44E2A045FA5C /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "NeulandNext/noop-file.swift"; sourceTree = ""; }; AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = NeulandNext/SplashScreen.storyboard; sourceTree = ""; }; - B0E14EE5A137BA0F67D9A415 /* Pods-NeulandNext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NeulandNext.debug.xcconfig"; path = "Target Support Files/Pods-NeulandNext/Pods-NeulandNext.debug.xcconfig"; sourceTree = ""; }; BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = ""; }; CBAD2D91DCBE4DFF953A4E6E /* InfoPlist.strings */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = de.lproj/InfoPlist.strings; sourceTree = ""; }; + D5D892EBC92A3CDC71953852 /* Pods-NeulandNext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NeulandNext.debug.xcconfig"; path = "Target Support Files/Pods-NeulandNext/Pods-NeulandNext.debug.xcconfig"; sourceTree = ""; }; + EACC65729D4A5EB31297381F /* libPods-NeulandNext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NeulandNext.a"; sourceTree = BUILT_PRODUCTS_DIR; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; F2353A55D7A0218E383EF53E /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = NeulandNext/PrivacyInfo.xcprivacy; sourceTree = ""; }; - F26276C9CD131EE616EA55D4 /* libPods-NeulandNext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NeulandNext.a"; sourceTree = BUILT_PRODUCTS_DIR; }; FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-NeulandNext/ExpoModulesProvider.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -48,7 +48,7 @@ buildActionMask = 2147483647; files = ( B7AAC9132C78F47E001B5511 /* MapLibre in Frameworks */, - 06AE316AB9B841001A52222B /* libPods-NeulandNext.a in Frameworks */, + 4515F873CC943B0D9681E944 /* libPods-NeulandNext.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -76,7 +76,7 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - F26276C9CD131EE616EA55D4 /* libPods-NeulandNext.a */, + EACC65729D4A5EB31297381F /* libPods-NeulandNext.a */, ); name = Frameworks; sourceTree = ""; @@ -141,8 +141,8 @@ D65327D7A22EEC0BE12398D9 /* Pods */ = { isa = PBXGroup; children = ( - B0E14EE5A137BA0F67D9A415 /* Pods-NeulandNext.debug.xcconfig */, - 7F6E627C5227537BCD391D2D /* Pods-NeulandNext.release.xcconfig */, + D5D892EBC92A3CDC71953852 /* Pods-NeulandNext.debug.xcconfig */, + 08321F24A200BED0FDCABAD1 /* Pods-NeulandNext.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -170,15 +170,15 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NeulandNext" */; buildPhases = ( - CB832BBFB2A2892774940553 /* [CP] Check Pods Manifest.lock */, + 60A2BA399987E314BA9DF886 /* [CP] Check Pods Manifest.lock */, 20106158D94352890A68C86A /* [Expo] Configure project */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, F81CEBBAB15C40E9993CF5DD /* Remove signature files (Xcode 16 workaround) */, - DE286250F2F8250F4CEF37D8 /* [CP] Embed Pods Frameworks */, - DCD900BAB1BBE2F5ACD931E4 /* [CP] Copy Pods Resources */, + 8FE171D204CCE64E6063DBF7 /* [CP] Embed Pods Frameworks */, + D3AD9D6A2AD5248D4BCE957D /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -277,7 +277,7 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-NeulandNext/expo-configure-project.sh\"\n"; }; - CB832BBFB2A2892774940553 /* [CP] Check Pods Manifest.lock */ = { + 60A2BA399987E314BA9DF886 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -299,7 +299,25 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - DCD900BAB1BBE2F5ACD931E4 /* [CP] Copy Pods Resources */ = { + 8FE171D204CCE64E6063DBF7 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-NeulandNext/Pods-NeulandNext-frameworks.sh", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NeulandNext/Pods-NeulandNext-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + D3AD9D6A2AD5248D4BCE957D /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -341,24 +359,6 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NeulandNext/Pods-NeulandNext-resources.sh\"\n"; showEnvVarsInLog = 0; }; - DE286250F2F8250F4CEF37D8 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-NeulandNext/Pods-NeulandNext-frameworks.sh", - "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", - ); - name = "[CP] Embed Pods Frameworks"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NeulandNext/Pods-NeulandNext-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; F81CEBBAB15C40E9993CF5DD /* Remove signature files (Xcode 16 workaround) */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -392,7 +392,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B0E14EE5A137BA0F67D9A415 /* Pods-NeulandNext.debug.xcconfig */; + baseConfigurationReference = D5D892EBC92A3CDC71953852 /* Pods-NeulandNext.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; @@ -430,7 +430,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 7F6E627C5227537BCD391D2D /* Pods-NeulandNext.release.xcconfig */; + baseConfigurationReference = 08321F24A200BED0FDCABAD1 /* Pods-NeulandNext.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; diff --git a/package.json b/package.json index 603d2d81..e671d0ba 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "@aptabase/react-native": "^0.3.10", "@babel/runtime": "^7.25.7", "@expo/vector-icons": "^14.0.4", - "@gorhom/bottom-sheet": "^5.0.2", + "@gorhom/bottom-sheet": "^5.0.4", "@kichiyaki/react-native-barcode-generator": "^0.6.7", "@maplibre/maplibre-react-native": "^10.0.0-alpha.21", "@react-native-community/datetimepicker": "8.2.0", @@ -55,7 +55,7 @@ "fuse.js": "^7.0.0", "graphql": "^16.9.0", "graphql-request": "^6.1.0", - "i18next": "^23.16.1", + "i18next": "^23.16.2", "metro": "~0.80.12", "moment": "^2.30.1", "moment-timezone": "^0.5.46", @@ -148,6 +148,7 @@ "@th3rdwave/react-navigation-bottom-sheet@0.3.2": "patches/@th3rdwave%2Freact-navigation-bottom-sheet@0.3.2.patch", "react-native-shimmer@0.6.0": "patches/react-native-shimmer@0.6.0.patch", "react-native-week-view@0.30.0": "patches/react-native-week-view@0.30.0.patch", - "react-native-paper@5.12.5": "patches/react-native-paper@5.12.5.patch" + "react-native-paper@5.12.5": "patches/react-native-paper@5.12.5.patch", + "@aptabase/react-native@0.3.10": "patches/@aptabase%2Freact-native@0.3.10.patch" } } diff --git a/patches/@aptabase%2Freact-native@0.3.10.patch b/patches/@aptabase%2Freact-native@0.3.10.patch new file mode 100644 index 00000000..23122445 --- /dev/null +++ b/patches/@aptabase%2Freact-native@0.3.10.patch @@ -0,0 +1,45 @@ +diff --git a/dist/index.js b/dist/index.js +index 18c43f77ea122a2b483a70dfda5d7ed207957474..b429aa8ec8ceb192e84d596697ea863b6ad989e9 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -1,2 +1,2 @@ +-var H=Object.defineProperty;var A=Object.getOwnPropertySymbols;var U=Object.prototype.hasOwnProperty,$=Object.prototype.propertyIsEnumerable;var S=(r,e,t)=>e in r?H(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,I=(r,e)=>{for(var t in e||(e={}))U.call(e,t)&&S(r,t,e[t]);if(A)for(var t of A(e))$.call(e,t)&&S(r,t,e[t]);return r};var i=(r,e,t)=>(S(r,typeof e!="symbol"?e+"":e,t),t);var E=(r,e,t)=>new Promise((s,u)=>{var a=o=>{try{c(t.next(o))}catch(b){u(b)}},p=o=>{try{c(t.throw(o))}catch(b){u(b)}},c=o=>o.done?s(o.value):Promise.resolve(o.value).then(a,p);c((t=t.apply(r,e)).next())});import{Platform as d}from"react-native";import{NativeModules as B}from"react-native";var{RNAptabaseModule:l}=B,O,P,V,w,C={appVersion:(P=(O=l==null?void 0:l.appVersion)==null?void 0:O.toString())!=null?P:"",appBuildNumber:(w=(V=l==null?void 0:l.appBuildNumber)==null?void 0:V.toString())!=null?w:""},_=C;var M="aptabase-reactnative@0.3.10";function T(){let[r,e]=j(),t="en-US";return{appVersion:_.appVersion,appBuildNumber:_.appBuildNumber,isDebug:__DEV__,locale:t,osName:r,osVersion:e,sdkVersion:M}}function j(){switch(d.OS){case"android":return["Android",d.constants.Release];case"ios":return d.isPad?["iPadOS",d.Version]:["iOS",d.Version];default:return["",""]}}import{AppState as D,Platform as L}from"react-native";var f=class{constructor(e,t,s){i(this,"_events",[]);i(this,"MAX_BATCH_SIZE",25);i(this,"headers");i(this,"apiUrl");this.apiUrl=`${t}/api/v0/events`,this.headers=new Headers({"Content-Type":"application/json","App-Key":e,"User-Agent":`${s.osName}/${s.osVersion} ${s.locale}`})}enqueue(e){if(Array.isArray(e)){this._events.push(...e);return}this._events.push(e)}flush(){return E(this,null,function*(){if(this._events.length===0)return Promise.resolve();let e=[];do{let t=this._events.splice(0,this.MAX_BATCH_SIZE);try{yield this._sendEvents(t)}catch(s){e=[...e,...t]}}while(this._events.length>0);e.length>0&&this.enqueue(e)})}_sendEvents(e){return E(this,null,function*(){try{let t=yield fetch(this.apiUrl,{method:"POST",headers:this.headers,credentials:"omit",body:JSON.stringify(e)});if(t.status<300)return Promise.resolve();let s=`${t.status} ${yield t.text()}`;if(t.status<500)return console.warn(`Aptabase: Failed to send ${e.length} events because of ${s}. Will not retry.`),Promise.resolve();throw new Error(s)}catch(t){throw console.error(`Aptabase: Failed to send ${e.length} events. Reason: ${t}`),t}})}};function y(){let r=Math.floor(Date.now()/1e3).toString(),e=Math.floor(Math.random()*1e8).toString().padStart(8,"0");return r+e}var x=__DEV__?2e3:6e4,m={US:"https://us.aptabase.com",EU:"https://eu.aptabase.com",DEV:"http://localhost:3000",SH:""};var h=class{constructor(e,t,s){i(this,"_dispatcher");i(this,"_env");i(this,"_sessionId",y());i(this,"_lastTouched",new Date);i(this,"_flushTimer");let[u,a]=e.split("-"),p=this.getBaseUrl(a,s);this._env=I({},t),s!=null&&s.appVersion&&(this._env.appVersion=s.appVersion),this._dispatcher=new f(e,p,t)}trackEvent(e,t){this._dispatcher.enqueue({timestamp:new Date().toISOString(),sessionId:this.evalSessionId(),eventName:e,systemProps:{isDebug:this._env.isDebug,locale:this._env.locale,osName:this._env.osName,osVersion:this._env.osVersion,appVersion:this._env.appVersion,appBuildNumber:this._env.appBuildNumber,sdkVersion:this._env.sdkVersion},props:t})}startPolling(e){this.stopPolling(),this._flushTimer=setInterval(this.flush.bind(this),e)}stopPolling(){this._flushTimer&&(clearInterval(this._flushTimer),this._flushTimer=void 0)}flush(){return this._dispatcher.flush()}evalSessionId(){let e=new Date;return e.getTime()-this._lastTouched.getTime()>36e5&&(this._sessionId=y()),this._lastTouched=e,this._sessionId}getBaseUrl(e,t){var s;return e==="SH"?(s=t==null?void 0:t.host)!=null?s:m.DEV:m[e]}};function N(r,e,t){if(r!=="android"&&r!=="ios")return[!1,"This SDK is only supported on Android and iOS"];let s=e.split("-");return s.length!==3||m[s[1]]===void 0?[!1,`App Key "${e}" is invalid`]:s[1]==="SH"&&!(t!=null&&t.host)?[!1,"Host parameter must be defined when using Self-Hosted App Key"]:[!0,""]}var n;function v(r,e){var p;let[t,s]=N(L.OS,r,e);if(!t){console.warn(`Aptabase: ${s}. Tracking will be disabled.`);return}let u=T();n=new h(r,u,e);let a=(p=e==null?void 0:e.flushInterval)!=null?p:x;n.startPolling(a),D.isAvailable&&D.addEventListener("change",c=>{n==null||n.flush(),c==="active"?n==null||n.startPolling(a):n==null||n.stopPolling()})}function k(){n?(n.stopPolling(),n=void 0):console.warn("Aptabase: dispose was called but SDK was not initialized.")}function g(r,e){if(e&&!F(e)){console.warn("Aptabase: trackEvent was called with invalid properties. The second parameter must be an object.");return}n==null||n.trackEvent(r,e)}var F=r=>typeof r=="object"&&r.constructor===Object;import{createContext as q,useEffect as K}from"react";import{jsx as z}from"react/jsx-runtime";var J=q({});function X({appKey:r,options:e,children:t}){return K(()=>{v(r,e)},[r,e]),z(J.Provider,{value:{},children:t})}function Z(){return{trackEvent:g}}var Ie={init:v,trackEvent:g,dispose:k};export{X as AptabaseProvider,Ie as default,k as dispose,v as init,g as trackEvent,Z as useAptabase}; ++var U=Object.defineProperty;var A=Object.getOwnPropertySymbols;var $=Object.prototype.hasOwnProperty,B=Object.prototype.propertyIsEnumerable;var E=(r,e,t)=>e in r?U(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t,y=(r,e)=>{for(var t in e||(e={}))$.call(e,t)&&E(r,t,e[t]);if(A)for(var t of A(e))B.call(e,t)&&E(r,t,e[t]);return r};var i=(r,e,t)=>(E(r,typeof e!="symbol"?e+"":e,t),t);var _=(r,e,t)=>new Promise((s,f)=>{var p=a=>{try{m(t.next(a))}catch(S){f(S)}},l=a=>{try{m(t.throw(a))}catch(S){f(S)}},m=a=>a.done?s(a.value):Promise.resolve(a.value).then(p,l);m((t=t.apply(r,e)).next())});import{Platform as c}from"react-native";import{NativeModules as C}from"react-native";var{RNAptabaseModule:o}=C,I,V,P,w,T,M={appVersion:(V=(I=o==null?void 0:o.appVersion)==null?void 0:I.toString())!=null?V:"",appBuildNumber:(w=(P=o==null?void 0:o.appBuildNumber)==null?void 0:P.toString())!=null?w:"",isiOSAppOnMac:(T=o==null?void 0:o.isiOSAppOnMac)!=null?T:!1},d=M;var j="aptabase-reactnative@0.3.10";function x(){let[r,e]=L(),t="en-US";return{appVersion:d.appVersion,appBuildNumber:d.appBuildNumber,isDebug:__DEV__,locale:t,osName:r,osVersion:e,sdkVersion:j}}function L(){switch(c.OS){case"android":return["Android",c.constants.Release];case"ios":return c.isPad?d.isiOSAppOnMac?["MacOS",c.Version]:["iPadOS",c.Version]:["iOS",c.Version];default:return["",""]}}import{AppState as k,Platform as R}from"react-native";var h=class{constructor(e,t,s){i(this,"_events",[]);i(this,"MAX_BATCH_SIZE",25);i(this,"headers");i(this,"apiUrl");this.apiUrl=`${t}/api/v0/events`,this.headers=new Headers({"Content-Type":"application/json","App-Key":e,"User-Agent":`${s.osName}/${s.osVersion} ${s.locale}`})}enqueue(e){if(Array.isArray(e)){this._events.push(...e);return}this._events.push(e)}flush(){return _(this,null,function*(){if(this._events.length===0)return Promise.resolve();let e=[];do{let t=this._events.splice(0,this.MAX_BATCH_SIZE);try{yield this._sendEvents(t)}catch(s){e=[...e,...t]}}while(this._events.length>0);e.length>0&&this.enqueue(e)})}_sendEvents(e){return _(this,null,function*(){try{let t=yield fetch(this.apiUrl,{method:"POST",headers:this.headers,credentials:"omit",body:JSON.stringify(e)});if(t.status<300)return Promise.resolve();let s=`${t.status} ${yield t.text()}`;if(t.status<500)return console.warn(`Aptabase: Failed to send ${e.length} events because of ${s}. Will not retry.`),Promise.resolve();throw new Error(s)}catch(t){throw console.error(`Aptabase: Failed to send ${e.length} events. Reason: ${t}`),t}})}};function O(){let r=Math.floor(Date.now()/1e3).toString(),e=Math.floor(Math.random()*1e8).toString().padStart(8,"0");return r+e}var N=__DEV__?2e3:6e4,u={US:"https://us.aptabase.com",EU:"https://eu.aptabase.com",DEV:"http://localhost:3000",SH:""};var v=class{constructor(e,t,s){i(this,"_dispatcher");i(this,"_env");i(this,"_sessionId",O());i(this,"_lastTouched",new Date);i(this,"_flushTimer");let[f,p]=e.split("-"),l=this.getBaseUrl(p,s);this._env=y({},t),s!=null&&s.appVersion&&(this._env.appVersion=s.appVersion),this._dispatcher=new h(e,l,t)}trackEvent(e,t){this._dispatcher.enqueue({timestamp:new Date().toISOString(),sessionId:this.evalSessionId(),eventName:e,systemProps:{isDebug:this._env.isDebug,locale:this._env.locale,osName:this._env.osName,osVersion:this._env.osVersion,appVersion:this._env.appVersion,appBuildNumber:this._env.appBuildNumber,sdkVersion:this._env.sdkVersion},props:t})}startPolling(e){this.stopPolling(),this._flushTimer=setInterval(this.flush.bind(this),e)}stopPolling(){this._flushTimer&&(clearInterval(this._flushTimer),this._flushTimer=void 0)}flush(){return this._dispatcher.flush()}evalSessionId(){let e=new Date;return e.getTime()-this._lastTouched.getTime()>36e5&&(this._sessionId=O()),this._lastTouched=e,this._sessionId}getBaseUrl(e,t){var s;return e==="SH"?(s=t==null?void 0:t.host)!=null?s:u.DEV:u[e]}};function D(r,e,t){if(r!=="android"&&r!=="ios")return[!1,"This SDK is only supported on Android and iOS"];let s=e.split("-");return s.length!==3||u[s[1]]===void 0?[!1,`App Key "${e}" is invalid`]:s[1]==="SH"&&!(t!=null&&t.host)?[!1,"Host parameter must be defined when using Self-Hosted App Key"]:[!0,""]}var n;function g(r,e){var l;let[t,s]=D(R.OS,r,e);if(!t){console.warn(`Aptabase: ${s}. Tracking will be disabled.`);return}let f=x();n=new v(r,f,e);let p=(l=e==null?void 0:e.flushInterval)!=null?l:N;n.startPolling(p),k.isAvailable&&k.addEventListener("change",m=>{n==null||n.flush(),m==="active"?n==null||n.startPolling(p):n==null||n.stopPolling()})}function H(){n?(n.stopPolling(),n=void 0):console.warn("Aptabase: dispose was called but SDK was not initialized.")}function b(r,e){if(e&&!q(e)){console.warn("Aptabase: trackEvent was called with invalid properties. The second parameter must be an object.");return}n==null||n.trackEvent(r,e)}var q=r=>typeof r=="object"&&r.constructor===Object;import{createContext as K,useEffect as J}from"react";import{jsx as G}from"react/jsx-runtime";var X=K({});function Z({appKey:r,options:e,children:t}){return J(()=>{g(r,e)},[r,e]),G(X.Provider,{value:{},children:t})}function z(){return{trackEvent:b}}var Ie={init:g,trackEvent:b,dispose:H};export{Z as AptabaseProvider,Ie as default,H as dispose,g as init,b as trackEvent,z as useAptabase}; + //# sourceMappingURL=index.js.map +\ No newline at end of file +diff --git a/dist/index.js.map b/dist/index.js.map +index d2954e095df6003c911afd6e240d98808c1aae94..2b9fb129b8120b68b138888cc215e6afeb3720fb 100644 +--- a/dist/index.js.map ++++ b/dist/index.js.map +@@ -1 +1 @@ +-{"version":3,"sources":["../src/env.ts","../src/version.ts","../src/track.ts","../src/dispatcher.ts","../src/session.ts","../src/constants.ts","../src/client.ts","../src/validate.ts","../src/context.tsx","../src/index.ts"],"sourcesContent":["import { Platform } from \"react-native\";\nimport version from \"./version\";\n\n// env.PKG_VERSION is replaced by Vite during build phase\nconst sdkVersion = `aptabase-reactnative@${process.env.PKG_VERSION}`;\n\nexport interface EnvironmentInfo {\n isDebug: boolean;\n locale: string;\n appVersion: string;\n appBuildNumber: string;\n sdkVersion: string;\n osName: string;\n osVersion: string;\n}\n\nexport function getEnvironmentInfo(): EnvironmentInfo {\n const [osName, osVersion] = getOperatingSystem();\n\n const locale = \"en-US\";\n\n return {\n appVersion: version.appVersion,\n appBuildNumber: version.appBuildNumber,\n isDebug: __DEV__,\n locale,\n osName,\n osVersion,\n sdkVersion,\n };\n}\n\nfunction getOperatingSystem(): [string, string] {\n switch (Platform.OS) {\n case \"android\":\n return [\"Android\", Platform.constants.Release];\n case \"ios\":\n if (Platform.isPad) {\n return [\"iPadOS\", Platform.Version];\n }\n return [\"iOS\", Platform.Version];\n default:\n return [\"\", \"\"];\n }\n}\n","import { NativeModules } from \"react-native\";\n\nconst { RNAptabaseModule } = NativeModules;\n\ntype VersionObject = {\n appVersion: string;\n appBuildNumber: string;\n};\n\nconst Version: VersionObject = {\n appVersion: RNAptabaseModule?.appVersion?.toString() ?? \"\",\n appBuildNumber: RNAptabaseModule?.appBuildNumber?.toString() ?? \"\",\n};\n\nexport default Version;\n","import type { AptabaseOptions } from \"./types\";\nimport { getEnvironmentInfo } from \"./env\";\nimport { AppState, Platform } from \"react-native\";\nimport { AptabaseClient } from \"./client\";\nimport { FLUSH_INTERVAL } from \"./constants\";\nimport { validate } from \"./validate\";\n\nlet _client: AptabaseClient | undefined;\n\n/**\n * Initializes the SDK with given App Key\n * @param {string} appKey - Aptabase App Key\n * @param {AptabaseOptions} options - Optional initialization parameters\n */\nexport function init(appKey: string, options?: AptabaseOptions) {\n const [ok, msg] = validate(Platform.OS, appKey, options);\n if (!ok) {\n console.warn(`Aptabase: ${msg}. Tracking will be disabled.`);\n return;\n }\n\n const env = getEnvironmentInfo();\n _client = new AptabaseClient(appKey, env, options);\n\n const flushInterval = options?.flushInterval ?? FLUSH_INTERVAL;\n _client.startPolling(flushInterval);\n\n if (!AppState.isAvailable) return;\n\n AppState.addEventListener(\"change\", (next) => {\n _client?.flush();\n\n if (next === \"active\") {\n _client?.startPolling(flushInterval);\n } else {\n _client?.stopPolling();\n }\n });\n}\n\n/**\n * Dispose the SDK and stop tracking events\n */\nexport function dispose() {\n if (_client) {\n _client.stopPolling();\n _client = undefined;\n } else {\n console.warn(`Aptabase: dispose was called but SDK was not initialized.`);\n }\n}\n\n/**\n * Track an event using given properties\n * @param {string} eventName - The name of the event to track\n * @param {Object} props - Optional custom properties\n */\nexport function trackEvent(\n eventName: string,\n props?: Record\n) {\n if (!!props && !isPlainObject(props)) {\n console.warn(\n `Aptabase: trackEvent was called with invalid properties. The second parameter must be an object.`\n );\n return;\n }\n\n _client?.trackEvent(eventName, props);\n}\n\nconst isPlainObject = (val: any) =>\n typeof val === \"object\" && val.constructor === Object;\n","import type { Event } from \"./types\";\nimport { EnvironmentInfo } from \"./env\";\n\nexport class EventDispatcher {\n private _events: Event[] = [];\n private MAX_BATCH_SIZE = 25;\n private headers: Headers;\n private apiUrl: string;\n\n constructor(appKey: string, baseUrl: string, env: EnvironmentInfo) {\n this.apiUrl = `${baseUrl}/api/v0/events`;\n this.headers = new Headers({\n \"Content-Type\": \"application/json\",\n \"App-Key\": appKey,\n \"User-Agent\": `${env.osName}/${env.osVersion} ${env.locale}`,\n });\n }\n\n public enqueue(evt: Event | Event[]) {\n if (Array.isArray(evt)) {\n this._events.push(...evt);\n return;\n }\n\n this._events.push(evt);\n }\n\n public async flush(): Promise {\n if (this._events.length === 0) {\n return Promise.resolve();\n }\n\n let failedEvents: Event[] = [];\n do {\n const eventsToSend = this._events.splice(0, this.MAX_BATCH_SIZE);\n try {\n await this._sendEvents(eventsToSend);\n } catch {\n failedEvents = [...failedEvents, ...eventsToSend];\n }\n } while (this._events.length > 0);\n\n if (failedEvents.length > 0) {\n this.enqueue(failedEvents);\n }\n }\n\n private async _sendEvents(events: Event[]): Promise {\n try {\n const res = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n credentials: \"omit\",\n body: JSON.stringify(events),\n });\n\n if (res.status < 300) {\n return Promise.resolve();\n }\n\n const reason = `${res.status} ${await res.text()}`;\n if (res.status < 500) {\n console.warn(\n `Aptabase: Failed to send ${events.length} events because of ${reason}. Will not retry.`\n );\n return Promise.resolve();\n }\n\n throw new Error(reason);\n } catch (e) {\n console.error(\n `Aptabase: Failed to send ${events.length} events. Reason: ${e}`\n );\n throw e;\n }\n }\n}\n","export function newSessionId(): string {\n const epochInSeconds = Math.floor(Date.now() / 1000).toString();\n const random = Math.floor(Math.random() * 100000000)\n .toString()\n .padStart(8, \"0\");\n\n return epochInSeconds + random;\n}\n","// Session expires after 1 hour of inactivity\nexport const SESSION_TIMEOUT = 60 * 60 * 1000;\n\n// Flush events every 60 seconds in production, or 2 seconds in development\nexport const FLUSH_INTERVAL = __DEV__ ? 2000 : 60000;\n\n// List of hosts for each region\n// To use a self-hosted (SH) deployment, the host must be set during init\nexport const HOSTS: { [region: string]: string } = {\n US: \"https://us.aptabase.com\",\n EU: \"https://eu.aptabase.com\",\n DEV: \"http://localhost:3000\",\n SH: \"\",\n};\n","import type { Platform } from \"react-native\";\nimport type { AptabaseOptions } from \"./types\";\nimport type { EnvironmentInfo } from \"./env\";\nimport { EventDispatcher } from \"./dispatcher\";\nimport { newSessionId } from \"./session\";\nimport { HOSTS, SESSION_TIMEOUT } from \"./constants\";\n\nexport class AptabaseClient {\n private readonly _dispatcher: EventDispatcher;\n private readonly _env: EnvironmentInfo;\n private _sessionId = newSessionId();\n private _lastTouched = new Date();\n private _flushTimer: NodeJS.Timeout | undefined;\n\n constructor(appKey: string, env: EnvironmentInfo, options?: AptabaseOptions) {\n const [_, region] = appKey.split(\"-\");\n const baseUrl = this.getBaseUrl(region, options);\n\n this._env = { ...env };\n if (options?.appVersion) {\n this._env.appVersion = options.appVersion;\n }\n\n this._dispatcher = new EventDispatcher(appKey, baseUrl, env);\n }\n\n public trackEvent(\n eventName: string,\n props?: Record\n ) {\n this._dispatcher.enqueue({\n timestamp: new Date().toISOString(),\n sessionId: this.evalSessionId(),\n eventName: eventName,\n systemProps: {\n isDebug: this._env.isDebug,\n locale: this._env.locale,\n osName: this._env.osName,\n osVersion: this._env.osVersion,\n appVersion: this._env.appVersion,\n appBuildNumber: this._env.appBuildNumber,\n sdkVersion: this._env.sdkVersion,\n },\n props: props,\n });\n }\n\n public startPolling(flushInterval: number) {\n this.stopPolling();\n\n this._flushTimer = setInterval(this.flush.bind(this), flushInterval);\n }\n\n public stopPolling() {\n if (this._flushTimer) {\n clearInterval(this._flushTimer);\n this._flushTimer = undefined;\n }\n }\n\n public flush(): Promise {\n return this._dispatcher.flush();\n }\n\n private evalSessionId() {\n let now = new Date();\n const diffInMs = now.getTime() - this._lastTouched.getTime();\n if (diffInMs > SESSION_TIMEOUT) {\n this._sessionId = newSessionId();\n }\n this._lastTouched = now;\n\n return this._sessionId;\n }\n\n private getBaseUrl(region: string, options?: AptabaseOptions): string {\n if (region === \"SH\") {\n return options?.host ?? HOSTS.DEV;\n }\n\n return HOSTS[region];\n }\n}\n","import type { Platform } from \"react-native\";\nimport { HOSTS } from \"./constants\";\n\nimport type { AptabaseOptions } from \"./types\";\n\nexport function validate(\n platform: typeof Platform.OS,\n appKey: string,\n options?: AptabaseOptions\n): [boolean, string] {\n if (platform !== \"android\" && platform !== \"ios\") {\n return [false, \"This SDK is only supported on Android and iOS\"];\n }\n\n const parts = appKey.split(\"-\");\n if (parts.length !== 3 || HOSTS[parts[1]] === undefined) {\n return [false, `App Key \"${appKey}\" is invalid`];\n }\n\n if (parts[1] === \"SH\" && !options?.host) {\n return [\n false,\n `Host parameter must be defined when using Self-Hosted App Key`,\n ];\n }\n\n return [true, \"\"];\n}\n","import { init, trackEvent } from \"./track\";\nimport { createContext, useEffect, type ReactNode } from \"react\";\nimport { AptabaseOptions } from \"./types\";\n\ntype ContextProps = {};\n\nexport type AptabaseClient = {\n trackEvent: typeof trackEvent;\n};\n\nconst AptabaseContext = createContext({});\n\ntype Props = {\n appKey: string;\n options?: AptabaseOptions;\n children: ReactNode;\n};\n\nexport function AptabaseProvider({ appKey, options, children }: Props) {\n useEffect(() => {\n init(appKey, options);\n }, [appKey, options]);\n\n return (\n {children}\n );\n}\n\nexport function useAptabase(): AptabaseClient {\n return { trackEvent };\n}\n","export type { AptabaseOptions } from \"./types\";\nexport { AptabaseProvider, useAptabase } from \"./context\";\nimport { init, trackEvent, dispose } from \"./track\";\nexport { init, trackEvent, dispose };\n\nexport default { init, trackEvent, dispose };\n"],"mappings":"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","names":["Platform","NativeModules","RNAptabaseModule","_a","_b","_c","_d","Version","version_default","sdkVersion","getEnvironmentInfo","osName","osVersion","getOperatingSystem","locale","version_default","Platform","AppState","Platform","EventDispatcher","appKey","baseUrl","env","__publicField","evt","__async","failedEvents","eventsToSend","e","events","res","reason","newSessionId","epochInSeconds","random","FLUSH_INTERVAL","HOSTS","AptabaseClient","appKey","env","options","__publicField","newSessionId","_","region","baseUrl","__spreadValues","EventDispatcher","eventName","props","flushInterval","now","_a","HOSTS","validate","platform","appKey","options","parts","HOSTS","_client","init","appKey","options","_a","ok","msg","validate","Platform","env","getEnvironmentInfo","AptabaseClient","flushInterval","FLUSH_INTERVAL","AppState","next","dispose","trackEvent","eventName","props","isPlainObject","val","createContext","useEffect","jsx","AptabaseContext","AptabaseProvider","appKey","options","children","init","useAptabase","trackEvent","src_default","init","trackEvent","dispose"]} +\ No newline at end of file ++{"version":3,"sources":["../src/env.ts","../src/version.ts","../src/track.ts","../src/dispatcher.ts","../src/session.ts","../src/constants.ts","../src/client.ts","../src/validate.ts","../src/context.tsx","../src/index.ts"],"sourcesContent":["import { Platform } from \"react-native\";\nimport version from \"./version\";\n\n// env.PKG_VERSION is replaced by Vite during build phase\nconst sdkVersion = `aptabase-reactnative@${process.env.PKG_VERSION}`;\n\nexport interface EnvironmentInfo {\n isDebug: boolean;\n locale: string;\n appVersion: string;\n appBuildNumber: string;\n sdkVersion: string;\n osName: string;\n osVersion: string;\n}\n\nexport function getEnvironmentInfo(): EnvironmentInfo {\n const [osName, osVersion] = getOperatingSystem();\n\n const locale = \"en-US\";\n\n return {\n appVersion: version.appVersion,\n appBuildNumber: version.appBuildNumber,\n isDebug: __DEV__,\n locale,\n osName,\n osVersion,\n sdkVersion,\n };\n}\n\nfunction getOperatingSystem(): [string, string] {\n switch (Platform.OS) {\n case \"android\":\n return [\"Android\", Platform.constants.Release];\n case \"ios\":\n if (Platform.isPad) {\n if (version.isiOSAppOnMac) {\n // Version represents the emulated iPadOS version and not the MacOS version\n return [\"MacOS\", Platform.Version];\n }\n return [\"iPadOS\", Platform.Version];\n }\n return [\"iOS\", Platform.Version];\n default:\n return [\"\", \"\"];\n }\n}\n","import { NativeModules } from \"react-native\";\n\nconst { RNAptabaseModule } = NativeModules;\n\ntype VersionObject = {\n appVersion: string;\n appBuildNumber: string;\n isiOSAppOnMac: boolean;\n};\n\nconst Version: VersionObject = {\n appVersion: RNAptabaseModule?.appVersion?.toString() ?? \"\",\n appBuildNumber: RNAptabaseModule?.appBuildNumber?.toString() ?? \"\",\n isiOSAppOnMac: RNAptabaseModule?.isiOSAppOnMac ?? false,\n};\n\nexport default Version;\n","import type { AptabaseOptions } from \"./types\";\nimport { getEnvironmentInfo } from \"./env\";\nimport { AppState, Platform } from \"react-native\";\nimport { AptabaseClient } from \"./client\";\nimport { FLUSH_INTERVAL } from \"./constants\";\nimport { validate } from \"./validate\";\n\nlet _client: AptabaseClient | undefined;\n\n/**\n * Initializes the SDK with given App Key\n * @param {string} appKey - Aptabase App Key\n * @param {AptabaseOptions} options - Optional initialization parameters\n */\nexport function init(appKey: string, options?: AptabaseOptions) {\n const [ok, msg] = validate(Platform.OS, appKey, options);\n if (!ok) {\n console.warn(`Aptabase: ${msg}. Tracking will be disabled.`);\n return;\n }\n\n const env = getEnvironmentInfo();\n _client = new AptabaseClient(appKey, env, options);\n\n const flushInterval = options?.flushInterval ?? FLUSH_INTERVAL;\n _client.startPolling(flushInterval);\n\n if (!AppState.isAvailable) return;\n\n AppState.addEventListener(\"change\", (next) => {\n _client?.flush();\n\n if (next === \"active\") {\n _client?.startPolling(flushInterval);\n } else {\n _client?.stopPolling();\n }\n });\n}\n\n/**\n * Dispose the SDK and stop tracking events\n */\nexport function dispose() {\n if (_client) {\n _client.stopPolling();\n _client = undefined;\n } else {\n console.warn(`Aptabase: dispose was called but SDK was not initialized.`);\n }\n}\n\n/**\n * Track an event using given properties\n * @param {string} eventName - The name of the event to track\n * @param {Object} props - Optional custom properties\n */\nexport function trackEvent(\n eventName: string,\n props?: Record\n) {\n if (!!props && !isPlainObject(props)) {\n console.warn(\n `Aptabase: trackEvent was called with invalid properties. The second parameter must be an object.`\n );\n return;\n }\n\n _client?.trackEvent(eventName, props);\n}\n\nconst isPlainObject = (val: any) =>\n typeof val === \"object\" && val.constructor === Object;\n","import type { Event } from \"./types\";\nimport { EnvironmentInfo } from \"./env\";\n\nexport class EventDispatcher {\n private _events: Event[] = [];\n private MAX_BATCH_SIZE = 25;\n private headers: Headers;\n private apiUrl: string;\n\n constructor(appKey: string, baseUrl: string, env: EnvironmentInfo) {\n this.apiUrl = `${baseUrl}/api/v0/events`;\n this.headers = new Headers({\n \"Content-Type\": \"application/json\",\n \"App-Key\": appKey,\n \"User-Agent\": `${env.osName}/${env.osVersion} ${env.locale}`,\n });\n }\n\n public enqueue(evt: Event | Event[]) {\n if (Array.isArray(evt)) {\n this._events.push(...evt);\n return;\n }\n\n this._events.push(evt);\n }\n\n public async flush(): Promise {\n if (this._events.length === 0) {\n return Promise.resolve();\n }\n\n let failedEvents: Event[] = [];\n do {\n const eventsToSend = this._events.splice(0, this.MAX_BATCH_SIZE);\n try {\n await this._sendEvents(eventsToSend);\n } catch {\n failedEvents = [...failedEvents, ...eventsToSend];\n }\n } while (this._events.length > 0);\n\n if (failedEvents.length > 0) {\n this.enqueue(failedEvents);\n }\n }\n\n private async _sendEvents(events: Event[]): Promise {\n try {\n const res = await fetch(this.apiUrl, {\n method: \"POST\",\n headers: this.headers,\n credentials: \"omit\",\n body: JSON.stringify(events),\n });\n\n if (res.status < 300) {\n return Promise.resolve();\n }\n\n const reason = `${res.status} ${await res.text()}`;\n if (res.status < 500) {\n console.warn(\n `Aptabase: Failed to send ${events.length} events because of ${reason}. Will not retry.`\n );\n return Promise.resolve();\n }\n\n throw new Error(reason);\n } catch (e) {\n console.error(\n `Aptabase: Failed to send ${events.length} events. Reason: ${e}`\n );\n throw e;\n }\n }\n}\n","export function newSessionId(): string {\n const epochInSeconds = Math.floor(Date.now() / 1000).toString();\n const random = Math.floor(Math.random() * 100000000)\n .toString()\n .padStart(8, \"0\");\n\n return epochInSeconds + random;\n}\n","// Session expires after 1 hour of inactivity\nexport const SESSION_TIMEOUT = 60 * 60 * 1000;\n\n// Flush events every 60 seconds in production, or 2 seconds in development\nexport const FLUSH_INTERVAL = __DEV__ ? 2000 : 60000;\n\n// List of hosts for each region\n// To use a self-hosted (SH) deployment, the host must be set during init\nexport const HOSTS: { [region: string]: string } = {\n US: \"https://us.aptabase.com\",\n EU: \"https://eu.aptabase.com\",\n DEV: \"http://localhost:3000\",\n SH: \"\",\n};\n","import type { Platform } from \"react-native\";\nimport type { AptabaseOptions } from \"./types\";\nimport type { EnvironmentInfo } from \"./env\";\nimport { EventDispatcher } from \"./dispatcher\";\nimport { newSessionId } from \"./session\";\nimport { HOSTS, SESSION_TIMEOUT } from \"./constants\";\n\nexport class AptabaseClient {\n private readonly _dispatcher: EventDispatcher;\n private readonly _env: EnvironmentInfo;\n private _sessionId = newSessionId();\n private _lastTouched = new Date();\n private _flushTimer: NodeJS.Timeout | undefined;\n\n constructor(appKey: string, env: EnvironmentInfo, options?: AptabaseOptions) {\n const [_, region] = appKey.split(\"-\");\n const baseUrl = this.getBaseUrl(region, options);\n\n this._env = { ...env };\n if (options?.appVersion) {\n this._env.appVersion = options.appVersion;\n }\n\n this._dispatcher = new EventDispatcher(appKey, baseUrl, env);\n }\n\n public trackEvent(\n eventName: string,\n props?: Record\n ) {\n this._dispatcher.enqueue({\n timestamp: new Date().toISOString(),\n sessionId: this.evalSessionId(),\n eventName: eventName,\n systemProps: {\n isDebug: this._env.isDebug,\n locale: this._env.locale,\n osName: this._env.osName,\n osVersion: this._env.osVersion,\n appVersion: this._env.appVersion,\n appBuildNumber: this._env.appBuildNumber,\n sdkVersion: this._env.sdkVersion,\n },\n props: props,\n });\n }\n\n public startPolling(flushInterval: number) {\n this.stopPolling();\n\n this._flushTimer = setInterval(this.flush.bind(this), flushInterval);\n }\n\n public stopPolling() {\n if (this._flushTimer) {\n clearInterval(this._flushTimer);\n this._flushTimer = undefined;\n }\n }\n\n public flush(): Promise {\n return this._dispatcher.flush();\n }\n\n private evalSessionId() {\n let now = new Date();\n const diffInMs = now.getTime() - this._lastTouched.getTime();\n if (diffInMs > SESSION_TIMEOUT) {\n this._sessionId = newSessionId();\n }\n this._lastTouched = now;\n\n return this._sessionId;\n }\n\n private getBaseUrl(region: string, options?: AptabaseOptions): string {\n if (region === \"SH\") {\n return options?.host ?? HOSTS.DEV;\n }\n\n return HOSTS[region];\n }\n}\n","import type { Platform } from \"react-native\";\nimport { HOSTS } from \"./constants\";\n\nimport type { AptabaseOptions } from \"./types\";\n\nexport function validate(\n platform: typeof Platform.OS,\n appKey: string,\n options?: AptabaseOptions\n): [boolean, string] {\n if (platform !== \"android\" && platform !== \"ios\") {\n return [false, \"This SDK is only supported on Android and iOS\"];\n }\n\n const parts = appKey.split(\"-\");\n if (parts.length !== 3 || HOSTS[parts[1]] === undefined) {\n return [false, `App Key \"${appKey}\" is invalid`];\n }\n\n if (parts[1] === \"SH\" && !options?.host) {\n return [\n false,\n `Host parameter must be defined when using Self-Hosted App Key`,\n ];\n }\n\n return [true, \"\"];\n}\n","import { init, trackEvent } from \"./track\";\nimport { createContext, useEffect, type ReactNode } from \"react\";\nimport { AptabaseOptions } from \"./types\";\n\ntype ContextProps = {};\n\nexport type AptabaseClient = {\n trackEvent: typeof trackEvent;\n};\n\nconst AptabaseContext = createContext({});\n\ntype Props = {\n appKey: string;\n options?: AptabaseOptions;\n children: ReactNode;\n};\n\nexport function AptabaseProvider({ appKey, options, children }: Props) {\n useEffect(() => {\n init(appKey, options);\n }, [appKey, options]);\n\n return (\n {children}\n );\n}\n\nexport function useAptabase(): AptabaseClient {\n return { trackEvent };\n}\n","export type { AptabaseOptions } from \"./types\";\nexport { AptabaseProvider, useAptabase } from \"./context\";\nimport { init, trackEvent, dispose } from \"./track\";\nexport { init, trackEvent, dispose };\n\nexport default { init, trackEvent, dispose };\n"],"mappings":"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","names":["Platform","NativeModules","RNAptabaseModule","_a","_b","_c","_d","_e","Version","version_default","sdkVersion","getEnvironmentInfo","osName","osVersion","getOperatingSystem","locale","version_default","Platform","AppState","Platform","EventDispatcher","appKey","baseUrl","env","__publicField","evt","__async","failedEvents","eventsToSend","e","events","res","reason","newSessionId","epochInSeconds","random","FLUSH_INTERVAL","HOSTS","AptabaseClient","appKey","env","options","__publicField","newSessionId","_","region","baseUrl","__spreadValues","EventDispatcher","eventName","props","flushInterval","now","_a","HOSTS","validate","platform","appKey","options","parts","HOSTS","_client","init","appKey","options","_a","ok","msg","validate","Platform","env","getEnvironmentInfo","AptabaseClient","flushInterval","FLUSH_INTERVAL","AppState","next","dispose","trackEvent","eventName","props","isPlainObject","val","createContext","useEffect","jsx","AptabaseContext","AptabaseProvider","appKey","options","children","init","useAptabase","trackEvent","src_default","init","trackEvent","dispose"]} +\ No newline at end of file +diff --git a/ios/RNAptabaseModule.swift b/ios/RNAptabaseModule.swift +index 2930d13d133a3f7d4528797125993ff15d6051d8..98c3563026ff3f1ffb3a6789cd0632ca3ca87d75 100644 +--- a/ios/RNAptabaseModule.swift ++++ b/ios/RNAptabaseModule.swift +@@ -2,12 +2,20 @@ import Foundation + + @objc(RNAptabaseModule) + class RNAptabaseModule: NSObject { ++ + @objc + func constantsToExport() -> [AnyHashable : Any]! { + return [ + "appVersion": Bundle.main.infoDictionary?["CFBundleShortVersionString"] as Any, +- "appBuildNumber": Bundle.main.infoDictionary?["CFBundleVersion"] as Any +- ] ++ "appBuildNumber": Bundle.main.infoDictionary?["CFBundleVersion"] as Any, ++ "isiOSAppOnMac": { ++ if #available(iOS 14.0, *) { ++ return ProcessInfo.processInfo.isiOSAppOnMac ++ } else { ++ return false ++ } ++ }() ++ ] + } + + @objc