diff --git a/.github/workflows/build-and-quality-checks-v2.yml b/.github/workflows/build-and-quality-checks-v2.yml
index bb4df1d2..d4f19e91 100644
--- a/.github/workflows/build-and-quality-checks-v2.yml
+++ b/.github/workflows/build-and-quality-checks-v2.yml
@@ -7,33 +7,33 @@ on:
jobs:
build:
name: Code Quality Checks(v2)
- runs-on: macOS-latest
+ runs-on: macos-latest
steps:
- name: Checkout source branch
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Install xcpretty
run: gem install xcpretty
- - name: Select Xcode version
- run: sudo xcode-select -s '/Applications/Xcode_13.2.1.app/Contents/Developer'
+# - name: Select Xcode version
+# run: sudo xcode-select -s '/Applications/Xcode_13.2.1.app/Contents/Developer'
- name: Build SDK(iOS)
run: |
- xcodebuild build -scheme RudderSDK-iOS -workspace Rudder.xcworkspace -destination 'platform=iOS Simulator,name=iPhone 13' | xcpretty
+ xcodebuild build -scheme Rudder-iOS -workspace Rudder.xcworkspace -destination 'platform=iOS Simulator,name=iPhone 14' | xcpretty
- name: Build SDK(watchOS)
run: |
- xcodebuild build -scheme RudderSDK-iOS -workspace Rudder.xcworkspace -destination 'platform=watchOS Simulator,name=Apple Watch Series 7 - 45mm' | xcpretty
+ xcodebuild build -scheme Rudder-watchOS -workspace Rudder.xcworkspace -destination 'platform=watchOS Simulator,name=Apple Watch Series 7 (45mm)' | xcpretty
- name: Build SDK(tvOS)
run: |
- xcodebuild build -scheme RudderSDK-iOS -workspace Rudder.xcworkspace -destination 'platform=tvOS Simulator,name=Apple TV' | xcpretty
+ xcodebuild build -scheme Rudder-tvOS -workspace Rudder.xcworkspace -destination 'platform=tvOS Simulator,name=Apple TV' | xcpretty
- - name: Build SDK(macOS)
- run: |
- xcodebuild build -scheme RudderSDK-iOS -workspace Rudder.xcworkspace -destination 'platform=macOS,variant=Mac Catalyst' | xcpretty
+# - name: Build SDK(macOS)
+# run: |
+# xcodebuild build -scheme Rudder-macOS -workspace Rudder.xcworkspace -destination 'platform=macOS,variant=Mac Catalyst' | xcpretty
- name: Install Cocoapods
run: gem install cocoapods
diff --git a/.github/workflows/check-pr-title-v2.yml b/.github/workflows/check-pr-title-v2.yml
index 56e0577a..5e79e878 100644
--- a/.github/workflows/check-pr-title-v2.yml
+++ b/.github/workflows/check-pr-title-v2.yml
@@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout source branch
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Check PR title
uses: rudderlabs/github-action-check-pr-title@v1.0.7
diff --git a/.github/workflows/deploy-cocoapods-v2.yml b/.github/workflows/deploy-cocoapods-v2.yml
index 5366c7a4..f0af24ea 100644
--- a/.github/workflows/deploy-cocoapods-v2.yml
+++ b/.github/workflows/deploy-cocoapods-v2.yml
@@ -7,13 +7,13 @@ on:
jobs:
build:
name: Deploy to Cocoapods
- runs-on: macOS-latest
+ runs-on: macos-latest
steps:
- name: Checkout source branch
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- - name: Select Xcode version
- run: sudo xcode-select -s '/Applications/Xcode_13.2.1.app/Contents/Developer'
+# - name: Select Xcode version
+# run: sudo xcode-select -s '/Applications/Xcode_13.2.1.app/Contents/Developer'
- name: Install Cocoapods
run: gem install cocoapods
diff --git a/.github/workflows/draft-new-beta-release.yml b/.github/workflows/draft-new-beta-release.yml
new file mode 100644
index 00000000..8786616a
--- /dev/null
+++ b/.github/workflows/draft-new-beta-release.yml
@@ -0,0 +1,103 @@
+name: Draft new Beta release
+
+on:
+ workflow_dispatch:
+ inputs:
+ beta_version:
+ description: "Beta version(Only single digit, example: 1)"
+ required: true
+
+jobs:
+ draft-new-beta-release:
+ name: Draft a new Beta release
+ runs-on: ubuntu-latest
+ if: startsWith(github.ref, 'refs/heads/fix/') || startsWith(github.ref, 'refs/heads/feat/')
+ steps:
+ - name: Checkout source branch
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Set Node 16
+ uses: actions/setup-node@v3
+ with:
+ node-version: 16
+
+ # In order to make a commit, we need to initialize a user.
+ # You may choose to write something less generic here if you want, it doesn't matter functionality wise.
+ - name: Initialize mandatory git config
+ run: |
+ git config user.name "GitHub actions"
+ git config user.email noreply@github.com
+
+ # Calculate the next release version based on conventional semantic release
+ - name: Create release branch
+ id: create-release
+ env:
+ HUSKY: 0
+ run: |
+ source_branch_name=${GITHUB_REF##*/}
+ release_type=beta-release
+ git fetch origin master-v2
+ git fetch --tags origin
+ git merge origin/master-v2
+ current_version=$(jq -r .version package.json)
+
+ npx standard-version --skip.commit --skip.tag --skip.changelog
+ new_version="$(jq -r .version package.json).beta.${{ github.event.inputs.beta_version }}"
+ git reset --hard
+
+ branch_name="${release_type}/${new_version}"
+
+ echo "Source branch for new release is $source_branch_name"
+ echo "Current version is $current_version"
+ echo "Release type is $release_type"
+ echo "New version is $new_version"
+ echo "New release branch name is $branch_name"
+ git checkout -b "$branch_name"
+ git push --set-upstream origin "$branch_name"
+
+ echo "source_branch_name=$source_branch_name" >> $GITHUB_OUTPUT
+ echo "branch_name=$branch_name" >> $GITHUB_OUTPUT
+ echo "new_version=$new_version" >> $GITHUB_OUTPUT
+ echo "CURRENT_VERSION_VALUE=$current_version" >> $GITHUB_ENV
+ echo "NEW_VERSION_VALUE=$new_version" >> $GITHUB_ENV
+
+ - name: Bump version
+ id: finish-release
+ env:
+ HUSKY: 0
+ run: |
+ echo "Current version: $CURRENT_VERSION_VALUE"
+ echo "New version: $NEW_VERSION_VALUE"
+ npx replace $CURRENT_VERSION_VALUE $NEW_VERSION_VALUE package.json
+ git add package.json
+ echo ${{ steps.create-release.outputs.new_version }}
+ echo "commit_summary=$SUMMARY" >> $GITHUB_OUTPUT
+ git commit -m "chore(beta-relase): $NEW_VERSION_VALUE"
+ git tag -a "v$NEW_VERSION_VALUE" -m "chore: release v$NEW_VERSION_VALUE"
+ git push origin "v$NEW_VERSION_VALUE"
+
+ - name: Push new version in release branch & tag
+ run: |
+ git push
+
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ ref: '${{ steps.create-release.outputs.branch_name }}'
+
+ - name: Install Cocoapods
+ run: gem install cocoapods
+
+ - name: 'Convert podspec to podspec.json'
+ run: |
+ pod ipc spec Rudder.podspec > Rudder.podspec.json
+
+ - name: Add Private Spec Repo to CocoaPods installation
+ run: |
+ pod repo add rudderlabs https://${{secrets.PAT_USERNAME}}:${{secrets.PAT}}@github.com/rudderlabs/Specs.git
+
+ - name: Add Podspec to repo
+ run: |
+ pod repo push rudderlabs Rudder.podspec.json
diff --git a/.github/workflows/draft-new-release-v2.yml b/.github/workflows/draft-new-release-v2.yml
index e735c7ce..2a26fb00 100644
--- a/.github/workflows/draft-new-release-v2.yml
+++ b/.github/workflows/draft-new-release-v2.yml
@@ -10,7 +10,7 @@ jobs:
if: startsWith(github.ref, 'refs/heads/develop-v2') || startsWith(github.ref, 'refs/heads/hotfix-v2/')
steps:
- name: Checkout source branch
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
diff --git a/.github/workflows/publish-new-release-v2.yml b/.github/workflows/publish-new-release-v2.yml
index 1cada18a..cffe3fc3 100644
--- a/.github/workflows/publish-new-release-v2.yml
+++ b/.github/workflows/publish-new-release-v2.yml
@@ -22,7 +22,7 @@ jobs:
echo "release_version=$VERSION" >> $GITHUB_OUTPUT
- name: Checkout source branch
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
with:
fetch-depth: 0
diff --git a/.github/workflows/test-v2.yml b/.github/workflows/test-v2.yml
index 0f1335d4..44bb24c8 100644
--- a/.github/workflows/test-v2.yml
+++ b/.github/workflows/test-v2.yml
@@ -10,36 +10,42 @@ on:
jobs:
build:
name: 'Tests & Coverage(v2)'
- runs-on: macOS-latest
-
+ runs-on: macos-latest
+ env:
+ BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory # Directory where build-wrapper output will be placed
steps:
- name: Checkout
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
+
+ - name: Install sonar-scanner and build-wrapper
+ uses: SonarSource/sonarcloud-github-c-cpp@v2
- name: Install xcpretty
run: gem install xcpretty
-# - name: Run tests(suite)
-# run: |
-# xcodebuild -scheme RudderSDK-iOS test -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 13' | xcpretty
-
-# - name: Run tests(1)
-# run: |
-# xcodebuild -scheme RudderSDK-iOS test -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 13' -only-testing "Tests/Tests" | xcpretty
-
-# - name: Run tests(2)
-# run: |
-# xcodebuild -scheme RudderSDK-iOS test -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 13' -only-testing "Tests/Tests2" | xcpretty
-
-# - name: Run tests(3)
-# run: |
-# xcodebuild -scheme RudderSDK-iOS test -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 13' -only-testing "Tests/Tests3" | xcpretty
-
- - name: Install SonarCloud
- run: npm install -g sonarqube-scanner
-
+ - name: Run tests(iOS)
+ run: |
+ xcodebuild -workspace Rudder.xcworkspace -scheme RudderTests-iOS test -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -enableCodeCoverage YES -derivedDataPath build | xcpretty
+
+ - name: Run tests(tvOS)
+ run: |
+ xcodebuild -workspace Rudder.xcworkspace -scheme RudderTests-tvOS test -sdk appletvsimulator -destination 'platform=tvOS Simulator,name=Apple TV' -enableCodeCoverage YES -derivedDataPath build | xcpretty
+
+ - name: Run tests(watchOS)
+ run: |
+ xcodebuild -workspace Rudder.xcworkspace -scheme RudderTests-watchOS test -sdk watchsimulator -destination 'platform=watchOS Simulator,name=Apple Watch Series 7 (45mm)' -enableCodeCoverage YES -derivedDataPath build | xcpretty
+
+ - name: Collect coverage into one XML report
+ run: |
+ bash xccov-to-generic.sh build/Logs/Test/*.xcresult/ > generic-coverage.xml
+
- name: SonarCloud Scan
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
sonar-scanner -Dsonar.host.url=https://sonarcloud.io
+
+ - name: Upload coverage reports to Codecov
+ uses: codecov/codecov-action@v3
+ env:
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 715d357e..8746c6ff 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,6 +88,12 @@ fastlane/test_output
# https://github.com/johnno1962/injectionforxcode
iOSInjectionProject/
-Configuration.json
.DS_Store
-.scannerwork
\ No newline at end of file
+.scannerwork
+
+# Sonar
+relative_or_absolute_path_to_cache_location
+compile_commands.json
+GoogleService-Info.plist
+RudderConfig.plist
+configuration.json
\ No newline at end of file
diff --git a/.swiftlint.yml b/.swiftlint.yml
index fbcddbc6..25debb45 100644
--- a/.swiftlint.yml
+++ b/.swiftlint.yml
@@ -14,7 +14,7 @@ excluded: # paths to ignore during linting. Takes precedence over `included`.
- Carthage
- Pods
- Examples
-
+ - RudderTests
analyzer_rules: # Rules run by `swiftlint analyze` (experimental)
- explicit_self
diff --git a/Examples/RudderConfig/RudderConfig.swift b/Examples/RudderConfig/RudderConfig.swift
new file mode 100644
index 00000000..4efa2614
--- /dev/null
+++ b/Examples/RudderConfig/RudderConfig.swift
@@ -0,0 +1,30 @@
+//
+// RudderConfig.swift
+// RudderOneTrust
+//
+// Created by Pallab Maiti on 26/01/23.
+//
+
+import Foundation
+
+@objc
+class RudderConfig: NSObject, Codable {
+ @objc let WRITE_KEY: String
+ @objc let PROD_DATA_PLANE_URL: String
+ @objc let PROD_CONTROL_PLANE_URL: String
+ @objc let LOCAL_DATA_PLANE_URL: String
+ @objc let LOCAL_CONTROL_PLANE_URL: String
+ @objc let DEV_DATA_PLANE_URL: String
+ @objc let DEV_CONTROL_PLANE_URL: String
+ @objc let STORAGE_LOCATION: String
+ @objc let DOMAIN_IDENTIFIER: String
+
+ @objc
+ class func create(from url: URL) -> RudderConfig? {
+ if let data = try? Data(contentsOf: url),
+ let rudderConfig = try? PropertyListDecoder().decode(RudderConfig.self, from: data) {
+ return rudderConfig
+ }
+ return nil
+ }
+}
diff --git a/Examples/RudderConfig/SampleRudderConfig.plist b/Examples/RudderConfig/SampleRudderConfig.plist
new file mode 100644
index 00000000..4e130dde
--- /dev/null
+++ b/Examples/RudderConfig/SampleRudderConfig.plist
@@ -0,0 +1,24 @@
+
+
+
+
+ WRITE_KEY
+
+ PROD_DATA_PLANE_URL
+
+ PROD_CONTROL_PLANE_URL
+
+ LOCAL_DATA_PLANE_URL
+
+ LOCAL_CONTROL_PLANE_URL
+
+ DEV_DATA_PLANE_URL
+
+ DEV_CONTROL_PLANE_URL
+
+ STORAGE_LOCATION
+
+ DOMAIN_IDENTIFIER
+
+
+
diff --git a/Examples/SampleObjC-tvOS/SampleObjC-tvOS/AppDelegate.m b/Examples/SampleObjC-tvOS/SampleObjC-tvOS/AppDelegate.m
index 43eb00d4..02f9ffd5 100644
--- a/Examples/SampleObjC-tvOS/SampleObjC-tvOS/AppDelegate.m
+++ b/Examples/SampleObjC-tvOS/SampleObjC-tvOS/AppDelegate.m
@@ -27,6 +27,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
[config dataPlaneURL:DATA_PLANE_URL];
[config trackLifecycleEvents:YES];
[config recordScreenViews:YES];
+ [config loglevel:RSLogLevelDebug];
client = [RSClient sharedInstance];
[client configureWith:config];
[client track:@"track 1"];
diff --git a/Examples/SampleObjC-watchOS/SampleObjC-watchOS.xcodeproj/xcshareddata/xcschemes/SampleObjC-watchOS WatchKit App (Complication).xcscheme b/Examples/SampleObjC-watchOS/SampleObjC-watchOS.xcodeproj/xcshareddata/xcschemes/SampleObjC-watchOS WatchKit App (Complication).xcscheme
new file mode 100644
index 00000000..de302bc2
--- /dev/null
+++ b/Examples/SampleObjC-watchOS/SampleObjC-watchOS.xcodeproj/xcshareddata/xcschemes/SampleObjC-watchOS WatchKit App (Complication).xcscheme
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Examples/SampleObjC-watchOS/SampleObjC-watchOS.xcodeproj/xcshareddata/xcschemes/SampleObjC-watchOS WatchKit App (Notification).xcscheme b/Examples/SampleObjC-watchOS/SampleObjC-watchOS.xcodeproj/xcshareddata/xcschemes/SampleObjC-watchOS WatchKit App (Notification).xcscheme
new file mode 100644
index 00000000..e073099b
--- /dev/null
+++ b/Examples/SampleObjC-watchOS/SampleObjC-watchOS.xcodeproj/xcshareddata/xcschemes/SampleObjC-watchOS WatchKit App (Notification).xcscheme
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Examples/SampleObjC-watchOS/SampleObjC-watchOS.xcodeproj/xcshareddata/xcschemes/SampleObjC-watchOS WatchKit App.xcscheme b/Examples/SampleObjC-watchOS/SampleObjC-watchOS.xcodeproj/xcshareddata/xcschemes/SampleObjC-watchOS WatchKit App.xcscheme
new file mode 100644
index 00000000..7895bc57
--- /dev/null
+++ b/Examples/SampleObjC-watchOS/SampleObjC-watchOS.xcodeproj/xcshareddata/xcschemes/SampleObjC-watchOS WatchKit App.xcscheme
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Examples/SampleSwift-iOS/SampleSwift-iOS.xcodeproj/project.pbxproj b/Examples/SampleSwift-iOS/SampleSwift-iOS.xcodeproj/project.pbxproj
index e092456b..df91196f 100644
--- a/Examples/SampleSwift-iOS/SampleSwift-iOS.xcodeproj/project.pbxproj
+++ b/Examples/SampleSwift-iOS/SampleSwift-iOS.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 51;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -14,7 +14,12 @@
06EABC8F24665E480043D720 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 06EABC8E24665E480043D720 /* Assets.xcassets */; };
06EABC9224665E480043D720 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 06EABC9024665E480043D720 /* LaunchScreen.storyboard */; };
1BBDBFA2CA1F65262723A637 /* Pods_SampleSwift_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72016B33854F923C48E9084A /* Pods_SampleSwift_iOS.framework */; };
+ ED333EC62B2358B4003EB0B3 /* RudderConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = ED333EC32B2358B4003EB0B3 /* RudderConfig.plist */; };
+ ED333EC72B2358B4003EB0B3 /* SampleRudderConfig.plist in Resources */ = {isa = PBXBuildFile; fileRef = ED333EC42B2358B4003EB0B3 /* SampleRudderConfig.plist */; };
+ ED333EC82B2358B4003EB0B3 /* RudderConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED333EC52B2358B4003EB0B3 /* RudderConfig.swift */; };
+ ED333ECA2B235D8E003EB0B3 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = ED333EC92B235D8E003EB0B3 /* GoogleService-Info.plist */; };
ED4EACA127F5718100207AF1 /* RSCustomDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4EACA027F5718100207AF1 /* RSCustomDestination.swift */; };
+ EDC1BBC82B0B2E7D00211F24 /* Configuration.json in Resources */ = {isa = PBXBuildFile; fileRef = EDC1BBC72B0B2E7D00211F24 /* Configuration.json */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -29,7 +34,12 @@
6AF9E4CE2308F413BD375A80 /* Pods-SampleSwift-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleSwift-iOS.debug.xcconfig"; path = "Target Support Files/Pods-SampleSwift-iOS/Pods-SampleSwift-iOS.debug.xcconfig"; sourceTree = ""; };
72016B33854F923C48E9084A /* Pods_SampleSwift_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SampleSwift_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
80FF9E334811B6015D51C152 /* Pods-SampleSwift-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SampleSwift-iOS.release.xcconfig"; path = "Target Support Files/Pods-SampleSwift-iOS/Pods-SampleSwift-iOS.release.xcconfig"; sourceTree = ""; };
+ ED333EC32B2358B4003EB0B3 /* RudderConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = RudderConfig.plist; sourceTree = ""; };
+ ED333EC42B2358B4003EB0B3 /* SampleRudderConfig.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = SampleRudderConfig.plist; sourceTree = ""; };
+ ED333EC52B2358B4003EB0B3 /* RudderConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RudderConfig.swift; sourceTree = ""; };
+ ED333EC92B235D8E003EB0B3 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
ED4EACA027F5718100207AF1 /* RSCustomDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSCustomDestination.swift; sourceTree = ""; };
+ EDC1BBC72B0B2E7D00211F24 /* Configuration.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = Configuration.json; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -65,6 +75,8 @@
06EABC8424665E470043D720 /* SampleSwift-iOS */ = {
isa = PBXGroup;
children = (
+ ED333EC22B2358B4003EB0B3 /* RudderConfig */,
+ ED333EC92B235D8E003EB0B3 /* GoogleService-Info.plist */,
06EABC8524665E470043D720 /* AppDelegate.swift */,
ED4EACA027F5718100207AF1 /* RSCustomDestination.swift */,
06EABC8724665E470043D720 /* SceneDelegate.swift */,
@@ -73,6 +85,7 @@
06EABC8E24665E480043D720 /* Assets.xcassets */,
06EABC9024665E480043D720 /* LaunchScreen.storyboard */,
06EABC9324665E480043D720 /* Info.plist */,
+ EDC1BBC72B0B2E7D00211F24 /* Configuration.json */,
);
path = "SampleSwift-iOS";
sourceTree = "";
@@ -95,6 +108,17 @@
name = Frameworks;
sourceTree = "";
};
+ ED333EC22B2358B4003EB0B3 /* RudderConfig */ = {
+ isa = PBXGroup;
+ children = (
+ ED333EC32B2358B4003EB0B3 /* RudderConfig.plist */,
+ ED333EC52B2358B4003EB0B3 /* RudderConfig.swift */,
+ ED333EC42B2358B4003EB0B3 /* SampleRudderConfig.plist */,
+ );
+ name = RudderConfig;
+ path = ../../RudderConfig;
+ sourceTree = "";
+ };
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -155,9 +179,13 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ ED333EC72B2358B4003EB0B3 /* SampleRudderConfig.plist in Resources */,
06EABC9224665E480043D720 /* LaunchScreen.storyboard in Resources */,
06EABC8F24665E480043D720 /* Assets.xcassets in Resources */,
+ ED333EC62B2358B4003EB0B3 /* RudderConfig.plist in Resources */,
+ EDC1BBC82B0B2E7D00211F24 /* Configuration.json in Resources */,
06EABC8D24665E470043D720 /* Main.storyboard in Resources */,
+ ED333ECA2B235D8E003EB0B3 /* GoogleService-Info.plist in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -211,6 +239,7 @@
buildActionMask = 2147483647;
files = (
06EABC8A24665E470043D720 /* ViewController.swift in Sources */,
+ ED333EC82B2358B4003EB0B3 /* RudderConfig.swift in Sources */,
06EABC8624665E470043D720 /* AppDelegate.swift in Sources */,
06EABC8824665E470043D720 /* SceneDelegate.swift in Sources */,
ED4EACA127F5718100207AF1 /* RSCustomDestination.swift in Sources */,
@@ -370,7 +399,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
- PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.ios.test.swift;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.swift.ios.v2;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -393,7 +422,7 @@
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.0;
- PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.ios.test.swift;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.swift.ios.v2;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
diff --git a/Examples/SampleSwift-iOS/SampleSwift-iOS.xcodeproj/xcshareddata/xcschemes/SampleSwift-iOS.xcscheme b/Examples/SampleSwift-iOS/SampleSwift-iOS.xcodeproj/xcshareddata/xcschemes/SampleSwift-iOS.xcscheme
index 3d1f2e51..fe24778c 100644
--- a/Examples/SampleSwift-iOS/SampleSwift-iOS.xcodeproj/xcshareddata/xcschemes/SampleSwift-iOS.xcscheme
+++ b/Examples/SampleSwift-iOS/SampleSwift-iOS.xcodeproj/xcshareddata/xcschemes/SampleSwift-iOS.xcscheme
@@ -50,6 +50,12 @@
ReferencedContainer = "container:SampleSwift-iOS.xcodeproj">
+
+
+
+
Bool {
- /// Create a `Configuration.json` file on root directory. The JSON should be look like:
- /// {
- /// "WRITE_KEY": "WRITE_KEY_VALUE",
- /// "DATA_PLANE_URL": "DATA_PLANE_URL_VALUE",
- /// "CONTROL_PLANE_URL": "CONTROL_PLANE_URL_VALUE"
- /// }
+ guard let path = Bundle.main.path(forResource: "RudderConfig", ofType: "plist"),
+ let data = try? Data(contentsOf: URL(fileURLWithPath: path)),
+ let rudderConfig = try? PropertyListDecoder().decode(RudderConfig.self, from: data) else {
+ return true
+ }
- let filePath = URL(fileURLWithPath: #file).pathComponents.dropLast().dropLast().dropLast().dropLast().joined(separator: "/").replacingOccurrences(of: "//", with: "/") + "/Configuration.json"
- do {
- let jsonString = try String(contentsOfFile: filePath, encoding: .utf8)
- let jsonData = Data(jsonString.utf8)
- let configuration = try JSONDecoder().decode(Configuration.self, from: jsonData)
-
- let config: RSConfig = RSConfig(writeKey: configuration.WRITE_KEY)
- .dataPlaneURL(configuration.DATA_PLANE_URL)
- .loglevel(.verbose)
- .trackLifecycleEvents(false)
- .recordScreenViews(true)
- .flushQueueSize(8)
-// .sleepTimeOut(1)
- RSClient.sharedInstance().configure(with: config)
+ print(NSHomeDirectory())
- /*client?.addDestination(CustomDestination())
+ let config: RSConfig = RSConfig(writeKey: rudderConfig.WRITE_KEY)
+ .dataPlaneURL(rudderConfig.DEV_DATA_PLANE_URL)
+// .controlPlaneURL(rudderConfig.DEV_CONTROL_PLANE_URL)
+ .controlPlaneURL("https://e2e6fd4f-c24c-43d6-8ca3-11a11e7cc7d5.mock.pstmn.io") // disabled
+// .controlPlaneURL("https://98e2b8de-9984-471b-a705-b1bcf3f9f6ba.mock.pstmn.io") // enabled
+ .loglevel(.verbose)
+ .trackLifecycleEvents(true)
+ .recordScreenViews(true)
+ .sleepTimeOut(20)
- client?.setAppTrackingConsent(.authorize)
- client?.setAnonymousId("example_anonymous_id")
- client?.setAdvertisingId(getIDFA())
- client?.setDeviceToken("example_device_token")*/
+ RSClient.sharedInstance().configure(with: config)
- /*client?.setOptOutStatus(true)
- client?.reset()
-
- let traits = client?.traits
- let defaultOption = RSOption()
- defaultOption.putIntegration("Amplitude", isEnabled: true)
- client?.setOption(defaultOption)
- let messageOption = RSOption()
- messageOption.putIntegration("MoEngage", isEnabled: true)
- messageOption.putExternalId("", withId: "")
- client?.identify("Track 2", traits: ["email": "abc@def.com"], option: messageOption)*/
- } catch { }
+ RSClient.sharedInstance().addDestination(RudderAmplitudeDestination())
+ RSClient.sharedInstance().addDestination(RudderFirebaseDestination())
+
return true
}
@@ -79,9 +63,3 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return ASIdentifierManager.shared().advertisingIdentifier.uuidString
}
}
-
-struct Configuration: Codable {
- let DATA_PLANE_URL: String
- let CONTROL_PLANE_URL: String
- let WRITE_KEY: String
-}
diff --git a/Examples/SampleSwift-iOS/SampleSwift-iOS/ViewController.swift b/Examples/SampleSwift-iOS/SampleSwift-iOS/ViewController.swift
index ba57c712..b1f9fe1a 100644
--- a/Examples/SampleSwift-iOS/SampleSwift-iOS/ViewController.swift
+++ b/Examples/SampleSwift-iOS/SampleSwift-iOS/ViewController.swift
@@ -22,16 +22,42 @@ class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
- let taskList: [Task] = [Task(name: "Identify"),
- Task(name: "Single Track"),
- Task(name: "Multiple Track"),
- Task(name: "Single Flush"),
- Task(name: "Multiple Flush From Background"),
- Task(name: "Alias"),
- Task(name: "Multiple Flush and Multiple Track"),
- Task(name: "Screen without properties"),
- Task(name: "Screen with properties"),
- Task(name: "Reset")]
+ let taskList: [Task] = [
+ Task(name: "Identify with traits"),
+ Task(name: "Identify without traits"),
+ Task(name: "Single Track with properties"),
+ Task(name: "Single Track without properties"),
+ Task(name: "Alias"),
+ Task(name: "Screen with properties"),
+ Task(name: "Screen without properties"),
+ Task(name: "Group with traits"),
+ Task(name: "Group without traits"),
+ Task(name: "Set AnonymousId"),
+ Task(name: "Set Device Token"),
+ Task(name: "Set AdvertisingId"),
+ Task(name: "Opt In"),
+ Task(name: "Opt Out"),
+ Task(name: "Reset"),
+ Task(name: "Single Flush"),
+ Task(name: "Update AnonymousId"),
+ Task(name: "Update Device Token"),
+ Task(name: "Update AdvertisingId"),
+ Task(name: "Set Option at root level"),
+ Task(name: "Set Option at identify"),
+ Task(name: "Set Option at track"),
+ Task(name: "Start session"),
+ Task(name: "End session"),
+ Task(name: "Start session with id"),
+ Task(name: "Get Context"),
+ Task(name: "Allowlist track"),
+ Task(name: "Denylist track"),
+ Task(name: "Order done"),
+ Task(name: "Multiple Track"),
+ Task(name: "Multiple Flush From Background"),
+ Task(name: "Multiple Flush and Multiple Track"),
+ Task(name: "Multiple Track, Screen, Alias, Group, Identify"),
+ Task(name: "Multiple Track, Screen, Alias, Group, Identify, Device Token, AnonymousId, AdvertisingId, AppTracking Consent")
+ ]
override func viewDidLoad() {
super.viewDidLoad()
@@ -56,18 +82,21 @@ extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
switch indexPath.row {
- case 0:
- RSClient.sharedInstance().identify("test_user_id", traits: [
- "integerValue": 42,
- "stringValue": "Hello, World!",
- "boolValue": true,
- "doubleValue": 3.14159,
- "arrayValue": [1, 2, 3, 4, 5],
- "dictionaryValue": ["key1": "value1", "key2": "value2"],
- "urlValue": URL(string: "https://www.example.com")!,
- "dateValue": Date()
- ])
- case 1:
+ case 0:
+ RSClient.sharedInstance().identify("test_user_id", traits: [
+ "integerValue": 42,
+ "stringValue": "Hello, World!",
+ "boolValue": true,
+ "doubleValue": 3.14159,
+ "arrayValue": [1, 2, 3, 4, 5],
+ "dictionaryValue": ["key1": "value1", "key2": "value2"],
+ "urlValue": URL(string: "https://www.example.com")!,
+ "dateValue": Date()
+ ])
+ case 1:
+ RSClient.sharedInstance().identify("test_user_id")
+
+ case 2:
RSClient.sharedInstance().track("single_track_call", properties: [
"integerValue": 42,
"stringValue": "Hello, World!",
@@ -78,12 +107,115 @@ extension ViewController: UITableViewDataSource, UITableViewDelegate {
"urlValue": URL(string: "https://www.example.com")!,
"dateValue": Date()
])
- case 2:
+ case 3:
+ RSClient.sharedInstance().track("single_track_call")
+ case 4:
+ RSClient.sharedInstance().alias("new_user_id")
+ case 5:
+ RSClient.sharedInstance().screen("ViewController", properties: ["key_1": "value_1"])
+ case 6:
+ RSClient.sharedInstance().screen("ViewController")
+ case 7:
+ RSClient.sharedInstance().group("test_group_id", traits: ["key_1": "value_1"])
+ case 8:
+ RSClient.sharedInstance().group("test_group_id")
+ case 9:
+ RSClient.sharedInstance().setAnonymousId("anonymous_id_1")
+ case 10:
+ RSClient.sharedInstance().setDeviceToken("device_token_1")
+ case 11:
+ RSClient.sharedInstance().setAdvertisingId("advertising_id_1")
+ case 12:
+ RSClient.sharedInstance().setOptOutStatus(false)
+ case 13:
+ RSClient.sharedInstance().setOptOutStatus(true)
+ case 14:
+ RSClient.sharedInstance().reset()
+ case 15:
+ RSClient.sharedInstance().flush()
+ case 16:
+ RSClient.sharedInstance().setAnonymousId("anonymous_id_2")
+ case 17:
+ RSClient.sharedInstance().setDeviceToken("device_token_2")
+ case 18:
+ RSClient.sharedInstance().setAdvertisingId("advertising_id_2")
+ case 19:
+ let option = RSOption()
+
+ option.putIntegration("key-5", isEnabled: true)
+ option.putIntegration("key-6", isEnabled: true)
+ option.putIntegration("key-7", isEnabled: true)
+ option.putIntegration("key-8", isEnabled: false)
+
+ RSClient.sharedInstance().setOption(option)
+ case 20:
+ let option = RSOption()
+ option.putExternalId("key-1", withId: "value-1")
+ option.putExternalId("key-2", withId: "value-2")
+
+ option.putIntegration("key-5", isEnabled: true)
+ option.putIntegration("key-6", isEnabled: true)
+ option.putIntegration("key-7", isEnabled: false)
+ option.putIntegration("key-8", isEnabled: false)
+
+ option.putCustomContext(["Key-01": "value-1"], withKey: "key-9")
+ option.putCustomContext(["Key-02": "value-1"], withKey: "key-10")
+ option.putCustomContext(["Key-03": "value-1"], withKey: "key-11")
+ option.putCustomContext(["Key-04": "value-1"], withKey: "key-12")
+ RSClient.sharedInstance().identify("test_user_id", option: option)
+ case 21:
+ let option = RSOption()
+ option.putExternalId("key-3", withId: "value-3")
+ option.putExternalId("key-4", withId: "value-4")
+
+ option.putIntegration("key-5", isEnabled: false)
+ option.putIntegration("key-6", isEnabled: true)
+ option.putIntegration("key-7", isEnabled: false)
+ option.putIntegration("key-8", isEnabled: true)
+
+ option.putCustomContext(["Key-01": "value-1"], withKey: "key-9")
+ option.putCustomContext(["Key-02": "value-2"], withKey: "key-10")
+ RSClient.sharedInstance().track("single_track_call", option: option)
+ case 22:
+ RSClient.sharedInstance().startSession()
+ case 23:
+ RSClient.sharedInstance().endSession()
+ case 24:
+ RSClient.sharedInstance().startSession(1234567890)
+ case 25:
+ if let context = RSClient.sharedInstance().context {
+ print(context.dictionaryValue)
+ }
+ case 26:
+ RSClient.sharedInstance().track("allow_list_track", properties: [
+ "integerValue": 42,
+ "stringValue": "Hello, World!",
+ "boolValue": true,
+ "doubleValue": 3.14159,
+ "arrayValue": [1, 2, 3, 4, 5],
+ "dictionaryValue": ["key1": "value1", "key2": Date(), "key-3": ["key1": URL(string: "https://www.example.com")!, "key2": Date()] as [String : Any]] as [String : Any],
+ "urlValue": URL(string: "https://www.example.com")!,
+ "dateValue": Date()
+ ])
+ case 27:
+ RSClient.sharedInstance().track("deny_list_track", properties: [
+ "integerValue": 42,
+ "stringValue": "Hello, World!",
+ "boolValue": true,
+ "doubleValue": 3.14159,
+ "arrayValue": [1, 2, 3, 4, 5],
+ "dictionaryValue": ["key1": "value1", "key2": Date(), "key-3": ["key1": URL(string: "https://www.example.com")!, "key2": Date()] as [String : Any]] as [String : Any],
+ "urlValue": URL(string: "https://www.example.com")!,
+ "dateValue": Date()
+ ])
+ case 28:
+ RSClient.sharedInstance().track("Order Done", properties: getProperties())
+ case 29:
+ RSClient.sharedInstance().track("Order Completed", properties: getProperties())
+ /*case 2:
for i in 1...50 {
RSClient.sharedInstance().track("Track \(i)", properties: ["time": Date().timeIntervalSince1970])
}
- case 3:
- RSClient.sharedInstance().flush()
case 4:
DispatchQueue.global(qos: .background).async {
for i in 1...1000 {
@@ -104,10 +236,8 @@ extension ViewController: UITableViewDataSource, UITableViewDelegate {
print("From Thread 3, Flush No. \(i)")
RSClient.sharedInstance().flush()
}
- }
- case 5:
- RSClient.sharedInstance().alias("new_user_id")
- case 6:
+ }*/
+ /*case 6:
DispatchQueue.global(qos: .background).async {
for i in 1...1000 {
print("From Thread 1A, Track No. \(i)")
@@ -149,14 +279,127 @@ extension ViewController: UITableViewDataSource, UITableViewDelegate {
RSClient.sharedInstance().flush()
}
}
- case 7:
- RSClient.sharedInstance().screen("ViewController")
- case 8:
- RSClient.sharedInstance().screen("ViewController", properties: ["key_1": "value_1"])
case 9:
- RSClient.sharedInstance().reset()
+ DispatchQueue.global(qos: .background).async {
+ for i in 1...1000 {
+ print("From Thread 1A, Track No. \(i)")
+ RSClient.sharedInstance().track("Track \(i)", properties: ["time": Date().timeIntervalSince1970])
+ }
+ }
+
+ DispatchQueue.global(qos: .background).async {
+ for i in 1001...2000 {
+ print("From Thread 2A, Screen No. \(i)")
+ RSClient.sharedInstance().screen("Screen \(i)", properties: ["time": Date().timeIntervalSince1970])
+ }
+ }
+
+ DispatchQueue.global(qos: .background).async {
+ for i in 2001...3000 {
+ print("From Thread 3A, Group No. \(i)")
+ RSClient.sharedInstance().group("Group \(i)", traits: ["time": "\(Date().timeIntervalSince1970)"])
+ }
+ }
+
+ DispatchQueue.global(qos: .background).async {
+ for i in 3001...4000 {
+ print("From Thread 4A, Alias No. \(i)")
+ RSClient.sharedInstance().alias("Alias \(i)")
+ }
+ }
+
+ DispatchQueue.global(qos: .background).async {
+ for i in 4001...5000 {
+ print("From Thread 5A, Identify No. \(i)")
+ RSClient.sharedInstance().identify("Identify \(i)", traits: ["time": Date().timeIntervalSince1970])
+ }
+ }
+ case 10:
+ DispatchQueue.global(qos: .background).async {
+ for i in 1...1000 {
+ print("From Thread 1A, Track No. \(i)")
+ if i % 2 == 0 {
+ RSClient.sharedInstance().track("Track \(i)", properties: ["time": Date().timeIntervalSince1970])
+ } else {
+ RSClient.sharedInstance().setAdvertisingId("Advertising Id \(i)")
+ }
+ }
+ }
+
+ DispatchQueue.global(qos: .background).async {
+ for i in 1001...2000 {
+ print("From Thread 2A, Screen No. \(i)")
+ if i % 2 == 0 {
+ RSClient.sharedInstance().screen("Screen \(i)", properties: ["time": Date().timeIntervalSince1970])
+ } else {
+ RSClient.sharedInstance().setAnonymousId("Anonymous Id \(i)")
+ }
+ }
+ }
+
+ DispatchQueue.global(qos: .background).async {
+ for i in 2001...3000 {
+ print("From Thread 3A, Group No. \(i)")
+ if i % 2 == 0 {
+ RSClient.sharedInstance().group("Group \(i)", traits: ["time": "\(Date().timeIntervalSince1970)"])
+ } else {
+ RSClient.sharedInstance().setDeviceToken("Device Token \(i)")
+ }
+ }
+ }
+
+ DispatchQueue.global(qos: .background).async {
+ for i in 3001...4000 {
+ print("From Thread 4A, Alias No. \(i)")
+ if i % 2 == 0 {
+ RSClient.sharedInstance().alias("Alias \(i)")
+ } else {
+ RSClient.sharedInstance().setAppTrackingConsent(.authorize)
+ }
+ }
+ }
+
+ DispatchQueue.global(qos: .background).async {
+ for i in 4001...5000 {
+ print("From Thread 5A, Identify No. \(i)")
+ if i % 2 == 0 {
+ RSClient.sharedInstance().identify("Identify \(i)", traits: ["time": Date().timeIntervalSince1970])
+ } else {
+ RSClient.sharedInstance().setDeviceToken("Device Token \(i)")
+ RSClient.sharedInstance().setAppTrackingConsent(.authorize)
+ }
+ }
+ }
+ */
default:
break
}
}
+
+ func getProperties() -> [String: Any] {
+ let products: [String: Any] = [
+ RSKeys.Ecommerce.productId: "1001",
+ RSKeys.Ecommerce.productName: "Books-1",
+ RSKeys.Ecommerce.category: "Books",
+ RSKeys.Ecommerce.sku: "Books-sku",
+ RSKeys.Ecommerce.quantity: 2,
+ RSKeys.Ecommerce.price: 1203.2
+ ]
+ let fullPath = getDocumentsDirectory().appendingPathComponent("randomFilename")
+ func getDocumentsDirectory() -> URL {
+ let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
+ return paths[0]
+ }
+ let properties: [String: Any] = [
+ RSKeys.Ecommerce.products: [products],
+ "optOutOfSession": true,
+ RSKeys.Ecommerce.revenue: 1203,
+ RSKeys.Ecommerce.quantity: 10,
+ RSKeys.Ecommerce.price: 101.34,
+ RSKeys.Ecommerce.productId: "123",
+ "revenue_type": "revenue_type_value",
+ "receipt": fullPath
+ ]
+ return properties
+ }
}
diff --git a/Examples/SampleSwift-macOS/SampleSwift-macOS.xcodeproj/project.pbxproj b/Examples/SampleSwift-macOS/SampleSwift-macOS.xcodeproj/project.pbxproj
index 036a77c1..7da87de6 100644
--- a/Examples/SampleSwift-macOS/SampleSwift-macOS.xcodeproj/project.pbxproj
+++ b/Examples/SampleSwift-macOS/SampleSwift-macOS.xcodeproj/project.pbxproj
@@ -344,7 +344,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = GTGKNDBD23;
+ DEVELOPMENT_TEAM = WPX9KRKA8B;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
@@ -375,7 +375,7 @@
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = GTGKNDBD23;
+ DEVELOPMENT_TEAM = WPX9KRKA8B;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
diff --git a/Examples/SampleSwift-macOS/SampleSwift-macOS.xcodeproj/xcshareddata/xcschemes/SampleSwift-macOS.xcscheme b/Examples/SampleSwift-macOS/SampleSwift-macOS.xcodeproj/xcshareddata/xcschemes/SampleSwift-macOS.xcscheme
new file mode 100644
index 00000000..bdaf0c14
--- /dev/null
+++ b/Examples/SampleSwift-macOS/SampleSwift-macOS.xcodeproj/xcshareddata/xcschemes/SampleSwift-macOS.xcscheme
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Podfile b/Podfile
index 884783b2..69cedde3 100644
--- a/Podfile
+++ b/Podfile
@@ -17,6 +17,8 @@ end
target 'SampleSwift-iOS' do
project 'Examples/SampleSwift-iOS/SampleSwift-iOS.xcodeproj'
platform :ios, '13.0'
+ pod 'RudderFirebase', '1.1.0'
+ pod 'RudderAmplitude', '1.1.0'
shared_pods
end
diff --git a/Podfile.lock b/Podfile.lock
index dba67f38..8c4981ea 100644
--- a/Podfile.lock
+++ b/Podfile.lock
@@ -1,16 +1,142 @@
PODS:
- - Rudder (2.3.0)
+ - Amplitude (8.8.0):
+ - AnalyticsConnector (~> 1.0.0)
+ - AnalyticsConnector (1.0.3)
+ - FirebaseAnalytics (9.2.0):
+ - FirebaseAnalytics/AdIdSupport (= 9.2.0)
+ - FirebaseCore (~> 9.0)
+ - FirebaseInstallations (~> 9.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 7.7)
+ - GoogleUtilities/MethodSwizzler (~> 7.7)
+ - GoogleUtilities/Network (~> 7.7)
+ - "GoogleUtilities/NSData+zlib (~> 7.7)"
+ - nanopb (< 2.30910.0, >= 2.30908.0)
+ - FirebaseAnalytics/AdIdSupport (9.2.0):
+ - FirebaseCore (~> 9.0)
+ - FirebaseInstallations (~> 9.0)
+ - GoogleAppMeasurement (= 9.2.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 7.7)
+ - GoogleUtilities/MethodSwizzler (~> 7.7)
+ - GoogleUtilities/Network (~> 7.7)
+ - "GoogleUtilities/NSData+zlib (~> 7.7)"
+ - nanopb (< 2.30910.0, >= 2.30908.0)
+ - FirebaseCore (9.6.0):
+ - FirebaseCoreDiagnostics (~> 9.0)
+ - FirebaseCoreInternal (~> 9.0)
+ - GoogleUtilities/Environment (~> 7.7)
+ - GoogleUtilities/Logger (~> 7.7)
+ - FirebaseCoreDiagnostics (9.6.0):
+ - GoogleDataTransport (< 10.0.0, >= 9.1.4)
+ - GoogleUtilities/Environment (~> 7.7)
+ - GoogleUtilities/Logger (~> 7.7)
+ - nanopb (< 2.30910.0, >= 2.30908.0)
+ - FirebaseCoreInternal (9.6.0):
+ - "GoogleUtilities/NSData+zlib (~> 7.7)"
+ - FirebaseInstallations (9.6.0):
+ - FirebaseCore (~> 9.0)
+ - GoogleUtilities/Environment (~> 7.7)
+ - GoogleUtilities/UserDefaults (~> 7.7)
+ - PromisesObjC (~> 2.1)
+ - GoogleAppMeasurement (9.2.0):
+ - GoogleAppMeasurement/AdIdSupport (= 9.2.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 7.7)
+ - GoogleUtilities/MethodSwizzler (~> 7.7)
+ - GoogleUtilities/Network (~> 7.7)
+ - "GoogleUtilities/NSData+zlib (~> 7.7)"
+ - nanopb (< 2.30910.0, >= 2.30908.0)
+ - GoogleAppMeasurement/AdIdSupport (9.2.0):
+ - GoogleAppMeasurement/WithoutAdIdSupport (= 9.2.0)
+ - GoogleUtilities/AppDelegateSwizzler (~> 7.7)
+ - GoogleUtilities/MethodSwizzler (~> 7.7)
+ - GoogleUtilities/Network (~> 7.7)
+ - "GoogleUtilities/NSData+zlib (~> 7.7)"
+ - nanopb (< 2.30910.0, >= 2.30908.0)
+ - GoogleAppMeasurement/WithoutAdIdSupport (9.2.0):
+ - GoogleUtilities/AppDelegateSwizzler (~> 7.7)
+ - GoogleUtilities/MethodSwizzler (~> 7.7)
+ - GoogleUtilities/Network (~> 7.7)
+ - "GoogleUtilities/NSData+zlib (~> 7.7)"
+ - nanopb (< 2.30910.0, >= 2.30908.0)
+ - GoogleDataTransport (9.3.0):
+ - GoogleUtilities/Environment (~> 7.7)
+ - nanopb (< 2.30910.0, >= 2.30908.0)
+ - PromisesObjC (< 3.0, >= 1.2)
+ - GoogleUtilities/AppDelegateSwizzler (7.12.0):
+ - GoogleUtilities/Environment
+ - GoogleUtilities/Logger
+ - GoogleUtilities/Network
+ - GoogleUtilities/Environment (7.12.0):
+ - PromisesObjC (< 3.0, >= 1.2)
+ - GoogleUtilities/Logger (7.12.0):
+ - GoogleUtilities/Environment
+ - GoogleUtilities/MethodSwizzler (7.12.0):
+ - GoogleUtilities/Logger
+ - GoogleUtilities/Network (7.12.0):
+ - GoogleUtilities/Logger
+ - "GoogleUtilities/NSData+zlib"
+ - GoogleUtilities/Reachability
+ - "GoogleUtilities/NSData+zlib (7.12.0)"
+ - GoogleUtilities/Reachability (7.12.0):
+ - GoogleUtilities/Logger
+ - GoogleUtilities/UserDefaults (7.12.0):
+ - GoogleUtilities/Logger
+ - nanopb (2.30909.1):
+ - nanopb/decode (= 2.30909.1)
+ - nanopb/encode (= 2.30909.1)
+ - nanopb/decode (2.30909.1)
+ - nanopb/encode (2.30909.1)
+ - PromisesObjC (2.3.1)
+ - Rudder (2.4.2)
+ - RudderAmplitude (1.1.0):
+ - Amplitude (= 8.8.0)
+ - Rudder (~> 2.0)
+ - RudderFirebase (1.1.0):
+ - FirebaseAnalytics (= 9.2.0)
+ - Rudder (~> 2.0)
DEPENDENCIES:
- Rudder (from `.`)
+ - RudderAmplitude (= 1.1.0)
+ - RudderFirebase (= 1.1.0)
+
+SPEC REPOS:
+ https://github.com/CocoaPods/Specs.git:
+ - Amplitude
+ - AnalyticsConnector
+ - FirebaseAnalytics
+ - FirebaseCore
+ - FirebaseCoreDiagnostics
+ - FirebaseCoreInternal
+ - FirebaseInstallations
+ - GoogleAppMeasurement
+ - GoogleDataTransport
+ - GoogleUtilities
+ - nanopb
+ - PromisesObjC
+ - RudderAmplitude
+ - RudderFirebase
EXTERNAL SOURCES:
Rudder:
:path: "."
SPEC CHECKSUMS:
- Rudder: 368691bcf2588f00cc99004cbc2026675b9cb16f
+ Amplitude: 710116f3539c225e86fb70a8abdcd20015683132
+ AnalyticsConnector: a53214d38ae22734c6266106c0492b37832633a9
+ FirebaseAnalytics: af5a03a8dff7648c7b8486f6a78b1368e0268dd3
+ FirebaseCore: 2082fffcd855f95f883c0a1641133eb9bbe76d40
+ FirebaseCoreDiagnostics: 99a495094b10a57eeb3ae8efa1665700ad0bdaa6
+ FirebaseCoreInternal: bca76517fe1ed381e989f5e7d8abb0da8d85bed3
+ FirebaseInstallations: 0a115432c4e223c5ab20b0dbbe4cbefa793a0e8e
+ GoogleAppMeasurement: 7a33224321f975d58c166657260526775d9c6b1a
+ GoogleDataTransport: 57c22343ab29bc686febbf7cbb13bad167c2d8fe
+ GoogleUtilities: 0759d1a57ebb953965c2dfe0ba4c82e95ccc2e34
+ nanopb: d4d75c12cd1316f4a64e3c6963f879ecd4b5e0d5
+ PromisesObjC: c50d2056b5253dadbd6c2bea79b0674bd5a52fa4
+ Rudder: d40c784d899ea76dab14808054120383d95379ae
+ RudderAmplitude: 5e7cdf892e635d2814258e217632ce18c196a79c
+ RudderFirebase: 37388a4c3c82a9938aef238eaaedb50bb183094d
-PODFILE CHECKSUM: ee379229e6a0b60bc98226700ace2de002171547
+PODFILE CHECKSUM: 96bec7fcdef20abbb7e05c8f937ef34333f65557
-COCOAPODS: 1.11.3
+COCOAPODS: 1.14.2
diff --git a/Rudder.xcodeproj/project.pbxproj b/Rudder.xcodeproj/project.pbxproj
index ad9ca08a..a379b078 100644
--- a/Rudder.xcodeproj/project.pbxproj
+++ b/Rudder.xcodeproj/project.pbxproj
@@ -10,23 +10,22 @@
8C6EA4432A0BDADF0049569A /* RSUserSessionPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C6EA4422A0BDADF0049569A /* RSUserSessionPlugin.swift */; };
ED05631F291BEB0400BAEE65 /* RSVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED05631E291BEB0400BAEE65 /* RSVersion.swift */; };
ED157C3727CE0EEA00F22202 /* RSmacOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C3627CE0EEA00F22202 /* RSmacOSLifecycleEvents.swift */; };
- ED157C3927CE1C0800F22202 /* RSUserIdPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C3827CE1C0800F22202 /* RSUserIdPlugin.swift */; };
- ED157C4127CFC33800F22202 /* RSAdvertisementIdPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4027CFC33800F22202 /* RSAdvertisementIdPlugin.swift */; };
- ED157C4327CFC6F700F22202 /* RSAnonymousIdPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4227CFC6F700F22202 /* RSAnonymousIdPlugin.swift */; };
ED157C4527CFD99700F22202 /* RSIntegrationPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4427CFD99700F22202 /* RSIntegrationPlugin.swift */; };
- ED157C4727CFDEC000F22202 /* RSOptionPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4627CFDEC000F22202 /* RSOptionPlugin.swift */; };
- ED157C4927CFE6CE00F22202 /* RSAppTrackingConsentPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4827CFE6CE00F22202 /* RSAppTrackingConsentPlugin.swift */; };
ED157C4B27CFE86100F22202 /* RSAppTrackingConsent.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4A27CFE86100F22202 /* RSAppTrackingConsent.swift */; };
ED157C4D27D0A63A00F22202 /* RSiOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4C27D0A63A00F22202 /* RSiOSScreenViewEvents.swift */; };
ED157C4F27D0AC0E00F22202 /* RSwatchOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4E27D0AC0E00F22202 /* RSwatchOSScreenViewEvents.swift */; };
- ED157C5427D0CA6900F22202 /* RSGDPRPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5327D0CA6900F22202 /* RSGDPRPlugin.swift */; };
ED157C5627D0FCDC00F22202 /* RSmacOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5527D0FCDC00F22202 /* RSmacOSScreenViewEvents.swift */; };
ED157C5827D0FFA400F22202 /* RSLifeCycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5727D0FFA400F22202 /* RSLifeCycle.swift */; };
ED157C5A27D1010D00F22202 /* RSPushNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5927D1010D00F22202 /* RSPushNotifications.swift */; };
ED277FA127421B06002A8FEA /* RSEventsAndKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED277FA027421B06002A8FEA /* RSEventsAndKeys.swift */; };
- ED277FF92744F199002A8FEA /* RSAnyCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED277FF82744F199002A8FEA /* RSAnyCodable.swift */; };
- ED277FFB2744F265002A8FEA /* RSAnyDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED277FFA2744F265002A8FEA /* RSAnyDecodable.swift */; };
- ED277FFD2744F2AD002A8FEA /* RSAnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED277FFC2744F2AD002A8FEA /* RSAnyEncodable.swift */; };
+ ED333EB72B21F324003EB0B3 /* RSSessionStoragePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED333EB62B21F324003EB0B3 /* RSSessionStoragePlugin.swift */; };
+ ED333EB82B21F324003EB0B3 /* RSSessionStoragePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED333EB62B21F324003EB0B3 /* RSSessionStoragePlugin.swift */; };
+ ED333EB92B21F324003EB0B3 /* RSSessionStoragePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED333EB62B21F324003EB0B3 /* RSSessionStoragePlugin.swift */; };
+ ED333EBA2B21F324003EB0B3 /* RSSessionStoragePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED333EB62B21F324003EB0B3 /* RSSessionStoragePlugin.swift */; };
+ ED333EBC2B22055D003EB0B3 /* RSContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED333EBB2B22055D003EB0B3 /* RSContext.swift */; };
+ ED333EBD2B22055D003EB0B3 /* RSContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED333EBB2B22055D003EB0B3 /* RSContext.swift */; };
+ ED333EBE2B22055D003EB0B3 /* RSContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED333EBB2B22055D003EB0B3 /* RSContext.swift */; };
+ ED333EBF2B22055D003EB0B3 /* RSContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED333EBB2B22055D003EB0B3 /* RSContext.swift */; };
ED3D225B279EAC2800EC8366 /* Rudder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06CABB842630C3CA0097BEFF /* Rudder.framework */; };
ED3D229427A3F0C100EC8366 /* RSClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226227A3F0C100EC8366 /* RSClient.swift */; };
ED3D229527A3F0C100EC8366 /* Vendor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226627A3F0C100EC8366 /* Vendor.swift */; };
@@ -41,14 +40,25 @@
ED3D22A427A3F0C100EC8366 /* RSReplayQueuePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227A27A3F0C100EC8366 /* RSReplayQueuePlugin.swift */; };
ED3D22A527A3F0C100EC8366 /* RudderDestinationPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227B27A3F0C100EC8366 /* RudderDestinationPlugin.swift */; };
ED3D22A627A3F0C100EC8366 /* RSContextPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227C27A3F0C100EC8366 /* RSContextPlugin.swift */; };
- ED3D22A727A3F0C100EC8366 /* RSDeviceTokenPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227D27A3F0C100EC8366 /* RSDeviceTokenPlugin.swift */; };
ED3D22A827A3F0C100EC8366 /* RSController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227E27A3F0C100EC8366 /* RSController.swift */; };
ED3D22AB27A3F0C100EC8366 /* RSPlugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D228127A3F0C100EC8366 /* RSPlugins.swift */; };
ED3D22AC27A3F0C100EC8366 /* RSClient+Plugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D228227A3F0C100EC8366 /* RSClient+Plugins.swift */; };
ED3D22BA27A3F0C100EC8366 /* RSMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D229227A3F0C100EC8366 /* RSMessage.swift */; };
ED3D22BE27A45B6500EC8366 /* RSTypeAlias.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D22BD27A45B6500EC8366 /* RSTypeAlias.swift */; };
- ED4EACA927F5EA1F00207AF1 /* RSIdentifyTraitsPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4EACA827F5EA1F00207AF1 /* RSIdentifyTraitsPlugin.swift */; };
- ED4EACAB27F5F03C00207AF1 /* RSAliasIdPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED4EACAA27F5F03C00207AF1 /* RSAliasIdPlugin.swift */; };
+ ED53723C2B15C32000D794EB /* Rudder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDC1BC972B0DD89400211F24 /* Rudder.framework */; };
+ ED53723D2B15C32900D794EB /* Rudder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDC1BC522B0DD88A00211F24 /* Rudder.framework */; };
+ ED53723E2B15C33300D794EB /* Rudder.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EDC1BC0D2B0DD87D00211F24 /* Rudder.framework */; };
+ ED5372462B1613CE00D794EB /* LogMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5372452B1613CE00D794EB /* LogMessages.swift */; };
+ ED5372472B1613CE00D794EB /* LogMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5372452B1613CE00D794EB /* LogMessages.swift */; };
+ ED5372482B1613CE00D794EB /* LogMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5372452B1613CE00D794EB /* LogMessages.swift */; };
+ ED5372492B1613CE00D794EB /* LogMessages.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5372452B1613CE00D794EB /* LogMessages.swift */; };
+ ED53724B2B18ED8E00D794EB /* MockURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED53724A2B18ED8E00D794EB /* MockURLProtocol.swift */; };
+ ED53724C2B18ED8E00D794EB /* MockURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED53724A2B18ED8E00D794EB /* MockURLProtocol.swift */; };
+ ED53724D2B18ED8E00D794EB /* MockURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED53724A2B18ED8E00D794EB /* MockURLProtocol.swift */; };
+ ED53724E2B18ED8E00D794EB /* MockURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED53724A2B18ED8E00D794EB /* MockURLProtocol.swift */; };
+ ED5603852881C691004B5BEC /* RSUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5603842881C691004B5BEC /* RSUserInfo.swift */; };
+ ED5603872882CE6D004B5BEC /* RSSessionStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5603862882CE6D004B5BEC /* RSSessionStorage.swift */; };
+ ED560389288316C2004B5BEC /* Data+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED560388288316C2004B5BEC /* Data+Ext.swift */; };
EDA7EF752739119600E73142 /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF332739119600E73142 /* API.swift */; };
EDA7EF762739119600E73142 /* RSServiceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF342739119600E73142 /* RSServiceManager.swift */; };
EDA7EF812739119600E73142 /* RSDatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF402739119600E73142 /* RSDatabaseManager.swift */; };
@@ -56,12 +66,10 @@
EDA7EF852739119600E73142 /* RSConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF462739119600E73142 /* RSConstants.swift */; };
EDA7EF862739119600E73142 /* String+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF482739119600E73142 /* String+Ext.swift */; };
EDA7EF872739119600E73142 /* NSError+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF492739119600E73142 /* NSError+Ext.swift */; };
- EDA7EF882739119600E73142 /* UserDefaults+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF4A2739119600E73142 /* UserDefaults+Ext.swift */; };
EDA7EF8A2739119600E73142 /* RSUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF4D2739119600E73142 /* RSUtils.swift */; };
EDA7EF8B2739119600E73142 /* Rudder.h in Headers */ = {isa = PBXBuildFile; fileRef = EDA7EF4F2739119600E73142 /* Rudder.h */; settings = {ATTRIBUTES = (Public, ); }; };
EDA7EF8D2739119600E73142 /* RSMessageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF532739119600E73142 /* RSMessageType.swift */; };
EDA7EF8F2739119600E73142 /* RSErrorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF552739119600E73142 /* RSErrorCode.swift */; };
- EDA7EF902739119600E73142 /* RSLogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF562739119600E73142 /* RSLogLevel.swift */; };
EDA7EF912739119600E73142 /* RSDBMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF582739119600E73142 /* RSDBMessage.swift */; };
EDA7EF922739119600E73142 /* RSConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF592739119600E73142 /* RSConfig.swift */; };
EDA7EF962739119600E73142 /* RSOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF5D2739119600E73142 /* RSOption.swift */; };
@@ -72,21 +80,214 @@
EDA7EFA22739119600E73142 /* RSServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF6B2739119600E73142 /* RSServiceType.swift */; };
EDC1327C27D614C400AFD833 /* RSClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1327B27D614C400AFD833 /* RSClientTests.swift */; };
EDC132A227D7D61D00AFD833 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132A127D7D61D00AFD833 /* JSON.swift */; };
- EDC132A427D8D55700AFD833 /* RSTrackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132A327D8D55600AFD833 /* RSTrackTests.swift */; };
- EDC132A627D8D5F300AFD833 /* RSIdentifyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132A527D8D5F300AFD833 /* RSIdentifyTests.swift */; };
- EDC132A827D8D61700AFD833 /* RSScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132A727D8D61700AFD833 /* RSScreenTests.swift */; };
- EDC132AA27D8D63D00AFD833 /* RSAliasTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132A927D8D63D00AFD833 /* RSAliasTests.swift */; };
- EDC132AC27D8D64E00AFD833 /* RSGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132AB27D8D64E00AFD833 /* RSGroupTests.swift */; };
EDC132AE27D9104700AFD833 /* RSBlackListedEventsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132AD27D9104700AFD833 /* RSBlackListedEventsTest.swift */; };
EDC132B027D9106500AFD833 /* RSWhiteListedEventsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132AF27D9106500AFD833 /* RSWhiteListedEventsTests.swift */; };
EDC14DDE2859C7DB00E2E6FE /* RSRepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC14DDD2859C7DB00E2E6FE /* RSRepeatingTimer.swift */; };
+ EDC1BBCB2B0DD87D00211F24 /* Rudder.h in Headers */ = {isa = PBXBuildFile; fileRef = EDA7EF4F2739119600E73142 /* Rudder.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EDC1BBCD2B0DD87D00211F24 /* RSUserSessionPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C6EA4422A0BDADF0049569A /* RSUserSessionPlugin.swift */; };
+ EDC1BBCE2B0DD87D00211F24 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132A127D7D61D00AFD833 /* JSON.swift */; };
+ EDC1BBCF2B0DD87D00211F24 /* RSiOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226E27A3F0C100EC8366 /* RSiOSLifecycleEvents.swift */; };
+ EDC1BBD02B0DD87D00211F24 /* RSServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF6B2739119600E73142 /* RSServiceType.swift */; };
+ EDC1BBD12B0DD87D00211F24 /* NSError+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF492739119600E73142 /* NSError+Ext.swift */; };
+ EDC1BBD32B0DD87D00211F24 /* RSDestinationConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF622739119600E73142 /* RSDestinationConfig.swift */; };
+ EDC1BBD42B0DD87D00211F24 /* RSMessageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF532739119600E73142 /* RSMessageType.swift */; };
+ EDC1BBD52B0DD87D00211F24 /* RudderDestinationPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227B27A3F0C100EC8366 /* RudderDestinationPlugin.swift */; };
+ EDC1BBD62B0DD87D00211F24 /* RSwatchOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226B27A3F0C100EC8366 /* RSwatchOSLifecycleEvents.swift */; };
+ EDC1BBD72B0DD87D00211F24 /* RSErrorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF552739119600E73142 /* RSErrorCode.swift */; };
+ EDC1BBD82B0DD87D00211F24 /* RSSessionStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5603862882CE6D004B5BEC /* RSSessionStorage.swift */; };
+ EDC1BBD92B0DD87D00211F24 /* RSMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D229227A3F0C100EC8366 /* RSMessage.swift */; };
+ EDC1BBDA2B0DD87D00211F24 /* RSwatchOSDelegation.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226A27A3F0C100EC8366 /* RSwatchOSDelegation.swift */; };
+ EDC1BBDB2B0DD87D00211F24 /* RSConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF462739119600E73142 /* RSConstants.swift */; };
+ EDC1BBDC2B0DD87D00211F24 /* RSAtomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD3AA3527C659C80048E61E /* RSAtomic.swift */; };
+ EDC1BBDD2B0DD87D00211F24 /* RSReplayQueuePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227A27A3F0C100EC8366 /* RSReplayQueuePlugin.swift */; };
+ EDC1BBDE2B0DD87D00211F24 /* RSOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF5D2739119600E73142 /* RSOption.swift */; };
+ EDC1BBDF2B0DD87D00211F24 /* RSEventsAndKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED277FA027421B06002A8FEA /* RSEventsAndKeys.swift */; };
+ EDC1BBE02B0DD87D00211F24 /* RSIntegrationPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4427CFD99700F22202 /* RSIntegrationPlugin.swift */; };
+ EDC1BBE12B0DD87D00211F24 /* RSRepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC14DDD2859C7DB00E2E6FE /* RSRepeatingTimer.swift */; };
+ EDC1BBE22B0DD87D00211F24 /* RSmacOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C3627CE0EEA00F22202 /* RSmacOSLifecycleEvents.swift */; };
+ EDC1BBE32B0DD87D00211F24 /* RSAppTrackingConsent.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4A27CFE86100F22202 /* RSAppTrackingConsent.swift */; };
+ EDC1BBE42B0DD87D00211F24 /* RSConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF592739119600E73142 /* RSConfig.swift */; };
+ EDC1BBE52B0DD87D00211F24 /* RSKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD3AA1227C64B430048E61E /* RSKeyPath.swift */; };
+ EDC1BBE62B0DD87D00211F24 /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF332739119600E73142 /* API.swift */; };
+ EDC1BBE72B0DD87D00211F24 /* RSDatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF402739119600E73142 /* RSDatabaseManager.swift */; };
+ EDC1BBE82B0DD87D00211F24 /* RSVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED05631E291BEB0400BAEE65 /* RSVersion.swift */; };
+ EDC1BBE92B0DD87D00211F24 /* RSServerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF612739119600E73142 /* RSServerConfig.swift */; };
+ EDC1BBEA2B0DD87D00211F24 /* RSmacOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227227A3F0C100EC8366 /* RSmacOSLifecycleMonitor.swift */; };
+ EDC1BBEB2B0DD87D00211F24 /* RSiOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227027A3F0C100EC8366 /* RSiOSLifecycleMonitor.swift */; };
+ EDC1BBEC2B0DD87D00211F24 /* RSUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5603842881C691004B5BEC /* RSUserInfo.swift */; };
+ EDC1BBEE2B0DD87D00211F24 /* RSPushNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5927D1010D00F22202 /* RSPushNotifications.swift */; };
+ EDC1BBEF2B0DD87D00211F24 /* RSController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227E27A3F0C100EC8366 /* RSController.swift */; };
+ EDC1BBF12B0DD87D00211F24 /* RSwatchOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4E27D0AC0E00F22202 /* RSwatchOSScreenViewEvents.swift */; };
+ EDC1BBF32B0DD87D00211F24 /* RSTypeAlias.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D22BD27A45B6500EC8366 /* RSTypeAlias.swift */; };
+ EDC1BBF42B0DD87D00211F24 /* RSiOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4C27D0A63A00F22202 /* RSiOSScreenViewEvents.swift */; };
+ EDC1BBF52B0DD87D00211F24 /* RSUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF452739119600E73142 /* RSUserDefaults.swift */; };
+ EDC1BBF62B0DD87D00211F24 /* RSmacOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5527D0FCDC00F22202 /* RSmacOSScreenViewEvents.swift */; };
+ EDC1BBF72B0DD87D00211F24 /* Vendor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226627A3F0C100EC8366 /* Vendor.swift */; };
+ EDC1BBF82B0DD87D00211F24 /* RSLifeCycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5727D0FFA400F22202 /* RSLifeCycle.swift */; };
+ EDC1BBF92B0DD87D00211F24 /* String+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF482739119600E73142 /* String+Ext.swift */; };
+ EDC1BBFA2B0DD87D00211F24 /* RSPlugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D228127A3F0C100EC8366 /* RSPlugins.swift */; };
+ EDC1BBFB2B0DD87D00211F24 /* RSDestinationDefinition.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF632739119600E73142 /* RSDestinationDefinition.swift */; };
+ EDC1BBFC2B0DD87D00211F24 /* RSClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226227A3F0C100EC8366 /* RSClient.swift */; };
+ EDC1BBFD2B0DD87D00211F24 /* AppleUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226727A3F0C100EC8366 /* AppleUtils.swift */; };
+ EDC1BBFE2B0DD87D00211F24 /* RSClient+Plugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D228227A3F0C100EC8366 /* RSClient+Plugins.swift */; };
+ EDC1BBFF2B0DD87D00211F24 /* RSContextPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227C27A3F0C100EC8366 /* RSContextPlugin.swift */; };
+ EDC1BC002B0DD87D00211F24 /* Data+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED560388288316C2004B5BEC /* Data+Ext.swift */; };
+ EDC1BC012B0DD87D00211F24 /* RSServiceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF342739119600E73142 /* RSServiceManager.swift */; };
+ EDC1BC022B0DD87D00211F24 /* RSDBMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF582739119600E73142 /* RSDBMessage.swift */; };
+ EDC1BC032B0DD87D00211F24 /* RSDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF642739119600E73142 /* RSDestination.swift */; };
+ EDC1BC042B0DD87D00211F24 /* RSiOSDelegation.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226F27A3F0C100EC8366 /* RSiOSDelegation.swift */; };
+ EDC1BC052B0DD87D00211F24 /* RSwatchOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226C27A3F0C100EC8366 /* RSwatchOSLifecycleMonitor.swift */; };
+ EDC1BC062B0DD87D00211F24 /* RSUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF4D2739119600E73142 /* RSUtils.swift */; };
+ EDC1BC102B0DD88A00211F24 /* Rudder.h in Headers */ = {isa = PBXBuildFile; fileRef = EDA7EF4F2739119600E73142 /* Rudder.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EDC1BC122B0DD88A00211F24 /* RSUserSessionPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C6EA4422A0BDADF0049569A /* RSUserSessionPlugin.swift */; };
+ EDC1BC132B0DD88A00211F24 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132A127D7D61D00AFD833 /* JSON.swift */; };
+ EDC1BC142B0DD88A00211F24 /* RSiOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226E27A3F0C100EC8366 /* RSiOSLifecycleEvents.swift */; };
+ EDC1BC152B0DD88A00211F24 /* RSServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF6B2739119600E73142 /* RSServiceType.swift */; };
+ EDC1BC162B0DD88A00211F24 /* NSError+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF492739119600E73142 /* NSError+Ext.swift */; };
+ EDC1BC182B0DD88A00211F24 /* RSDestinationConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF622739119600E73142 /* RSDestinationConfig.swift */; };
+ EDC1BC192B0DD88A00211F24 /* RSMessageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF532739119600E73142 /* RSMessageType.swift */; };
+ EDC1BC1A2B0DD88A00211F24 /* RudderDestinationPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227B27A3F0C100EC8366 /* RudderDestinationPlugin.swift */; };
+ EDC1BC1B2B0DD88A00211F24 /* RSwatchOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226B27A3F0C100EC8366 /* RSwatchOSLifecycleEvents.swift */; };
+ EDC1BC1C2B0DD88A00211F24 /* RSErrorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF552739119600E73142 /* RSErrorCode.swift */; };
+ EDC1BC1D2B0DD88A00211F24 /* RSSessionStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5603862882CE6D004B5BEC /* RSSessionStorage.swift */; };
+ EDC1BC1E2B0DD88A00211F24 /* RSMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D229227A3F0C100EC8366 /* RSMessage.swift */; };
+ EDC1BC1F2B0DD88A00211F24 /* RSwatchOSDelegation.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226A27A3F0C100EC8366 /* RSwatchOSDelegation.swift */; };
+ EDC1BC202B0DD88A00211F24 /* RSConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF462739119600E73142 /* RSConstants.swift */; };
+ EDC1BC212B0DD88A00211F24 /* RSAtomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD3AA3527C659C80048E61E /* RSAtomic.swift */; };
+ EDC1BC222B0DD88A00211F24 /* RSReplayQueuePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227A27A3F0C100EC8366 /* RSReplayQueuePlugin.swift */; };
+ EDC1BC232B0DD88A00211F24 /* RSOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF5D2739119600E73142 /* RSOption.swift */; };
+ EDC1BC242B0DD88A00211F24 /* RSEventsAndKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED277FA027421B06002A8FEA /* RSEventsAndKeys.swift */; };
+ EDC1BC252B0DD88A00211F24 /* RSIntegrationPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4427CFD99700F22202 /* RSIntegrationPlugin.swift */; };
+ EDC1BC262B0DD88A00211F24 /* RSRepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC14DDD2859C7DB00E2E6FE /* RSRepeatingTimer.swift */; };
+ EDC1BC272B0DD88A00211F24 /* RSmacOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C3627CE0EEA00F22202 /* RSmacOSLifecycleEvents.swift */; };
+ EDC1BC282B0DD88A00211F24 /* RSAppTrackingConsent.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4A27CFE86100F22202 /* RSAppTrackingConsent.swift */; };
+ EDC1BC292B0DD88A00211F24 /* RSConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF592739119600E73142 /* RSConfig.swift */; };
+ EDC1BC2A2B0DD88A00211F24 /* RSKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD3AA1227C64B430048E61E /* RSKeyPath.swift */; };
+ EDC1BC2B2B0DD88A00211F24 /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF332739119600E73142 /* API.swift */; };
+ EDC1BC2C2B0DD88A00211F24 /* RSDatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF402739119600E73142 /* RSDatabaseManager.swift */; };
+ EDC1BC2D2B0DD88A00211F24 /* RSVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED05631E291BEB0400BAEE65 /* RSVersion.swift */; };
+ EDC1BC2E2B0DD88A00211F24 /* RSServerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF612739119600E73142 /* RSServerConfig.swift */; };
+ EDC1BC2F2B0DD88A00211F24 /* RSmacOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227227A3F0C100EC8366 /* RSmacOSLifecycleMonitor.swift */; };
+ EDC1BC302B0DD88A00211F24 /* RSiOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227027A3F0C100EC8366 /* RSiOSLifecycleMonitor.swift */; };
+ EDC1BC312B0DD88A00211F24 /* RSUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5603842881C691004B5BEC /* RSUserInfo.swift */; };
+ EDC1BC332B0DD88A00211F24 /* RSPushNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5927D1010D00F22202 /* RSPushNotifications.swift */; };
+ EDC1BC342B0DD88A00211F24 /* RSController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227E27A3F0C100EC8366 /* RSController.swift */; };
+ EDC1BC362B0DD88A00211F24 /* RSwatchOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4E27D0AC0E00F22202 /* RSwatchOSScreenViewEvents.swift */; };
+ EDC1BC382B0DD88A00211F24 /* RSTypeAlias.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D22BD27A45B6500EC8366 /* RSTypeAlias.swift */; };
+ EDC1BC392B0DD88A00211F24 /* RSiOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4C27D0A63A00F22202 /* RSiOSScreenViewEvents.swift */; };
+ EDC1BC3A2B0DD88A00211F24 /* RSUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF452739119600E73142 /* RSUserDefaults.swift */; };
+ EDC1BC3B2B0DD88A00211F24 /* RSmacOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5527D0FCDC00F22202 /* RSmacOSScreenViewEvents.swift */; };
+ EDC1BC3C2B0DD88A00211F24 /* Vendor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226627A3F0C100EC8366 /* Vendor.swift */; };
+ EDC1BC3D2B0DD88A00211F24 /* RSLifeCycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5727D0FFA400F22202 /* RSLifeCycle.swift */; };
+ EDC1BC3E2B0DD88A00211F24 /* String+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF482739119600E73142 /* String+Ext.swift */; };
+ EDC1BC3F2B0DD88A00211F24 /* RSPlugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D228127A3F0C100EC8366 /* RSPlugins.swift */; };
+ EDC1BC402B0DD88A00211F24 /* RSDestinationDefinition.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF632739119600E73142 /* RSDestinationDefinition.swift */; };
+ EDC1BC412B0DD88A00211F24 /* RSClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226227A3F0C100EC8366 /* RSClient.swift */; };
+ EDC1BC422B0DD88A00211F24 /* AppleUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226727A3F0C100EC8366 /* AppleUtils.swift */; };
+ EDC1BC432B0DD88A00211F24 /* RSClient+Plugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D228227A3F0C100EC8366 /* RSClient+Plugins.swift */; };
+ EDC1BC442B0DD88A00211F24 /* RSContextPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227C27A3F0C100EC8366 /* RSContextPlugin.swift */; };
+ EDC1BC452B0DD88A00211F24 /* Data+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED560388288316C2004B5BEC /* Data+Ext.swift */; };
+ EDC1BC462B0DD88A00211F24 /* RSServiceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF342739119600E73142 /* RSServiceManager.swift */; };
+ EDC1BC472B0DD88A00211F24 /* RSDBMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF582739119600E73142 /* RSDBMessage.swift */; };
+ EDC1BC482B0DD88A00211F24 /* RSDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF642739119600E73142 /* RSDestination.swift */; };
+ EDC1BC492B0DD88A00211F24 /* RSiOSDelegation.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226F27A3F0C100EC8366 /* RSiOSDelegation.swift */; };
+ EDC1BC4A2B0DD88A00211F24 /* RSwatchOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226C27A3F0C100EC8366 /* RSwatchOSLifecycleMonitor.swift */; };
+ EDC1BC4B2B0DD88A00211F24 /* RSUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF4D2739119600E73142 /* RSUtils.swift */; };
+ EDC1BC552B0DD89400211F24 /* Rudder.h in Headers */ = {isa = PBXBuildFile; fileRef = EDA7EF4F2739119600E73142 /* Rudder.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ EDC1BC572B0DD89400211F24 /* RSUserSessionPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C6EA4422A0BDADF0049569A /* RSUserSessionPlugin.swift */; };
+ EDC1BC582B0DD89400211F24 /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132A127D7D61D00AFD833 /* JSON.swift */; };
+ EDC1BC592B0DD89400211F24 /* RSiOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226E27A3F0C100EC8366 /* RSiOSLifecycleEvents.swift */; };
+ EDC1BC5A2B0DD89400211F24 /* RSServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF6B2739119600E73142 /* RSServiceType.swift */; };
+ EDC1BC5B2B0DD89400211F24 /* NSError+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF492739119600E73142 /* NSError+Ext.swift */; };
+ EDC1BC5D2B0DD89400211F24 /* RSDestinationConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF622739119600E73142 /* RSDestinationConfig.swift */; };
+ EDC1BC5E2B0DD89400211F24 /* RSMessageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF532739119600E73142 /* RSMessageType.swift */; };
+ EDC1BC5F2B0DD89400211F24 /* RudderDestinationPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227B27A3F0C100EC8366 /* RudderDestinationPlugin.swift */; };
+ EDC1BC602B0DD89400211F24 /* RSwatchOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226B27A3F0C100EC8366 /* RSwatchOSLifecycleEvents.swift */; };
+ EDC1BC612B0DD89400211F24 /* RSErrorCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF552739119600E73142 /* RSErrorCode.swift */; };
+ EDC1BC622B0DD89400211F24 /* RSSessionStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5603862882CE6D004B5BEC /* RSSessionStorage.swift */; };
+ EDC1BC632B0DD89400211F24 /* RSMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D229227A3F0C100EC8366 /* RSMessage.swift */; };
+ EDC1BC642B0DD89400211F24 /* RSwatchOSDelegation.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226A27A3F0C100EC8366 /* RSwatchOSDelegation.swift */; };
+ EDC1BC652B0DD89400211F24 /* RSConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF462739119600E73142 /* RSConstants.swift */; };
+ EDC1BC662B0DD89400211F24 /* RSAtomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD3AA3527C659C80048E61E /* RSAtomic.swift */; };
+ EDC1BC672B0DD89400211F24 /* RSReplayQueuePlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227A27A3F0C100EC8366 /* RSReplayQueuePlugin.swift */; };
+ EDC1BC682B0DD89400211F24 /* RSOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF5D2739119600E73142 /* RSOption.swift */; };
+ EDC1BC692B0DD89400211F24 /* RSEventsAndKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED277FA027421B06002A8FEA /* RSEventsAndKeys.swift */; };
+ EDC1BC6A2B0DD89400211F24 /* RSIntegrationPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4427CFD99700F22202 /* RSIntegrationPlugin.swift */; };
+ EDC1BC6B2B0DD89400211F24 /* RSRepeatingTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC14DDD2859C7DB00E2E6FE /* RSRepeatingTimer.swift */; };
+ EDC1BC6C2B0DD89400211F24 /* RSmacOSLifecycleEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C3627CE0EEA00F22202 /* RSmacOSLifecycleEvents.swift */; };
+ EDC1BC6D2B0DD89400211F24 /* RSAppTrackingConsent.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4A27CFE86100F22202 /* RSAppTrackingConsent.swift */; };
+ EDC1BC6E2B0DD89400211F24 /* RSConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF592739119600E73142 /* RSConfig.swift */; };
+ EDC1BC6F2B0DD89400211F24 /* RSKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD3AA1227C64B430048E61E /* RSKeyPath.swift */; };
+ EDC1BC702B0DD89400211F24 /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF332739119600E73142 /* API.swift */; };
+ EDC1BC712B0DD89400211F24 /* RSDatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF402739119600E73142 /* RSDatabaseManager.swift */; };
+ EDC1BC722B0DD89400211F24 /* RSVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED05631E291BEB0400BAEE65 /* RSVersion.swift */; };
+ EDC1BC732B0DD89400211F24 /* RSServerConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF612739119600E73142 /* RSServerConfig.swift */; };
+ EDC1BC742B0DD89400211F24 /* RSmacOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227227A3F0C100EC8366 /* RSmacOSLifecycleMonitor.swift */; };
+ EDC1BC752B0DD89400211F24 /* RSiOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227027A3F0C100EC8366 /* RSiOSLifecycleMonitor.swift */; };
+ EDC1BC762B0DD89400211F24 /* RSUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5603842881C691004B5BEC /* RSUserInfo.swift */; };
+ EDC1BC782B0DD89400211F24 /* RSPushNotifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5927D1010D00F22202 /* RSPushNotifications.swift */; };
+ EDC1BC792B0DD89400211F24 /* RSController.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227E27A3F0C100EC8366 /* RSController.swift */; };
+ EDC1BC7B2B0DD89400211F24 /* RSwatchOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4E27D0AC0E00F22202 /* RSwatchOSScreenViewEvents.swift */; };
+ EDC1BC7D2B0DD89400211F24 /* RSTypeAlias.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D22BD27A45B6500EC8366 /* RSTypeAlias.swift */; };
+ EDC1BC7E2B0DD89400211F24 /* RSiOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C4C27D0A63A00F22202 /* RSiOSScreenViewEvents.swift */; };
+ EDC1BC7F2B0DD89400211F24 /* RSUserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF452739119600E73142 /* RSUserDefaults.swift */; };
+ EDC1BC802B0DD89400211F24 /* RSmacOSScreenViewEvents.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5527D0FCDC00F22202 /* RSmacOSScreenViewEvents.swift */; };
+ EDC1BC812B0DD89400211F24 /* Vendor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226627A3F0C100EC8366 /* Vendor.swift */; };
+ EDC1BC822B0DD89400211F24 /* RSLifeCycle.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED157C5727D0FFA400F22202 /* RSLifeCycle.swift */; };
+ EDC1BC832B0DD89400211F24 /* String+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF482739119600E73142 /* String+Ext.swift */; };
+ EDC1BC842B0DD89400211F24 /* RSPlugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D228127A3F0C100EC8366 /* RSPlugins.swift */; };
+ EDC1BC852B0DD89400211F24 /* RSDestinationDefinition.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF632739119600E73142 /* RSDestinationDefinition.swift */; };
+ EDC1BC862B0DD89400211F24 /* RSClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226227A3F0C100EC8366 /* RSClient.swift */; };
+ EDC1BC872B0DD89400211F24 /* AppleUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226727A3F0C100EC8366 /* AppleUtils.swift */; };
+ EDC1BC882B0DD89400211F24 /* RSClient+Plugins.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D228227A3F0C100EC8366 /* RSClient+Plugins.swift */; };
+ EDC1BC892B0DD89400211F24 /* RSContextPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227C27A3F0C100EC8366 /* RSContextPlugin.swift */; };
+ EDC1BC8A2B0DD89400211F24 /* Data+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED560388288316C2004B5BEC /* Data+Ext.swift */; };
+ EDC1BC8B2B0DD89400211F24 /* RSServiceManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF342739119600E73142 /* RSServiceManager.swift */; };
+ EDC1BC8C2B0DD89400211F24 /* RSDBMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF582739119600E73142 /* RSDBMessage.swift */; };
+ EDC1BC8D2B0DD89400211F24 /* RSDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF642739119600E73142 /* RSDestination.swift */; };
+ EDC1BC8E2B0DD89400211F24 /* RSiOSDelegation.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226F27A3F0C100EC8366 /* RSiOSDelegation.swift */; };
+ EDC1BC8F2B0DD89400211F24 /* RSwatchOSLifecycleMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D226C27A3F0C100EC8366 /* RSwatchOSLifecycleMonitor.swift */; };
+ EDC1BC902B0DD89400211F24 /* RSUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDA7EF4D2739119600E73142 /* RSUtils.swift */; };
+ EDC1BC9D2B1465AC00211F24 /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1BC992B10A31C00211F24 /* TestUtils.swift */; };
+ EDC1BC9E2B1465AC00211F24 /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1BC992B10A31C00211F24 /* TestUtils.swift */; };
+ EDC1BC9F2B1465AC00211F24 /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1BC992B10A31C00211F24 /* TestUtils.swift */; };
+ EDC1BCA02B1465AC00211F24 /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1BC992B10A31C00211F24 /* TestUtils.swift */; };
+ EDC1BCA52B146A2D00211F24 /* RSClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1327B27D614C400AFD833 /* RSClientTests.swift */; };
+ EDC1BCA62B146A2D00211F24 /* RSmacOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF5728489E2C002B2D46 /* RSmacOSLifeCycleEventTests.swift */; };
+ EDC1BCA72B146A2D00211F24 /* RSwatchOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF5628489E2C002B2D46 /* RSwatchOSLifeCycleEventTests.swift */; };
+ EDC1BCA82B146A2D00211F24 /* RSWhiteListedEventsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132AF27D9106500AFD833 /* RSWhiteListedEventsTests.swift */; };
+ EDC1BCA92B146A2D00211F24 /* RSThreadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD0C96428225BFB00470E88 /* RSThreadTests.swift */; };
+ EDC1BCAA2B146A2D00211F24 /* RSiOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF54284895F9002B2D46 /* RSiOSLifeCycleEventTests.swift */; };
+ EDC1BCAB2B146A2D00211F24 /* RSBlackListedEventsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132AD27D9104700AFD833 /* RSBlackListedEventsTest.swift */; };
+ EDC1BCAC2B146A2D00211F24 /* RSDatabaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD0C9662829199200470E88 /* RSDatabaseTests.swift */; };
+ EDC1BCB92B146A3800211F24 /* RSClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1327B27D614C400AFD833 /* RSClientTests.swift */; };
+ EDC1BCBA2B146A3800211F24 /* RSmacOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF5728489E2C002B2D46 /* RSmacOSLifeCycleEventTests.swift */; };
+ EDC1BCBB2B146A3800211F24 /* RSwatchOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF5628489E2C002B2D46 /* RSwatchOSLifeCycleEventTests.swift */; };
+ EDC1BCBC2B146A3800211F24 /* RSWhiteListedEventsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132AF27D9106500AFD833 /* RSWhiteListedEventsTests.swift */; };
+ EDC1BCBD2B146A3800211F24 /* RSThreadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD0C96428225BFB00470E88 /* RSThreadTests.swift */; };
+ EDC1BCBE2B146A3800211F24 /* RSiOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF54284895F9002B2D46 /* RSiOSLifeCycleEventTests.swift */; };
+ EDC1BCBF2B146A3800211F24 /* RSBlackListedEventsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132AD27D9104700AFD833 /* RSBlackListedEventsTest.swift */; };
+ EDC1BCC02B146A3800211F24 /* RSDatabaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD0C9662829199200470E88 /* RSDatabaseTests.swift */; };
+ EDC1BCCD2B146A4E00211F24 /* RSClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1327B27D614C400AFD833 /* RSClientTests.swift */; };
+ EDC1BCCE2B146A4E00211F24 /* RSmacOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF5728489E2C002B2D46 /* RSmacOSLifeCycleEventTests.swift */; };
+ EDC1BCCF2B146A4E00211F24 /* RSwatchOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF5628489E2C002B2D46 /* RSwatchOSLifeCycleEventTests.swift */; };
+ EDC1BCD02B146A4E00211F24 /* RSWhiteListedEventsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132AF27D9106500AFD833 /* RSWhiteListedEventsTests.swift */; };
+ EDC1BCD12B146A4E00211F24 /* RSThreadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD0C96428225BFB00470E88 /* RSThreadTests.swift */; };
+ EDC1BCD22B146A4E00211F24 /* RSiOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF54284895F9002B2D46 /* RSiOSLifeCycleEventTests.swift */; };
+ EDC1BCD32B146A4E00211F24 /* RSBlackListedEventsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC132AD27D9104700AFD833 /* RSBlackListedEventsTest.swift */; };
+ EDC1BCD42B146A4E00211F24 /* RSDatabaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD0C9662829199200470E88 /* RSDatabaseTests.swift */; };
+ EDC1BCDE2B14738F00211F24 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1BCDD2B14738F00211F24 /* Logger.swift */; };
+ EDC1BCDF2B14738F00211F24 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1BCDD2B14738F00211F24 /* Logger.swift */; };
+ EDC1BCE02B14738F00211F24 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1BCDD2B14738F00211F24 /* Logger.swift */; };
+ EDC1BCE12B14738F00211F24 /* Logger.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDC1BCDD2B14738F00211F24 /* Logger.swift */; };
+ EDC1BCE22B15BC4600211F24 /* ServerConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = EDC1BC9B2B10A5DA00211F24 /* ServerConfig.json */; };
+ EDC1BCE32B15BC4700211F24 /* ServerConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = EDC1BC9B2B10A5DA00211F24 /* ServerConfig.json */; };
+ EDC1BCE42B15BC4800211F24 /* ServerConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = EDC1BC9B2B10A5DA00211F24 /* ServerConfig.json */; };
+ EDC1BCE52B15BC4800211F24 /* ServerConfig.json in Resources */ = {isa = PBXBuildFile; fileRef = EDC1BC9B2B10A5DA00211F24 /* ServerConfig.json */; };
EDD0C96528225BFB00470E88 /* RSThreadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD0C96428225BFB00470E88 /* RSThreadTests.swift */; };
EDD0C9672829199200470E88 /* RSDatabaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD0C9662829199200470E88 /* RSDatabaseTests.swift */; };
EDD3AA1327C64B430048E61E /* RSKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD3AA1227C64B430048E61E /* RSKeyPath.swift */; };
EDD3AA3627C659C80048E61E /* RSAtomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDD3AA3527C659C80048E61E /* RSAtomic.swift */; };
- EDD3AA4A27C8DAAA0048E61E /* RSLoggerPlugin.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227827A3F0C100EC8366 /* RSLoggerPlugin.swift */; };
- EDD3AA4B27C8DAB90048E61E /* RSLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227727A3F0C100EC8366 /* RSLogger.swift */; };
- EDD3AA4C27C8DABD0048E61E /* RSConsoleLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED3D227927A3F0C100EC8366 /* RSConsoleLogger.swift */; };
EDF3FF55284895F9002B2D46 /* RSiOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF54284895F9002B2D46 /* RSiOSLifeCycleEventTests.swift */; };
EDF3FF5828489E2C002B2D46 /* RSwatchOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF5628489E2C002B2D46 /* RSwatchOSLifeCycleEventTests.swift */; };
EDF3FF5928489E2C002B2D46 /* RSmacOSLifeCycleEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDF3FF5728489E2C002B2D46 /* RSmacOSLifeCycleEventTests.swift */; };
@@ -100,11 +301,32 @@
remoteGlobalIDString = 06CABB832630C3CA0097BEFF;
remoteInfo = Rudder;
};
+ ED53723F2B15C6BC00D794EB /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 06CABB7B2630C3CA0097BEFF /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = EDC1BC0E2B0DD88A00211F24;
+ remoteInfo = "Rudder-tvOS";
+ };
+ ED5372412B15C6C600D794EB /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 06CABB7B2630C3CA0097BEFF /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = EDC1BC532B0DD89400211F24;
+ remoteInfo = "Rudder-watchOS";
+ };
+ ED5372432B15C6CE00D794EB /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 06CABB7B2630C3CA0097BEFF /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = EDC1BBC92B0DD87D00211F24;
+ remoteInfo = "Rudder-macOS";
+ };
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
06CABB842630C3CA0097BEFF /* Rudder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Rudder.framework; sourceTree = BUILT_PRODUCTS_DIR; };
- 8C6EA4422A0BDADF0049569A /* RSUserSessionPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = RSUserSessionPlugin.swift; path = Sources/Classes/Client/Plugins/RSUserSessionPlugin.swift; sourceTree = ""; };
+ 8C6EA4422A0BDADF0049569A /* RSUserSessionPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSUserSessionPlugin.swift; sourceTree = ""; };
ED056315291BB03900BAEE65 /* Configuration.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = Configuration.json; sourceTree = ""; };
ED056316291BB03900BAEE65 /* package.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = package.json; sourceTree = ""; };
ED056317291BB03900BAEE65 /* CONTRIBUTING.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CONTRIBUTING.md; sourceTree = ""; };
@@ -114,24 +336,17 @@
ED05631D291BE61000BAEE65 /* .github */ = {isa = PBXFileReference; lastKnownFileType = folder; path = .github; sourceTree = ""; };
ED05631E291BEB0400BAEE65 /* RSVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSVersion.swift; sourceTree = ""; };
ED157C3627CE0EEA00F22202 /* RSmacOSLifecycleEvents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSmacOSLifecycleEvents.swift; sourceTree = ""; };
- ED157C3827CE1C0800F22202 /* RSUserIdPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSUserIdPlugin.swift; sourceTree = ""; };
- ED157C4027CFC33800F22202 /* RSAdvertisementIdPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSAdvertisementIdPlugin.swift; sourceTree = ""; };
- ED157C4227CFC6F700F22202 /* RSAnonymousIdPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSAnonymousIdPlugin.swift; sourceTree = ""; };
ED157C4427CFD99700F22202 /* RSIntegrationPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSIntegrationPlugin.swift; sourceTree = ""; };
- ED157C4627CFDEC000F22202 /* RSOptionPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSOptionPlugin.swift; sourceTree = ""; };
- ED157C4827CFE6CE00F22202 /* RSAppTrackingConsentPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSAppTrackingConsentPlugin.swift; sourceTree = ""; };
ED157C4A27CFE86100F22202 /* RSAppTrackingConsent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSAppTrackingConsent.swift; sourceTree = ""; };
ED157C4C27D0A63A00F22202 /* RSiOSScreenViewEvents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSiOSScreenViewEvents.swift; sourceTree = ""; };
ED157C4E27D0AC0E00F22202 /* RSwatchOSScreenViewEvents.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSwatchOSScreenViewEvents.swift; sourceTree = ""; };
- ED157C5327D0CA6900F22202 /* RSGDPRPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSGDPRPlugin.swift; sourceTree = ""; };
ED157C5527D0FCDC00F22202 /* RSmacOSScreenViewEvents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSmacOSScreenViewEvents.swift; sourceTree = ""; };
ED157C5727D0FFA400F22202 /* RSLifeCycle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSLifeCycle.swift; sourceTree = ""; };
ED157C5927D1010D00F22202 /* RSPushNotifications.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSPushNotifications.swift; sourceTree = ""; };
ED277FA027421B06002A8FEA /* RSEventsAndKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSEventsAndKeys.swift; sourceTree = ""; };
- ED277FF82744F199002A8FEA /* RSAnyCodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSAnyCodable.swift; sourceTree = ""; };
- ED277FFA2744F265002A8FEA /* RSAnyDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSAnyDecodable.swift; sourceTree = ""; };
- ED277FFC2744F2AD002A8FEA /* RSAnyEncodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSAnyEncodable.swift; sourceTree = ""; };
- ED3D2257279EAC2800EC8366 /* RudderTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RudderTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ ED333EB62B21F324003EB0B3 /* RSSessionStoragePlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSSessionStoragePlugin.swift; sourceTree = ""; };
+ ED333EBB2B22055D003EB0B3 /* RSContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSContext.swift; sourceTree = ""; };
+ ED3D2257279EAC2800EC8366 /* RudderTests-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "RudderTests-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
ED3D226227A3F0C100EC8366 /* RSClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSClient.swift; sourceTree = ""; };
ED3D226627A3F0C100EC8366 /* Vendor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vendor.swift; sourceTree = ""; };
ED3D226727A3F0C100EC8366 /* AppleUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppleUtils.swift; sourceTree = ""; };
@@ -142,20 +357,19 @@
ED3D226F27A3F0C100EC8366 /* RSiOSDelegation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSiOSDelegation.swift; sourceTree = ""; };
ED3D227027A3F0C100EC8366 /* RSiOSLifecycleMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSiOSLifecycleMonitor.swift; sourceTree = ""; };
ED3D227227A3F0C100EC8366 /* RSmacOSLifecycleMonitor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSmacOSLifecycleMonitor.swift; sourceTree = ""; };
- ED3D227727A3F0C100EC8366 /* RSLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSLogger.swift; sourceTree = ""; };
- ED3D227827A3F0C100EC8366 /* RSLoggerPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSLoggerPlugin.swift; sourceTree = ""; };
- ED3D227927A3F0C100EC8366 /* RSConsoleLogger.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSConsoleLogger.swift; sourceTree = ""; };
ED3D227A27A3F0C100EC8366 /* RSReplayQueuePlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSReplayQueuePlugin.swift; sourceTree = ""; };
ED3D227B27A3F0C100EC8366 /* RudderDestinationPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RudderDestinationPlugin.swift; sourceTree = ""; };
ED3D227C27A3F0C100EC8366 /* RSContextPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSContextPlugin.swift; sourceTree = ""; };
- ED3D227D27A3F0C100EC8366 /* RSDeviceTokenPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSDeviceTokenPlugin.swift; sourceTree = ""; };
ED3D227E27A3F0C100EC8366 /* RSController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSController.swift; sourceTree = ""; };
ED3D228127A3F0C100EC8366 /* RSPlugins.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSPlugins.swift; sourceTree = ""; };
ED3D228227A3F0C100EC8366 /* RSClient+Plugins.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "RSClient+Plugins.swift"; sourceTree = ""; };
ED3D229227A3F0C100EC8366 /* RSMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSMessage.swift; sourceTree = ""; };
ED3D22BD27A45B6500EC8366 /* RSTypeAlias.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSTypeAlias.swift; sourceTree = ""; };
- ED4EACA827F5EA1F00207AF1 /* RSIdentifyTraitsPlugin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSIdentifyTraitsPlugin.swift; sourceTree = ""; };
- ED4EACAA27F5F03C00207AF1 /* RSAliasIdPlugin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSAliasIdPlugin.swift; sourceTree = ""; };
+ ED5372452B1613CE00D794EB /* LogMessages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogMessages.swift; sourceTree = ""; };
+ ED53724A2B18ED8E00D794EB /* MockURLProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockURLProtocol.swift; sourceTree = ""; };
+ ED5603842881C691004B5BEC /* RSUserInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSUserInfo.swift; sourceTree = ""; };
+ ED5603862882CE6D004B5BEC /* RSSessionStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSSessionStorage.swift; sourceTree = ""; };
+ ED560388288316C2004B5BEC /* Data+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+Ext.swift"; sourceTree = ""; };
ED910CDE273BA25100A3EDFF /* Package.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; };
ED910CE0273BA25100A3EDFF /* CHANGELOG.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = ""; };
ED910CE1273BA25100A3EDFF /* Podfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
@@ -169,13 +383,10 @@
EDA7EF462739119600E73142 /* RSConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSConstants.swift; sourceTree = ""; };
EDA7EF482739119600E73142 /* String+Ext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Ext.swift"; sourceTree = ""; };
EDA7EF492739119600E73142 /* NSError+Ext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSError+Ext.swift"; sourceTree = ""; };
- EDA7EF4A2739119600E73142 /* UserDefaults+Ext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserDefaults+Ext.swift"; sourceTree = ""; };
EDA7EF4D2739119600E73142 /* RSUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSUtils.swift; sourceTree = ""; };
EDA7EF4F2739119600E73142 /* Rudder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Rudder.h; sourceTree = ""; };
- EDA7EF502739119600E73142 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
EDA7EF532739119600E73142 /* RSMessageType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSMessageType.swift; sourceTree = ""; };
EDA7EF552739119600E73142 /* RSErrorCode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSErrorCode.swift; sourceTree = ""; };
- EDA7EF562739119600E73142 /* RSLogLevel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSLogLevel.swift; sourceTree = ""; };
EDA7EF582739119600E73142 /* RSDBMessage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSDBMessage.swift; sourceTree = ""; };
EDA7EF592739119600E73142 /* RSConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSConfig.swift; sourceTree = ""; };
EDA7EF5D2739119600E73142 /* RSOption.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSOption.swift; sourceTree = ""; };
@@ -186,14 +397,18 @@
EDA7EF6B2739119600E73142 /* RSServiceType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSServiceType.swift; sourceTree = ""; };
EDC1327B27D614C400AFD833 /* RSClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSClientTests.swift; sourceTree = ""; };
EDC132A127D7D61D00AFD833 /* JSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = ""; };
- EDC132A327D8D55600AFD833 /* RSTrackTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSTrackTests.swift; sourceTree = ""; };
- EDC132A527D8D5F300AFD833 /* RSIdentifyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSIdentifyTests.swift; sourceTree = ""; };
- EDC132A727D8D61700AFD833 /* RSScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSScreenTests.swift; sourceTree = ""; };
- EDC132A927D8D63D00AFD833 /* RSAliasTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSAliasTests.swift; sourceTree = ""; };
- EDC132AB27D8D64E00AFD833 /* RSGroupTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSGroupTests.swift; sourceTree = ""; };
EDC132AD27D9104700AFD833 /* RSBlackListedEventsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSBlackListedEventsTest.swift; sourceTree = ""; };
EDC132AF27D9106500AFD833 /* RSWhiteListedEventsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSWhiteListedEventsTests.swift; sourceTree = ""; };
EDC14DDD2859C7DB00E2E6FE /* RSRepeatingTimer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RSRepeatingTimer.swift; path = Sources/Classes/Helpers/RSRepeatingTimer.swift; sourceTree = SOURCE_ROOT; };
+ EDC1BC0D2B0DD87D00211F24 /* Rudder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Rudder.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ EDC1BC522B0DD88A00211F24 /* Rudder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Rudder.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ EDC1BC972B0DD89400211F24 /* Rudder.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Rudder.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ EDC1BC992B10A31C00211F24 /* TestUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUtils.swift; sourceTree = ""; };
+ EDC1BC9B2B10A5DA00211F24 /* ServerConfig.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = ServerConfig.json; sourceTree = ""; };
+ EDC1BCB42B146A2D00211F24 /* RudderTests-watchOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "RudderTests-watchOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+ EDC1BCC82B146A3800211F24 /* RudderTests-tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "RudderTests-tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+ EDC1BCDC2B146A4E00211F24 /* RudderTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "RudderTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
+ EDC1BCDD2B14738F00211F24 /* Logger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logger.swift; sourceTree = ""; };
EDD0C96428225BFB00470E88 /* RSThreadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSThreadTests.swift; sourceTree = ""; };
EDD0C9662829199200470E88 /* RSDatabaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RSDatabaseTests.swift; sourceTree = ""; };
EDD3AA1227C64B430048E61E /* RSKeyPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RSKeyPath.swift; sourceTree = ""; };
@@ -220,16 +435,60 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ EDC1BC072B0DD87D00211F24 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BC4C2B0DD88A00211F24 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BC912B0DD89400211F24 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BCAD2B146A2D00211F24 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ ED53723C2B15C32000D794EB /* Rudder.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BCC12B146A3800211F24 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ ED53723D2B15C32900D794EB /* Rudder.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BCD52B146A4E00211F24 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ ED53723E2B15C33300D794EB /* Rudder.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
06CABB7A2630C3CA0097BEFF = {
isa = PBXGroup;
children = (
- 8C6EA4422A0BDADF0049569A /* RSUserSessionPlugin.swift */,
ED056319291BB06C00BAEE65 /* Others */,
EDA7EF2D2739119600E73142 /* Sources */,
- EDC1325A27D612B600AFD833 /* Tests */,
+ EDC1325B27D612B600AFD833 /* RudderTests */,
06CABB852630C3CA0097BEFF /* Products */,
);
sourceTree = "";
@@ -238,7 +497,13 @@
isa = PBXGroup;
children = (
06CABB842630C3CA0097BEFF /* Rudder.framework */,
- ED3D2257279EAC2800EC8366 /* RudderTests.xctest */,
+ ED3D2257279EAC2800EC8366 /* RudderTests-iOS.xctest */,
+ EDC1BC0D2B0DD87D00211F24 /* Rudder.framework */,
+ EDC1BC522B0DD88A00211F24 /* Rudder.framework */,
+ EDC1BC972B0DD89400211F24 /* Rudder.framework */,
+ EDC1BCB42B146A2D00211F24 /* RudderTests-watchOS.xctest */,
+ EDC1BCC82B146A3800211F24 /* RudderTests-tvOS.xctest */,
+ EDC1BCDC2B146A4E00211F24 /* RudderTests-macOS.xctest */,
);
name = Products;
sourceTree = "";
@@ -266,19 +531,11 @@
ED3D226327A3F0C100EC8366 /* Plugins */ = {
isa = PBXGroup;
children = (
- ED4EACAA27F5F03C00207AF1 /* RSAliasIdPlugin.swift */,
- ED157C4027CFC33800F22202 /* RSAdvertisementIdPlugin.swift */,
- ED157C4227CFC6F700F22202 /* RSAnonymousIdPlugin.swift */,
- ED157C4827CFE6CE00F22202 /* RSAppTrackingConsentPlugin.swift */,
ED3D227C27A3F0C100EC8366 /* RSContextPlugin.swift */,
- ED3D227D27A3F0C100EC8366 /* RSDeviceTokenPlugin.swift */,
- ED157C5327D0CA6900F22202 /* RSGDPRPlugin.swift */,
- ED4EACA827F5EA1F00207AF1 /* RSIdentifyTraitsPlugin.swift */,
ED157C4427CFD99700F22202 /* RSIntegrationPlugin.swift */,
- ED3D227827A3F0C100EC8366 /* RSLoggerPlugin.swift */,
- ED157C4627CFDEC000F22202 /* RSOptionPlugin.swift */,
ED3D227A27A3F0C100EC8366 /* RSReplayQueuePlugin.swift */,
- ED157C3827CE1C0800F22202 /* RSUserIdPlugin.swift */,
+ ED333EB62B21F324003EB0B3 /* RSSessionStoragePlugin.swift */,
+ 8C6EA4422A0BDADF0049569A /* RSUserSessionPlugin.swift */,
ED3D227B27A3F0C100EC8366 /* RudderDestinationPlugin.swift */,
);
path = Plugins;
@@ -353,7 +610,7 @@
isa = PBXGroup;
children = (
ED3D22BC27A4565A00EC8366 /* Classes */,
- EDA7EF4E2739119600E73142 /* SDKInfo */,
+ EDA7EF4F2739119600E73142 /* Rudder.h */,
);
path = Sources;
sourceTree = "";
@@ -379,10 +636,10 @@
EDA7EF442739119600E73142 /* Constants */ = {
isa = PBXGroup;
children = (
+ ED5372452B1613CE00D794EB /* LogMessages.swift */,
EDA7EF462739119600E73142 /* RSConstants.swift */,
ED277FA027421B06002A8FEA /* RSEventsAndKeys.swift */,
ED3D22BD27A45B6500EC8366 /* RSTypeAlias.swift */,
- EDA7EF452739119600E73142 /* RSUserDefaults.swift */,
ED05631E291BEB0400BAEE65 /* RSVersion.swift */,
);
path = Constants;
@@ -391,27 +648,20 @@
EDA7EF4C2739119600E73142 /* Utility */ = {
isa = PBXGroup;
children = (
+ EDC1BC982B10A26700211F24 /* Fixtures */,
+ ED53724A2B18ED8E00D794EB /* MockURLProtocol.swift */,
EDA7EF4D2739119600E73142 /* RSUtils.swift */,
+ EDC1BC992B10A31C00211F24 /* TestUtils.swift */,
);
path = Utility;
sourceTree = "";
};
- EDA7EF4E2739119600E73142 /* SDKInfo */ = {
- isa = PBXGroup;
- children = (
- EDA7EF4F2739119600E73142 /* Rudder.h */,
- EDA7EF502739119600E73142 /* Info.plist */,
- );
- path = SDKInfo;
- sourceTree = "";
- };
EDA7EF522739119600E73142 /* Enums */ = {
isa = PBXGroup;
children = (
EDC132A127D7D61D00AFD833 /* JSON.swift */,
ED157C4A27CFE86100F22202 /* RSAppTrackingConsent.swift */,
EDA7EF552739119600E73142 /* RSErrorCode.swift */,
- EDA7EF562739119600E73142 /* RSLogLevel.swift */,
EDA7EF532739119600E73142 /* RSMessageType.swift */,
);
path = Enums;
@@ -428,34 +678,29 @@
path = Attributes;
sourceTree = "";
};
- EDC1325A27D612B600AFD833 /* Tests */ = {
- isa = PBXGroup;
- children = (
- EDC1325B27D612B600AFD833 /* RudderTests */,
- );
- path = Tests;
- sourceTree = "";
- };
EDC1325B27D612B600AFD833 /* RudderTests */ = {
isa = PBXGroup;
children = (
- EDC132A927D8D63D00AFD833 /* RSAliasTests.swift */,
EDC132AD27D9104700AFD833 /* RSBlackListedEventsTest.swift */,
EDC1327B27D614C400AFD833 /* RSClientTests.swift */,
EDD0C9662829199200470E88 /* RSDatabaseTests.swift */,
- EDC132AB27D8D64E00AFD833 /* RSGroupTests.swift */,
- EDC132A527D8D5F300AFD833 /* RSIdentifyTests.swift */,
EDF3FF54284895F9002B2D46 /* RSiOSLifeCycleEventTests.swift */,
EDF3FF5728489E2C002B2D46 /* RSmacOSLifeCycleEventTests.swift */,
- EDC132A727D8D61700AFD833 /* RSScreenTests.swift */,
EDD0C96428225BFB00470E88 /* RSThreadTests.swift */,
- EDC132A327D8D55600AFD833 /* RSTrackTests.swift */,
EDF3FF5628489E2C002B2D46 /* RSwatchOSLifeCycleEventTests.swift */,
EDC132AF27D9106500AFD833 /* RSWhiteListedEventsTests.swift */,
);
path = RudderTests;
sourceTree = "";
};
+ EDC1BC982B10A26700211F24 /* Fixtures */ = {
+ isa = PBXGroup;
+ children = (
+ EDC1BC9B2B10A5DA00211F24 /* ServerConfig.json */,
+ );
+ path = Fixtures;
+ sourceTree = "";
+ };
EDD3AA1727C656F90048E61E /* Domain */ = {
isa = PBXGroup;
children = (
@@ -469,9 +714,7 @@
EDD3AA1827C657210048E61E /* Protocols */ = {
isa = PBXGroup;
children = (
- ED3D227927A3F0C100EC8366 /* RSConsoleLogger.swift */,
ED157C5727D0FFA400F22202 /* RSLifeCycle.swift */,
- ED3D227727A3F0C100EC8366 /* RSLogger.swift */,
ED3D229227A3F0C100EC8366 /* RSMessage.swift */,
ED3D228127A3F0C100EC8366 /* RSPlugins.swift */,
ED157C5927D1010D00F22202 /* RSPushNotifications.swift */,
@@ -495,9 +738,9 @@
EDD3AA1B27C657EA0048E61E /* Extensions */ = {
isa = PBXGroup;
children = (
+ ED560388288316C2004B5BEC /* Data+Ext.swift */,
EDA7EF492739119600E73142 /* NSError+Ext.swift */,
EDA7EF482739119600E73142 /* String+Ext.swift */,
- EDA7EF4A2739119600E73142 /* UserDefaults+Ext.swift */,
);
path = Extensions;
sourceTree = "";
@@ -508,9 +751,11 @@
EDA7EF602739119600E73142 /* Attributes */,
EDD3AA3527C659C80048E61E /* RSAtomic.swift */,
EDA7EF592739119600E73142 /* RSConfig.swift */,
+ ED333EBB2B22055D003EB0B3 /* RSContext.swift */,
EDA7EF582739119600E73142 /* RSDBMessage.swift */,
EDD3AA1227C64B430048E61E /* RSKeyPath.swift */,
EDA7EF5D2739119600E73142 /* RSOption.swift */,
+ ED5603842881C691004B5BEC /* RSUserInfo.swift */,
);
path = Models;
sourceTree = "";
@@ -528,10 +773,10 @@
isa = PBXGroup;
children = (
ED3D226427A3F0C100EC8366 /* Platforms */,
- ED277FF82744F199002A8FEA /* RSAnyCodable.swift */,
- ED277FFA2744F265002A8FEA /* RSAnyDecodable.swift */,
- ED277FFC2744F2AD002A8FEA /* RSAnyEncodable.swift */,
+ EDC1BCDD2B14738F00211F24 /* Logger.swift */,
EDC14DDD2859C7DB00E2E6FE /* RSRepeatingTimer.swift */,
+ ED5603862882CE6D004B5BEC /* RSSessionStorage.swift */,
+ EDA7EF452739119600E73142 /* RSUserDefaults.swift */,
);
path = Helpers;
sourceTree = "";
@@ -547,12 +792,36 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ EDC1BBCA2B0DD87D00211F24 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BBCB2B0DD87D00211F24 /* Rudder.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BC0F2B0DD88A00211F24 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BC102B0DD88A00211F24 /* Rudder.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BC542B0DD89400211F24 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BC552B0DD89400211F24 /* Rudder.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
- 06CABB832630C3CA0097BEFF /* Rudder */ = {
+ 06CABB832630C3CA0097BEFF /* Rudder-iOS */ = {
isa = PBXNativeTarget;
- buildConfigurationList = 06CABB982630C3CA0097BEFF /* Build configuration list for PBXNativeTarget "Rudder" */;
+ buildConfigurationList = 06CABB982630C3CA0097BEFF /* Build configuration list for PBXNativeTarget "Rudder-iOS" */;
buildPhases = (
06CABB7F2630C3CA0097BEFF /* Headers */,
06CABB802630C3CA0097BEFF /* Sources */,
@@ -564,14 +833,14 @@
);
dependencies = (
);
- name = Rudder;
+ name = "Rudder-iOS";
productName = Rudder;
productReference = 06CABB842630C3CA0097BEFF /* Rudder.framework */;
productType = "com.apple.product-type.framework";
};
- ED3D2256279EAC2800EC8366 /* RudderTests */ = {
+ ED3D2256279EAC2800EC8366 /* RudderTests-iOS */ = {
isa = PBXNativeTarget;
- buildConfigurationList = ED3D225E279EAC2800EC8366 /* Build configuration list for PBXNativeTarget "RudderTests" */;
+ buildConfigurationList = ED3D225E279EAC2800EC8366 /* Build configuration list for PBXNativeTarget "RudderTests-iOS" */;
buildPhases = (
ED3D2253279EAC2800EC8366 /* Sources */,
ED3D2254279EAC2800EC8366 /* Frameworks */,
@@ -582,9 +851,120 @@
dependencies = (
ED3D225D279EAC2800EC8366 /* PBXTargetDependency */,
);
- name = RudderTests;
+ name = "RudderTests-iOS";
+ productName = RudderTests;
+ productReference = ED3D2257279EAC2800EC8366 /* RudderTests-iOS.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ EDC1BBC92B0DD87D00211F24 /* Rudder-macOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = EDC1BC0A2B0DD87D00211F24 /* Build configuration list for PBXNativeTarget "Rudder-macOS" */;
+ buildPhases = (
+ EDC1BBCA2B0DD87D00211F24 /* Headers */,
+ EDC1BBCC2B0DD87D00211F24 /* Sources */,
+ EDC1BC072B0DD87D00211F24 /* Frameworks */,
+ EDC1BC082B0DD87D00211F24 /* Resources */,
+ EDC1BC092B0DD87D00211F24 /* SwiftLint Script */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Rudder-macOS";
+ productName = Rudder;
+ productReference = EDC1BC0D2B0DD87D00211F24 /* Rudder.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ EDC1BC0E2B0DD88A00211F24 /* Rudder-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = EDC1BC4F2B0DD88A00211F24 /* Build configuration list for PBXNativeTarget "Rudder-tvOS" */;
+ buildPhases = (
+ EDC1BC0F2B0DD88A00211F24 /* Headers */,
+ EDC1BC112B0DD88A00211F24 /* Sources */,
+ EDC1BC4C2B0DD88A00211F24 /* Frameworks */,
+ EDC1BC4D2B0DD88A00211F24 /* Resources */,
+ EDC1BC4E2B0DD88A00211F24 /* SwiftLint Script */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Rudder-tvOS";
+ productName = Rudder;
+ productReference = EDC1BC522B0DD88A00211F24 /* Rudder.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ EDC1BC532B0DD89400211F24 /* Rudder-watchOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = EDC1BC942B0DD89400211F24 /* Build configuration list for PBXNativeTarget "Rudder-watchOS" */;
+ buildPhases = (
+ EDC1BC542B0DD89400211F24 /* Headers */,
+ EDC1BC562B0DD89400211F24 /* Sources */,
+ EDC1BC912B0DD89400211F24 /* Frameworks */,
+ EDC1BC922B0DD89400211F24 /* Resources */,
+ EDC1BC932B0DD89400211F24 /* SwiftLint Script */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = "Rudder-watchOS";
+ productName = Rudder;
+ productReference = EDC1BC972B0DD89400211F24 /* Rudder.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ EDC1BCA12B146A2D00211F24 /* RudderTests-watchOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = EDC1BCB12B146A2D00211F24 /* Build configuration list for PBXNativeTarget "RudderTests-watchOS" */;
+ buildPhases = (
+ EDC1BCA42B146A2D00211F24 /* Sources */,
+ EDC1BCAD2B146A2D00211F24 /* Frameworks */,
+ EDC1BCAF2B146A2D00211F24 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ ED5372422B15C6C600D794EB /* PBXTargetDependency */,
+ );
+ name = "RudderTests-watchOS";
+ productName = RudderTests;
+ productReference = EDC1BCB42B146A2D00211F24 /* RudderTests-watchOS.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ EDC1BCB52B146A3800211F24 /* RudderTests-tvOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = EDC1BCC52B146A3800211F24 /* Build configuration list for PBXNativeTarget "RudderTests-tvOS" */;
+ buildPhases = (
+ EDC1BCB82B146A3800211F24 /* Sources */,
+ EDC1BCC12B146A3800211F24 /* Frameworks */,
+ EDC1BCC32B146A3800211F24 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ ED5372402B15C6BC00D794EB /* PBXTargetDependency */,
+ );
+ name = "RudderTests-tvOS";
+ productName = RudderTests;
+ productReference = EDC1BCC82B146A3800211F24 /* RudderTests-tvOS.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ EDC1BCC92B146A4E00211F24 /* RudderTests-macOS */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = EDC1BCD92B146A4E00211F24 /* Build configuration list for PBXNativeTarget "RudderTests-macOS" */;
+ buildPhases = (
+ EDC1BCCC2B146A4E00211F24 /* Sources */,
+ EDC1BCD52B146A4E00211F24 /* Frameworks */,
+ EDC1BCD72B146A4E00211F24 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ ED5372442B15C6CE00D794EB /* PBXTargetDependency */,
+ );
+ name = "RudderTests-macOS";
productName = RudderTests;
- productReference = ED3D2257279EAC2800EC8366 /* RudderTests.xctest */;
+ productReference = EDC1BCDC2B146A4E00211F24 /* RudderTests-macOS.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
@@ -593,7 +973,7 @@
06CABB7B2630C3CA0097BEFF /* Project object */ = {
isa = PBXProject;
attributes = {
- CLASSPREFIX = RS;
+ CLASSPREFIX = "";
LastSwiftUpdateCheck = 1320;
LastUpgradeCheck = 1310;
ORGANIZATIONNAME = "Rudder Labs India Pvt Ltd.";
@@ -620,8 +1000,14 @@
projectDirPath = "";
projectRoot = "";
targets = (
- 06CABB832630C3CA0097BEFF /* Rudder */,
- ED3D2256279EAC2800EC8366 /* RudderTests */,
+ 06CABB832630C3CA0097BEFF /* Rudder-iOS */,
+ EDC1BC0E2B0DD88A00211F24 /* Rudder-tvOS */,
+ EDC1BC532B0DD89400211F24 /* Rudder-watchOS */,
+ EDC1BBC92B0DD87D00211F24 /* Rudder-macOS */,
+ ED3D2256279EAC2800EC8366 /* RudderTests-iOS */,
+ EDC1BCB52B146A3800211F24 /* RudderTests-tvOS */,
+ EDC1BCA12B146A2D00211F24 /* RudderTests-watchOS */,
+ EDC1BCC92B146A4E00211F24 /* RudderTests-macOS */,
);
};
/* End PBXProject section */
@@ -631,6 +1017,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ EDC1BCE22B15BC4600211F24 /* ServerConfig.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -641,6 +1028,51 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
+ EDC1BC082B0DD87D00211F24 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BCE52B15BC4800211F24 /* ServerConfig.json in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BC4D2B0DD88A00211F24 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BCE32B15BC4700211F24 /* ServerConfig.json in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BC922B0DD89400211F24 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BCE42B15BC4800211F24 /* ServerConfig.json in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BCAF2B146A2D00211F24 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BCC32B146A3800211F24 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BCD72B146A4E00211F24 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
@@ -662,6 +1094,60 @@
shellPath = /bin/sh;
shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
};
+ EDC1BC092B0DD87D00211F24 /* SwiftLint Script */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "SwiftLint Script";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
+ };
+ EDC1BC4E2B0DD88A00211F24 /* SwiftLint Script */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "SwiftLint Script";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
+ };
+ EDC1BC932B0DD89400211F24 /* SwiftLint Script */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "SwiftLint Script";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n";
+ };
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -670,52 +1156,44 @@
buildActionMask = 2147483647;
files = (
8C6EA4432A0BDADF0049569A /* RSUserSessionPlugin.swift in Sources */,
- ED277FFD2744F2AD002A8FEA /* RSAnyEncodable.swift in Sources */,
EDC132A227D7D61D00AFD833 /* JSON.swift in Sources */,
ED3D229B27A3F0C100EC8366 /* RSiOSLifecycleEvents.swift in Sources */,
EDA7EFA22739119600E73142 /* RSServiceType.swift in Sources */,
EDA7EF872739119600E73142 /* NSError+Ext.swift in Sources */,
- EDA7EF902739119600E73142 /* RSLogLevel.swift in Sources */,
EDA7EF9A2739119600E73142 /* RSDestinationConfig.swift in Sources */,
EDA7EF8D2739119600E73142 /* RSMessageType.swift in Sources */,
ED3D22A527A3F0C100EC8366 /* RudderDestinationPlugin.swift in Sources */,
+ ED5372462B1613CE00D794EB /* LogMessages.swift in Sources */,
ED3D229927A3F0C100EC8366 /* RSwatchOSLifecycleEvents.swift in Sources */,
EDA7EF8F2739119600E73142 /* RSErrorCode.swift in Sources */,
+ ED5603872882CE6D004B5BEC /* RSSessionStorage.swift in Sources */,
ED3D22BA27A3F0C100EC8366 /* RSMessage.swift in Sources */,
ED3D229827A3F0C100EC8366 /* RSwatchOSDelegation.swift in Sources */,
EDA7EF852739119600E73142 /* RSConstants.swift in Sources */,
- EDA7EF882739119600E73142 /* UserDefaults+Ext.swift in Sources */,
EDD3AA3627C659C80048E61E /* RSAtomic.swift in Sources */,
+ ED333EBC2B22055D003EB0B3 /* RSContext.swift in Sources */,
ED3D22A427A3F0C100EC8366 /* RSReplayQueuePlugin.swift in Sources */,
EDA7EF962739119600E73142 /* RSOption.swift in Sources */,
- ED277FFB2744F265002A8FEA /* RSAnyDecodable.swift in Sources */,
ED277FA127421B06002A8FEA /* RSEventsAndKeys.swift in Sources */,
+ ED53724B2B18ED8E00D794EB /* MockURLProtocol.swift in Sources */,
ED157C4527CFD99700F22202 /* RSIntegrationPlugin.swift in Sources */,
- ED157C4727CFDEC000F22202 /* RSOptionPlugin.swift in Sources */,
EDC14DDE2859C7DB00E2E6FE /* RSRepeatingTimer.swift in Sources */,
ED157C3727CE0EEA00F22202 /* RSmacOSLifecycleEvents.swift in Sources */,
ED157C4B27CFE86100F22202 /* RSAppTrackingConsent.swift in Sources */,
- ED157C4327CFC6F700F22202 /* RSAnonymousIdPlugin.swift in Sources */,
EDA7EF922739119600E73142 /* RSConfig.swift in Sources */,
- ED157C4927CFE6CE00F22202 /* RSAppTrackingConsentPlugin.swift in Sources */,
EDD3AA1327C64B430048E61E /* RSKeyPath.swift in Sources */,
EDA7EF752739119600E73142 /* API.swift in Sources */,
EDA7EF812739119600E73142 /* RSDatabaseManager.swift in Sources */,
- ED157C4127CFC33800F22202 /* RSAdvertisementIdPlugin.swift in Sources */,
ED05631F291BEB0400BAEE65 /* RSVersion.swift in Sources */,
EDA7EF992739119600E73142 /* RSServerConfig.swift in Sources */,
- ED277FF92744F199002A8FEA /* RSAnyCodable.swift in Sources */,
- ED157C3927CE1C0800F22202 /* RSUserIdPlugin.swift in Sources */,
ED3D229E27A3F0C100EC8366 /* RSmacOSLifecycleMonitor.swift in Sources */,
+ EDC1BCA02B1465AC00211F24 /* TestUtils.swift in Sources */,
ED3D229D27A3F0C100EC8366 /* RSiOSLifecycleMonitor.swift in Sources */,
- ED4EACA927F5EA1F00207AF1 /* RSIdentifyTraitsPlugin.swift in Sources */,
- EDD3AA4C27C8DABD0048E61E /* RSConsoleLogger.swift in Sources */,
+ ED5603852881C691004B5BEC /* RSUserInfo.swift in Sources */,
ED157C5A27D1010D00F22202 /* RSPushNotifications.swift in Sources */,
+ ED333EB72B21F324003EB0B3 /* RSSessionStoragePlugin.swift in Sources */,
ED3D22A827A3F0C100EC8366 /* RSController.swift in Sources */,
- ED3D22A727A3F0C100EC8366 /* RSDeviceTokenPlugin.swift in Sources */,
- EDD3AA4A27C8DAAA0048E61E /* RSLoggerPlugin.swift in Sources */,
ED157C4F27D0AC0E00F22202 /* RSwatchOSScreenViewEvents.swift in Sources */,
- EDD3AA4B27C8DAB90048E61E /* RSLogger.swift in Sources */,
ED3D22BE27A45B6500EC8366 /* RSTypeAlias.swift in Sources */,
ED157C4D27D0A63A00F22202 /* RSiOSScreenViewEvents.swift in Sources */,
EDA7EF842739119600E73142 /* RSUserDefaults.swift in Sources */,
@@ -724,18 +1202,18 @@
ED157C5827D0FFA400F22202 /* RSLifeCycle.swift in Sources */,
EDA7EF862739119600E73142 /* String+Ext.swift in Sources */,
ED3D22AB27A3F0C100EC8366 /* RSPlugins.swift in Sources */,
- ED4EACAB27F5F03C00207AF1 /* RSAliasIdPlugin.swift in Sources */,
EDA7EF9B2739119600E73142 /* RSDestinationDefinition.swift in Sources */,
ED3D229427A3F0C100EC8366 /* RSClient.swift in Sources */,
ED3D229627A3F0C100EC8366 /* AppleUtils.swift in Sources */,
ED3D22AC27A3F0C100EC8366 /* RSClient+Plugins.swift in Sources */,
+ EDC1BCDE2B14738F00211F24 /* Logger.swift in Sources */,
ED3D22A627A3F0C100EC8366 /* RSContextPlugin.swift in Sources */,
+ ED560389288316C2004B5BEC /* Data+Ext.swift in Sources */,
EDA7EF762739119600E73142 /* RSServiceManager.swift in Sources */,
EDA7EF912739119600E73142 /* RSDBMessage.swift in Sources */,
EDA7EF9C2739119600E73142 /* RSDestination.swift in Sources */,
ED3D229C27A3F0C100EC8366 /* RSiOSDelegation.swift in Sources */,
ED3D229A27A3F0C100EC8366 /* RSwatchOSLifecycleMonitor.swift in Sources */,
- ED157C5427D0CA6900F22202 /* RSGDPRPlugin.swift in Sources */,
EDA7EF8A2739119600E73142 /* RSUtils.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -744,39 +1222,295 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- EDC132AA27D8D63D00AFD833 /* RSAliasTests.swift in Sources */,
- EDC132A427D8D55700AFD833 /* RSTrackTests.swift in Sources */,
EDC1327C27D614C400AFD833 /* RSClientTests.swift in Sources */,
EDF3FF5928489E2C002B2D46 /* RSmacOSLifeCycleEventTests.swift in Sources */,
- EDC132A827D8D61700AFD833 /* RSScreenTests.swift in Sources */,
EDF3FF5828489E2C002B2D46 /* RSwatchOSLifeCycleEventTests.swift in Sources */,
EDC132B027D9106500AFD833 /* RSWhiteListedEventsTests.swift in Sources */,
- EDC132AC27D8D64E00AFD833 /* RSGroupTests.swift in Sources */,
EDD0C96528225BFB00470E88 /* RSThreadTests.swift in Sources */,
EDF3FF55284895F9002B2D46 /* RSiOSLifeCycleEventTests.swift in Sources */,
EDC132AE27D9104700AFD833 /* RSBlackListedEventsTest.swift in Sources */,
- EDC132A627D8D5F300AFD833 /* RSIdentifyTests.swift in Sources */,
EDD0C9672829199200470E88 /* RSDatabaseTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXTargetDependency section */
- ED3D225D279EAC2800EC8366 /* PBXTargetDependency */ = {
- isa = PBXTargetDependency;
- target = 06CABB832630C3CA0097BEFF /* Rudder */;
- targetProxy = ED3D225C279EAC2800EC8366 /* PBXContainerItemProxy */;
+ EDC1BBCC2B0DD87D00211F24 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BBCD2B0DD87D00211F24 /* RSUserSessionPlugin.swift in Sources */,
+ EDC1BBCE2B0DD87D00211F24 /* JSON.swift in Sources */,
+ EDC1BBCF2B0DD87D00211F24 /* RSiOSLifecycleEvents.swift in Sources */,
+ EDC1BBD02B0DD87D00211F24 /* RSServiceType.swift in Sources */,
+ EDC1BBD12B0DD87D00211F24 /* NSError+Ext.swift in Sources */,
+ EDC1BBD32B0DD87D00211F24 /* RSDestinationConfig.swift in Sources */,
+ EDC1BBD42B0DD87D00211F24 /* RSMessageType.swift in Sources */,
+ EDC1BBD52B0DD87D00211F24 /* RudderDestinationPlugin.swift in Sources */,
+ ED5372492B1613CE00D794EB /* LogMessages.swift in Sources */,
+ EDC1BBD62B0DD87D00211F24 /* RSwatchOSLifecycleEvents.swift in Sources */,
+ EDC1BBD72B0DD87D00211F24 /* RSErrorCode.swift in Sources */,
+ EDC1BBD82B0DD87D00211F24 /* RSSessionStorage.swift in Sources */,
+ EDC1BBD92B0DD87D00211F24 /* RSMessage.swift in Sources */,
+ EDC1BBDA2B0DD87D00211F24 /* RSwatchOSDelegation.swift in Sources */,
+ EDC1BBDB2B0DD87D00211F24 /* RSConstants.swift in Sources */,
+ EDC1BBDC2B0DD87D00211F24 /* RSAtomic.swift in Sources */,
+ ED333EBF2B22055D003EB0B3 /* RSContext.swift in Sources */,
+ EDC1BBDD2B0DD87D00211F24 /* RSReplayQueuePlugin.swift in Sources */,
+ EDC1BBDE2B0DD87D00211F24 /* RSOption.swift in Sources */,
+ EDC1BBDF2B0DD87D00211F24 /* RSEventsAndKeys.swift in Sources */,
+ ED53724E2B18ED8E00D794EB /* MockURLProtocol.swift in Sources */,
+ EDC1BBE02B0DD87D00211F24 /* RSIntegrationPlugin.swift in Sources */,
+ EDC1BBE12B0DD87D00211F24 /* RSRepeatingTimer.swift in Sources */,
+ EDC1BBE22B0DD87D00211F24 /* RSmacOSLifecycleEvents.swift in Sources */,
+ EDC1BBE32B0DD87D00211F24 /* RSAppTrackingConsent.swift in Sources */,
+ EDC1BBE42B0DD87D00211F24 /* RSConfig.swift in Sources */,
+ EDC1BBE52B0DD87D00211F24 /* RSKeyPath.swift in Sources */,
+ EDC1BBE62B0DD87D00211F24 /* API.swift in Sources */,
+ EDC1BBE72B0DD87D00211F24 /* RSDatabaseManager.swift in Sources */,
+ EDC1BBE82B0DD87D00211F24 /* RSVersion.swift in Sources */,
+ EDC1BBE92B0DD87D00211F24 /* RSServerConfig.swift in Sources */,
+ EDC1BBEA2B0DD87D00211F24 /* RSmacOSLifecycleMonitor.swift in Sources */,
+ EDC1BC9D2B1465AC00211F24 /* TestUtils.swift in Sources */,
+ EDC1BBEB2B0DD87D00211F24 /* RSiOSLifecycleMonitor.swift in Sources */,
+ EDC1BBEC2B0DD87D00211F24 /* RSUserInfo.swift in Sources */,
+ EDC1BBEE2B0DD87D00211F24 /* RSPushNotifications.swift in Sources */,
+ ED333EBA2B21F324003EB0B3 /* RSSessionStoragePlugin.swift in Sources */,
+ EDC1BBEF2B0DD87D00211F24 /* RSController.swift in Sources */,
+ EDC1BBF12B0DD87D00211F24 /* RSwatchOSScreenViewEvents.swift in Sources */,
+ EDC1BBF32B0DD87D00211F24 /* RSTypeAlias.swift in Sources */,
+ EDC1BBF42B0DD87D00211F24 /* RSiOSScreenViewEvents.swift in Sources */,
+ EDC1BBF52B0DD87D00211F24 /* RSUserDefaults.swift in Sources */,
+ EDC1BBF62B0DD87D00211F24 /* RSmacOSScreenViewEvents.swift in Sources */,
+ EDC1BBF72B0DD87D00211F24 /* Vendor.swift in Sources */,
+ EDC1BBF82B0DD87D00211F24 /* RSLifeCycle.swift in Sources */,
+ EDC1BBF92B0DD87D00211F24 /* String+Ext.swift in Sources */,
+ EDC1BBFA2B0DD87D00211F24 /* RSPlugins.swift in Sources */,
+ EDC1BBFB2B0DD87D00211F24 /* RSDestinationDefinition.swift in Sources */,
+ EDC1BBFC2B0DD87D00211F24 /* RSClient.swift in Sources */,
+ EDC1BBFD2B0DD87D00211F24 /* AppleUtils.swift in Sources */,
+ EDC1BBFE2B0DD87D00211F24 /* RSClient+Plugins.swift in Sources */,
+ EDC1BCE12B14738F00211F24 /* Logger.swift in Sources */,
+ EDC1BBFF2B0DD87D00211F24 /* RSContextPlugin.swift in Sources */,
+ EDC1BC002B0DD87D00211F24 /* Data+Ext.swift in Sources */,
+ EDC1BC012B0DD87D00211F24 /* RSServiceManager.swift in Sources */,
+ EDC1BC022B0DD87D00211F24 /* RSDBMessage.swift in Sources */,
+ EDC1BC032B0DD87D00211F24 /* RSDestination.swift in Sources */,
+ EDC1BC042B0DD87D00211F24 /* RSiOSDelegation.swift in Sources */,
+ EDC1BC052B0DD87D00211F24 /* RSwatchOSLifecycleMonitor.swift in Sources */,
+ EDC1BC062B0DD87D00211F24 /* RSUtils.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
};
-/* End PBXTargetDependency section */
-
-/* Begin XCBuildConfiguration section */
- 06CABB962630C3CA0097BEFF /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ EDC1BC112B0DD88A00211F24 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BC122B0DD88A00211F24 /* RSUserSessionPlugin.swift in Sources */,
+ EDC1BC132B0DD88A00211F24 /* JSON.swift in Sources */,
+ EDC1BC142B0DD88A00211F24 /* RSiOSLifecycleEvents.swift in Sources */,
+ EDC1BC152B0DD88A00211F24 /* RSServiceType.swift in Sources */,
+ EDC1BC162B0DD88A00211F24 /* NSError+Ext.swift in Sources */,
+ EDC1BC182B0DD88A00211F24 /* RSDestinationConfig.swift in Sources */,
+ EDC1BC192B0DD88A00211F24 /* RSMessageType.swift in Sources */,
+ EDC1BC1A2B0DD88A00211F24 /* RudderDestinationPlugin.swift in Sources */,
+ ED5372472B1613CE00D794EB /* LogMessages.swift in Sources */,
+ EDC1BC1B2B0DD88A00211F24 /* RSwatchOSLifecycleEvents.swift in Sources */,
+ EDC1BC1C2B0DD88A00211F24 /* RSErrorCode.swift in Sources */,
+ EDC1BC1D2B0DD88A00211F24 /* RSSessionStorage.swift in Sources */,
+ EDC1BC1E2B0DD88A00211F24 /* RSMessage.swift in Sources */,
+ EDC1BC1F2B0DD88A00211F24 /* RSwatchOSDelegation.swift in Sources */,
+ EDC1BC202B0DD88A00211F24 /* RSConstants.swift in Sources */,
+ EDC1BC212B0DD88A00211F24 /* RSAtomic.swift in Sources */,
+ ED333EBD2B22055D003EB0B3 /* RSContext.swift in Sources */,
+ EDC1BC222B0DD88A00211F24 /* RSReplayQueuePlugin.swift in Sources */,
+ EDC1BC232B0DD88A00211F24 /* RSOption.swift in Sources */,
+ EDC1BC242B0DD88A00211F24 /* RSEventsAndKeys.swift in Sources */,
+ ED53724C2B18ED8E00D794EB /* MockURLProtocol.swift in Sources */,
+ EDC1BC252B0DD88A00211F24 /* RSIntegrationPlugin.swift in Sources */,
+ EDC1BC262B0DD88A00211F24 /* RSRepeatingTimer.swift in Sources */,
+ EDC1BC272B0DD88A00211F24 /* RSmacOSLifecycleEvents.swift in Sources */,
+ EDC1BC282B0DD88A00211F24 /* RSAppTrackingConsent.swift in Sources */,
+ EDC1BC292B0DD88A00211F24 /* RSConfig.swift in Sources */,
+ EDC1BC2A2B0DD88A00211F24 /* RSKeyPath.swift in Sources */,
+ EDC1BC2B2B0DD88A00211F24 /* API.swift in Sources */,
+ EDC1BC2C2B0DD88A00211F24 /* RSDatabaseManager.swift in Sources */,
+ EDC1BC2D2B0DD88A00211F24 /* RSVersion.swift in Sources */,
+ EDC1BC2E2B0DD88A00211F24 /* RSServerConfig.swift in Sources */,
+ EDC1BC2F2B0DD88A00211F24 /* RSmacOSLifecycleMonitor.swift in Sources */,
+ EDC1BC9E2B1465AC00211F24 /* TestUtils.swift in Sources */,
+ EDC1BC302B0DD88A00211F24 /* RSiOSLifecycleMonitor.swift in Sources */,
+ EDC1BC312B0DD88A00211F24 /* RSUserInfo.swift in Sources */,
+ EDC1BC332B0DD88A00211F24 /* RSPushNotifications.swift in Sources */,
+ ED333EB82B21F324003EB0B3 /* RSSessionStoragePlugin.swift in Sources */,
+ EDC1BC342B0DD88A00211F24 /* RSController.swift in Sources */,
+ EDC1BC362B0DD88A00211F24 /* RSwatchOSScreenViewEvents.swift in Sources */,
+ EDC1BC382B0DD88A00211F24 /* RSTypeAlias.swift in Sources */,
+ EDC1BC392B0DD88A00211F24 /* RSiOSScreenViewEvents.swift in Sources */,
+ EDC1BC3A2B0DD88A00211F24 /* RSUserDefaults.swift in Sources */,
+ EDC1BC3B2B0DD88A00211F24 /* RSmacOSScreenViewEvents.swift in Sources */,
+ EDC1BC3C2B0DD88A00211F24 /* Vendor.swift in Sources */,
+ EDC1BC3D2B0DD88A00211F24 /* RSLifeCycle.swift in Sources */,
+ EDC1BC3E2B0DD88A00211F24 /* String+Ext.swift in Sources */,
+ EDC1BC3F2B0DD88A00211F24 /* RSPlugins.swift in Sources */,
+ EDC1BC402B0DD88A00211F24 /* RSDestinationDefinition.swift in Sources */,
+ EDC1BC412B0DD88A00211F24 /* RSClient.swift in Sources */,
+ EDC1BC422B0DD88A00211F24 /* AppleUtils.swift in Sources */,
+ EDC1BC432B0DD88A00211F24 /* RSClient+Plugins.swift in Sources */,
+ EDC1BCDF2B14738F00211F24 /* Logger.swift in Sources */,
+ EDC1BC442B0DD88A00211F24 /* RSContextPlugin.swift in Sources */,
+ EDC1BC452B0DD88A00211F24 /* Data+Ext.swift in Sources */,
+ EDC1BC462B0DD88A00211F24 /* RSServiceManager.swift in Sources */,
+ EDC1BC472B0DD88A00211F24 /* RSDBMessage.swift in Sources */,
+ EDC1BC482B0DD88A00211F24 /* RSDestination.swift in Sources */,
+ EDC1BC492B0DD88A00211F24 /* RSiOSDelegation.swift in Sources */,
+ EDC1BC4A2B0DD88A00211F24 /* RSwatchOSLifecycleMonitor.swift in Sources */,
+ EDC1BC4B2B0DD88A00211F24 /* RSUtils.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BC562B0DD89400211F24 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BC572B0DD89400211F24 /* RSUserSessionPlugin.swift in Sources */,
+ EDC1BC582B0DD89400211F24 /* JSON.swift in Sources */,
+ EDC1BC592B0DD89400211F24 /* RSiOSLifecycleEvents.swift in Sources */,
+ EDC1BC5A2B0DD89400211F24 /* RSServiceType.swift in Sources */,
+ EDC1BC5B2B0DD89400211F24 /* NSError+Ext.swift in Sources */,
+ EDC1BC5D2B0DD89400211F24 /* RSDestinationConfig.swift in Sources */,
+ EDC1BC5E2B0DD89400211F24 /* RSMessageType.swift in Sources */,
+ EDC1BC5F2B0DD89400211F24 /* RudderDestinationPlugin.swift in Sources */,
+ ED5372482B1613CE00D794EB /* LogMessages.swift in Sources */,
+ EDC1BC602B0DD89400211F24 /* RSwatchOSLifecycleEvents.swift in Sources */,
+ EDC1BC612B0DD89400211F24 /* RSErrorCode.swift in Sources */,
+ EDC1BC622B0DD89400211F24 /* RSSessionStorage.swift in Sources */,
+ EDC1BC632B0DD89400211F24 /* RSMessage.swift in Sources */,
+ EDC1BC642B0DD89400211F24 /* RSwatchOSDelegation.swift in Sources */,
+ EDC1BC652B0DD89400211F24 /* RSConstants.swift in Sources */,
+ EDC1BC662B0DD89400211F24 /* RSAtomic.swift in Sources */,
+ ED333EBE2B22055D003EB0B3 /* RSContext.swift in Sources */,
+ EDC1BC672B0DD89400211F24 /* RSReplayQueuePlugin.swift in Sources */,
+ EDC1BC682B0DD89400211F24 /* RSOption.swift in Sources */,
+ EDC1BC692B0DD89400211F24 /* RSEventsAndKeys.swift in Sources */,
+ ED53724D2B18ED8E00D794EB /* MockURLProtocol.swift in Sources */,
+ EDC1BC6A2B0DD89400211F24 /* RSIntegrationPlugin.swift in Sources */,
+ EDC1BC6B2B0DD89400211F24 /* RSRepeatingTimer.swift in Sources */,
+ EDC1BC6C2B0DD89400211F24 /* RSmacOSLifecycleEvents.swift in Sources */,
+ EDC1BC6D2B0DD89400211F24 /* RSAppTrackingConsent.swift in Sources */,
+ EDC1BC6E2B0DD89400211F24 /* RSConfig.swift in Sources */,
+ EDC1BC6F2B0DD89400211F24 /* RSKeyPath.swift in Sources */,
+ EDC1BC702B0DD89400211F24 /* API.swift in Sources */,
+ EDC1BC712B0DD89400211F24 /* RSDatabaseManager.swift in Sources */,
+ EDC1BC722B0DD89400211F24 /* RSVersion.swift in Sources */,
+ EDC1BC732B0DD89400211F24 /* RSServerConfig.swift in Sources */,
+ EDC1BC742B0DD89400211F24 /* RSmacOSLifecycleMonitor.swift in Sources */,
+ EDC1BC9F2B1465AC00211F24 /* TestUtils.swift in Sources */,
+ EDC1BC752B0DD89400211F24 /* RSiOSLifecycleMonitor.swift in Sources */,
+ EDC1BC762B0DD89400211F24 /* RSUserInfo.swift in Sources */,
+ EDC1BC782B0DD89400211F24 /* RSPushNotifications.swift in Sources */,
+ ED333EB92B21F324003EB0B3 /* RSSessionStoragePlugin.swift in Sources */,
+ EDC1BC792B0DD89400211F24 /* RSController.swift in Sources */,
+ EDC1BC7B2B0DD89400211F24 /* RSwatchOSScreenViewEvents.swift in Sources */,
+ EDC1BC7D2B0DD89400211F24 /* RSTypeAlias.swift in Sources */,
+ EDC1BC7E2B0DD89400211F24 /* RSiOSScreenViewEvents.swift in Sources */,
+ EDC1BC7F2B0DD89400211F24 /* RSUserDefaults.swift in Sources */,
+ EDC1BC802B0DD89400211F24 /* RSmacOSScreenViewEvents.swift in Sources */,
+ EDC1BC812B0DD89400211F24 /* Vendor.swift in Sources */,
+ EDC1BC822B0DD89400211F24 /* RSLifeCycle.swift in Sources */,
+ EDC1BC832B0DD89400211F24 /* String+Ext.swift in Sources */,
+ EDC1BC842B0DD89400211F24 /* RSPlugins.swift in Sources */,
+ EDC1BC852B0DD89400211F24 /* RSDestinationDefinition.swift in Sources */,
+ EDC1BC862B0DD89400211F24 /* RSClient.swift in Sources */,
+ EDC1BC872B0DD89400211F24 /* AppleUtils.swift in Sources */,
+ EDC1BC882B0DD89400211F24 /* RSClient+Plugins.swift in Sources */,
+ EDC1BCE02B14738F00211F24 /* Logger.swift in Sources */,
+ EDC1BC892B0DD89400211F24 /* RSContextPlugin.swift in Sources */,
+ EDC1BC8A2B0DD89400211F24 /* Data+Ext.swift in Sources */,
+ EDC1BC8B2B0DD89400211F24 /* RSServiceManager.swift in Sources */,
+ EDC1BC8C2B0DD89400211F24 /* RSDBMessage.swift in Sources */,
+ EDC1BC8D2B0DD89400211F24 /* RSDestination.swift in Sources */,
+ EDC1BC8E2B0DD89400211F24 /* RSiOSDelegation.swift in Sources */,
+ EDC1BC8F2B0DD89400211F24 /* RSwatchOSLifecycleMonitor.swift in Sources */,
+ EDC1BC902B0DD89400211F24 /* RSUtils.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BCA42B146A2D00211F24 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BCA52B146A2D00211F24 /* RSClientTests.swift in Sources */,
+ EDC1BCA62B146A2D00211F24 /* RSmacOSLifeCycleEventTests.swift in Sources */,
+ EDC1BCA72B146A2D00211F24 /* RSwatchOSLifeCycleEventTests.swift in Sources */,
+ EDC1BCA82B146A2D00211F24 /* RSWhiteListedEventsTests.swift in Sources */,
+ EDC1BCA92B146A2D00211F24 /* RSThreadTests.swift in Sources */,
+ EDC1BCAA2B146A2D00211F24 /* RSiOSLifeCycleEventTests.swift in Sources */,
+ EDC1BCAB2B146A2D00211F24 /* RSBlackListedEventsTest.swift in Sources */,
+ EDC1BCAC2B146A2D00211F24 /* RSDatabaseTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BCB82B146A3800211F24 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BCB92B146A3800211F24 /* RSClientTests.swift in Sources */,
+ EDC1BCBA2B146A3800211F24 /* RSmacOSLifeCycleEventTests.swift in Sources */,
+ EDC1BCBB2B146A3800211F24 /* RSwatchOSLifeCycleEventTests.swift in Sources */,
+ EDC1BCBC2B146A3800211F24 /* RSWhiteListedEventsTests.swift in Sources */,
+ EDC1BCBD2B146A3800211F24 /* RSThreadTests.swift in Sources */,
+ EDC1BCBE2B146A3800211F24 /* RSiOSLifeCycleEventTests.swift in Sources */,
+ EDC1BCBF2B146A3800211F24 /* RSBlackListedEventsTest.swift in Sources */,
+ EDC1BCC02B146A3800211F24 /* RSDatabaseTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ EDC1BCCC2B146A4E00211F24 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ EDC1BCCD2B146A4E00211F24 /* RSClientTests.swift in Sources */,
+ EDC1BCCE2B146A4E00211F24 /* RSmacOSLifeCycleEventTests.swift in Sources */,
+ EDC1BCCF2B146A4E00211F24 /* RSwatchOSLifeCycleEventTests.swift in Sources */,
+ EDC1BCD02B146A4E00211F24 /* RSWhiteListedEventsTests.swift in Sources */,
+ EDC1BCD12B146A4E00211F24 /* RSThreadTests.swift in Sources */,
+ EDC1BCD22B146A4E00211F24 /* RSiOSLifeCycleEventTests.swift in Sources */,
+ EDC1BCD32B146A4E00211F24 /* RSBlackListedEventsTest.swift in Sources */,
+ EDC1BCD42B146A4E00211F24 /* RSDatabaseTests.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ ED3D225D279EAC2800EC8366 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 06CABB832630C3CA0097BEFF /* Rudder-iOS */;
+ targetProxy = ED3D225C279EAC2800EC8366 /* PBXContainerItemProxy */;
+ };
+ ED5372402B15C6BC00D794EB /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = EDC1BC0E2B0DD88A00211F24 /* Rudder-tvOS */;
+ targetProxy = ED53723F2B15C6BC00D794EB /* PBXContainerItemProxy */;
+ };
+ ED5372422B15C6C600D794EB /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = EDC1BC532B0DD89400211F24 /* Rudder-watchOS */;
+ targetProxy = ED5372412B15C6C600D794EB /* PBXContainerItemProxy */;
+ };
+ ED5372442B15C6CE00D794EB /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = EDC1BBC92B0DD87D00211F24 /* Rudder-macOS */;
+ targetProxy = ED5372432B15C6CE00D794EB /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 06CABB962630C3CA0097BEFF /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
@@ -909,7 +1643,8 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
- INFOPLIST_FILE = "$(SRCROOT)/Sources/SDKInfo/Info.plist";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -917,16 +1652,16 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
- MARKETING_VERSION = 2.2.4;
+ MARKETING_VERSION = 2.2.7;
PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderStack;
- PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ PRODUCT_NAME = Rudder;
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
- SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvsimulator appletvos watchsimulator watchos macosx";
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SUPPORTS_MACCATALYST = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = "1,2,3,4,6";
+ TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 12.0;
};
name = Debug;
@@ -945,7 +1680,8 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_TESTABILITY = NO;
- INFOPLIST_FILE = "$(SRCROOT)/Sources/SDKInfo/Info.plist";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -953,15 +1689,15 @@
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
- MARKETING_VERSION = 2.2.4;
+ MARKETING_VERSION = 2.2.7;
PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderStack;
- PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ PRODUCT_NAME = Rudder;
PROVISIONING_PROFILE_SPECIFIER = "";
SKIP_INSTALL = YES;
- SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvsimulator appletvos watchsimulator watchos macosx";
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SUPPORTS_MACCATALYST = YES;
SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = "1,2,3,4,6";
+ TARGETED_DEVICE_FAMILY = "1,2";
TVOS_DEPLOYMENT_TARGET = 12.0;
};
name = Release;
@@ -974,16 +1710,16 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = GTGKNDBD23;
GENERATE_INFOPLIST_FILE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 15.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderTests;
PRODUCT_NAME = "$(TARGET_NAME)";
- SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvsimulator appletvos watchsimulator watchos macosx";
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = "1,2,3,4,6";
+ TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
@@ -995,11 +1731,362 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = GTGKNDBD23;
GENERATE_INFOPLIST_FILE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 15.2;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderTests;
PRODUCT_NAME = "$(TARGET_NAME)";
- SUPPORTED_PLATFORMS = "iphonesimulator iphoneos appletvsimulator appletvos watchsimulator watchos macosx";
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ EDC1BC0B2B0DD87D00211F24 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = NO;
+ BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_STYLE = Manual;
+ CURRENT_PROJECT_VERSION = 8;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MARKETING_VERSION = 2.2.7;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderStack;
+ PRODUCT_NAME = Rudder;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = macosx;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ SUPPORTS_MACCATALYST = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2,3,4,6";
+ TVOS_DEPLOYMENT_TARGET = 12.0;
+ };
+ name = Debug;
+ };
+ EDC1BC0C2B0DD87D00211F24 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = NO;
+ BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_STYLE = Manual;
+ CURRENT_PROJECT_VERSION = 8;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_TESTABILITY = NO;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MARKETING_VERSION = 2.2.7;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderStack;
+ PRODUCT_NAME = Rudder;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = macosx;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = macosx;
+ SUPPORTS_MACCATALYST = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2,3,4,6";
+ TVOS_DEPLOYMENT_TARGET = 12.0;
+ };
+ name = Release;
+ };
+ EDC1BC502B0DD88A00211F24 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = NO;
+ BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_STYLE = Manual;
+ CURRENT_PROJECT_VERSION = 8;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MARKETING_VERSION = 2.2.7;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderStack;
+ PRODUCT_NAME = Rudder;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = appletvos;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = "appletvsimulator appletvos";
+ SUPPORTS_MACCATALYST = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 3;
+ TVOS_DEPLOYMENT_TARGET = 12.0;
+ };
+ name = Debug;
+ };
+ EDC1BC512B0DD88A00211F24 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = NO;
+ BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_STYLE = Manual;
+ CURRENT_PROJECT_VERSION = 8;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_TESTABILITY = NO;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MARKETING_VERSION = 2.2.7;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderStack;
+ PRODUCT_NAME = Rudder;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = appletvos;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = "appletvsimulator appletvos";
+ SUPPORTS_MACCATALYST = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 3;
+ TVOS_DEPLOYMENT_TARGET = 12.0;
+ };
+ name = Release;
+ };
+ EDC1BC952B0DD89400211F24 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = NO;
+ BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_STYLE = Manual;
+ CURRENT_PROJECT_VERSION = 8;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MARKETING_VERSION = 2.2.7;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderStack;
+ PRODUCT_NAME = Rudder;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = "watchsimulator watchos";
+ SUPPORTS_MACCATALYST = YES;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ TVOS_DEPLOYMENT_TARGET = 12.0;
+ };
+ name = Debug;
+ };
+ EDC1BC962B0DD89400211F24 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ APPLICATION_EXTENSION_API_ONLY = NO;
+ BUILD_LIBRARY_FOR_DISTRIBUTION = YES;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_STYLE = Manual;
+ CURRENT_PROJECT_VERSION = 8;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = "";
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ ENABLE_TESTABILITY = NO;
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_FILE = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MARKETING_VERSION = 2.2.7;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderStack;
+ PRODUCT_NAME = Rudder;
+ PROVISIONING_PROFILE_SPECIFIER = "";
+ SDKROOT = watchos;
+ SKIP_INSTALL = YES;
+ SUPPORTED_PLATFORMS = "watchsimulator watchos";
+ SUPPORTS_MACCATALYST = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ TVOS_DEPLOYMENT_TARGET = 12.0;
+ };
+ name = Release;
+ };
+ EDC1BCB22B146A2D00211F24 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = GTGKNDBD23;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = watchos;
+ SUPPORTED_PLATFORMS = "watchsimulator watchos";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ };
+ name = Debug;
+ };
+ EDC1BCB32B146A2D00211F24 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = GTGKNDBD23;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = watchos;
+ SUPPORTED_PLATFORMS = "watchsimulator watchos";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 4;
+ };
+ name = Release;
+ };
+ EDC1BCC62B146A3800211F24 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = GTGKNDBD23;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = appletvos;
+ SUPPORTED_PLATFORMS = "appletvsimulator appletvos";
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Debug;
+ };
+ EDC1BCC72B146A3800211F24 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = GTGKNDBD23;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = appletvos;
+ SUPPORTED_PLATFORMS = "appletvsimulator appletvos";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = 3;
+ };
+ name = Release;
+ };
+ EDC1BCDA2B146A4E00211F24 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = GTGKNDBD23;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ SUPPORTED_PLATFORMS = macosx;
+ SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2,3,4,6";
+ };
+ name = Debug;
+ };
+ EDC1BCDB2B146A4E00211F24 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = GTGKNDBD23;
+ GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 12.0;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = com.rudderstack.RudderTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ SUPPORTED_PLATFORMS = macosx;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
@@ -1019,7 +2106,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 06CABB982630C3CA0097BEFF /* Build configuration list for PBXNativeTarget "Rudder" */ = {
+ 06CABB982630C3CA0097BEFF /* Build configuration list for PBXNativeTarget "Rudder-iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
06CABB992630C3CA0097BEFF /* Debug */,
@@ -1028,7 +2115,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- ED3D225E279EAC2800EC8366 /* Build configuration list for PBXNativeTarget "RudderTests" */ = {
+ ED3D225E279EAC2800EC8366 /* Build configuration list for PBXNativeTarget "RudderTests-iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
ED3D225F279EAC2800EC8366 /* Debug */,
@@ -1037,6 +2124,60 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ EDC1BC0A2B0DD87D00211F24 /* Build configuration list for PBXNativeTarget "Rudder-macOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EDC1BC0B2B0DD87D00211F24 /* Debug */,
+ EDC1BC0C2B0DD87D00211F24 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ EDC1BC4F2B0DD88A00211F24 /* Build configuration list for PBXNativeTarget "Rudder-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EDC1BC502B0DD88A00211F24 /* Debug */,
+ EDC1BC512B0DD88A00211F24 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ EDC1BC942B0DD89400211F24 /* Build configuration list for PBXNativeTarget "Rudder-watchOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EDC1BC952B0DD89400211F24 /* Debug */,
+ EDC1BC962B0DD89400211F24 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ EDC1BCB12B146A2D00211F24 /* Build configuration list for PBXNativeTarget "RudderTests-watchOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EDC1BCB22B146A2D00211F24 /* Debug */,
+ EDC1BCB32B146A2D00211F24 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ EDC1BCC52B146A3800211F24 /* Build configuration list for PBXNativeTarget "RudderTests-tvOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EDC1BCC62B146A3800211F24 /* Debug */,
+ EDC1BCC72B146A3800211F24 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ EDC1BCD92B146A4E00211F24 /* Build configuration list for PBXNativeTarget "RudderTests-macOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ EDC1BCDA2B146A4E00211F24 /* Debug */,
+ EDC1BCDB2B146A4E00211F24 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
/* End XCConfigurationList section */
};
rootObject = 06CABB7B2630C3CA0097BEFF /* Project object */;
diff --git a/Rudder.xcodeproj/xcshareddata/xcschemes/RudderSDK-iOS.xcscheme b/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-iOS.xcscheme
similarity index 77%
rename from Rudder.xcodeproj/xcshareddata/xcschemes/RudderSDK-iOS.xcscheme
rename to Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-iOS.xcscheme
index 3efd83d0..59efbf20 100644
--- a/Rudder.xcodeproj/xcshareddata/xcschemes/RudderSDK-iOS.xcscheme
+++ b/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-iOS.xcscheme
@@ -1,7 +1,7 @@
+ LastUpgradeVersion = "1500"
+ version = "1.7">
@@ -16,7 +16,7 @@
BuildableIdentifier = "primary"
BlueprintIdentifier = "06CABB832630C3CA0097BEFF"
BuildableName = "Rudder.framework"
- BlueprintName = "Rudder"
+ BlueprintName = "Rudder-iOS"
ReferencedContainer = "container:Rudder.xcodeproj">
@@ -26,19 +26,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- shouldUseLaunchSchemeArgsEnv = "YES">
-
-
-
-
-
-
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ shouldAutocreateTestPlan = "YES">
diff --git a/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-macOS.xcscheme b/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-macOS.xcscheme
new file mode 100644
index 00000000..b688f2e8
--- /dev/null
+++ b/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-macOS.xcscheme
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-tvOS.xcscheme b/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-tvOS.xcscheme
new file mode 100644
index 00000000..f3c673c3
--- /dev/null
+++ b/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-tvOS.xcscheme
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-watchOS.xcscheme b/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-watchOS.xcscheme
new file mode 100644
index 00000000..47727f17
--- /dev/null
+++ b/Rudder.xcodeproj/xcshareddata/xcschemes/Rudder-watchOS.xcscheme
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests.xcscheme b/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-iOS.xcscheme
similarity index 94%
rename from Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests.xcscheme
rename to Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-iOS.xcscheme
index 1d9c9646..d72112df 100644
--- a/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests.xcscheme
+++ b/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-iOS.xcscheme
@@ -17,8 +17,8 @@
diff --git a/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-macOS.xcscheme b/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-macOS.xcscheme
new file mode 100644
index 00000000..0d1b9c9c
--- /dev/null
+++ b/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-macOS.xcscheme
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-tvOS.xcscheme b/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-tvOS.xcscheme
new file mode 100644
index 00000000..91373d65
--- /dev/null
+++ b/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-tvOS.xcscheme
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-watchOS.xcscheme b/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-watchOS.xcscheme
new file mode 100644
index 00000000..fd0ddc78
--- /dev/null
+++ b/Rudder.xcodeproj/xcshareddata/xcschemes/RudderTests-watchOS.xcscheme
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Tests/RudderTests/RSBlackListedEventsTest.swift b/RudderTests/RSBlackListedEventsTest.swift
similarity index 78%
rename from Tests/RudderTests/RSBlackListedEventsTest.swift
rename to RudderTests/RSBlackListedEventsTest.swift
index 91bcaa12..83ae25d4 100644
--- a/Tests/RudderTests/RSBlackListedEventsTest.swift
+++ b/RudderTests/RSBlackListedEventsTest.swift
@@ -9,14 +9,14 @@
import XCTest
@testable import Rudder
-// swiftlint:disable inclusive_language
+
class RSBlackListedEventsTest: XCTestCase {
var client: RSClient!
override func setUpWithError() throws {
- client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
+// client = RSClient.sharedInstance()
+// client.configure(with: RSConfig(writeKey: "WRITE_KEY").dataPlaneURL("DATA_PLANE_URL"))
}
override func tearDownWithError() throws {
@@ -26,7 +26,7 @@ class RSBlackListedEventsTest: XCTestCase {
// swiftlint:disable inclusive_language
// make sure you select 'Blacklist' for 'Client-side Events Filtering' section in
// Configuration from RudderStack dashboard. It will take 5 min to be affected.
- func testBlackListedSuccess() {
+ /*func testBlackListedSuccess() {
let expectation = XCTestExpectation(description: "Firebase Expectation")
let myDestination = FirebaseDestination {
expectation.fulfill()
@@ -54,13 +54,5 @@ class RSBlackListedEventsTest: XCTestCase {
waitUntilStarted(client: client)
client.track("track_blacklist_2")
wait(for: [expectation], timeout: 2.0)
- }
-
- func testPerformanceExample() throws {
- // This is an example of a performance test case.
- self.measure {
- // Put the code you want to measure the time of here.
- }
- }
-
+ }*/
}
diff --git a/RudderTests/RSClientTests.swift b/RudderTests/RSClientTests.swift
new file mode 100644
index 00000000..1e273986
--- /dev/null
+++ b/RudderTests/RSClientTests.swift
@@ -0,0 +1,435 @@
+//
+// RSClientTests.swift
+// RudderStackTests
+//
+// Created by Pallab Maiti on 07/03/22.
+// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
+//
+
+import XCTest
+@testable import Rudder
+
+class RSClientTests: XCTestCase {
+
+ var client: RSClient!
+
+ override func setUpWithError() throws {
+ try super.setUpWithError()
+ client = RSClient.sharedInstance()
+ let userDefaults = UserDefaults(suiteName: #file) ?? UserDefaults.standard
+ userDefaults.removePersistentDomain(forName: #file)
+ client.userDefaults = RSUserDefaults(userDefaults: userDefaults)
+
+ client.configure(with: RSConfig(writeKey: "WRITE_KEY").dataPlaneURL("DATA_PLANE_URL"))
+ }
+
+ override func tearDownWithError() throws {
+ try super.tearDownWithError()
+ client = nil
+ }
+
+ func testAlias() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.alias("user_id")
+
+ let aliasEvent1 = resultPlugin.lastMessage as? AliasMessage
+
+ XCTAssertTrue(aliasEvent1?.userId == "user_id")
+ XCTAssertTrue(aliasEvent1?.type == .alias)
+ XCTAssertNil(aliasEvent1?.option)
+ XCTAssertNil(aliasEvent1?.previousId)
+
+ client.alias("new_user_id")
+
+ let aliasEvent2 = resultPlugin.lastMessage as? AliasMessage
+
+ XCTAssertTrue(aliasEvent2?.userId == "new_user_id")
+ XCTAssertTrue(aliasEvent2?.previousId == "user_id")
+ XCTAssertTrue(aliasEvent2?.type == .alias)
+ XCTAssertNil(aliasEvent2?.option)
+ }
+
+ func testGroup() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.group("sample_group_id")
+
+ let groupEvent = resultPlugin.lastMessage as? GroupMessage
+
+ XCTAssertTrue(groupEvent?.groupId == "sample_group_id")
+ XCTAssertTrue(groupEvent?.type == .group)
+ XCTAssertNil(groupEvent?.traits)
+ XCTAssertNil(groupEvent?.option)
+ }
+
+ func testGroupWithTraits() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.group("sample_group_id", traits: ["key_1": "value_1", "key_2": "value_2"])
+
+ let groupEvent = resultPlugin.lastMessage as? GroupMessage
+
+ XCTAssertTrue(groupEvent?.groupId == "sample_group_id")
+ XCTAssertTrue(groupEvent?.type == .group)
+ XCTAssertNotNil(groupEvent?.traits)
+ XCTAssertNil(groupEvent?.option)
+
+ let traits = groupEvent?.traits
+
+ XCTAssertTrue(traits?["key_1"] == "value_1")
+ XCTAssertTrue(traits?["key_2"] == "value_2")
+ }
+
+ func testIdentify() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.identify("user_id")
+
+ let identifyEvent = resultPlugin.lastMessage as? IdentifyMessage
+
+ XCTAssertTrue(identifyEvent?.userId == "user_id")
+ XCTAssertTrue(identifyEvent?.type == .identify)
+ }
+
+ func testIdentifyWithTraits() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.identify("user_id", traits: ["email": "abc@def.com"])
+
+ let identifyEvent = resultPlugin.lastMessage as? IdentifyMessage
+
+ XCTAssertTrue(identifyEvent?.userId == "user_id")
+ XCTAssertTrue(identifyEvent?.type == .identify)
+
+ let traits = identifyEvent?.traits
+
+ XCTAssertTrue(traits?["email"] as? String == "abc@def.com")
+ XCTAssertFalse(traits?["name"] as? String == "name")
+ }
+
+ func testUserIdAndTraitsPersistCorrectly() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.identify("user_id", traits: ["email": "abc@def.com"])
+
+ let identifyEvent = resultPlugin.lastMessage as? IdentifyMessage
+
+ XCTAssertTrue(identifyEvent?.userId == "user_id")
+ XCTAssertTrue(identifyEvent?.type == .identify)
+
+ let traits = identifyEvent?.traits
+
+ XCTAssertTrue(traits?["email"] as? String == "abc@def.com")
+ XCTAssertFalse(traits?["name"] as? String == "name")
+
+ client.track("simple_track")
+
+ let trackEvent = resultPlugin.lastMessage as? TrackMessage
+
+ XCTAssertTrue(trackEvent?.userId == "user_id")
+ let trackTraits = trackEvent?.context?["traits"] as? [String: Any]
+ XCTAssertNotNil(trackTraits)
+ XCTAssertTrue(trackTraits?["email"] as? String == "abc@def.com")
+ XCTAssertTrue(trackTraits?["userId"] as? String == "user_id")
+ }
+
+ func testScreen() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.screen("ViewController")
+
+ let screenEvent = resultPlugin.lastMessage as? ScreenMessage
+ XCTAssertTrue(screenEvent?.name == "ViewController")
+ XCTAssertTrue(screenEvent?.type == .screen)
+ }
+
+ func testScreenWithProperties() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.screen("ViewController", properties: ["key_1": "value_1", "key_2": "value_2"])
+
+ let screenEvent = resultPlugin.lastMessage as? ScreenMessage
+
+ XCTAssertTrue(screenEvent?.name == "ViewController")
+ XCTAssertTrue(screenEvent?.type == .screen)
+ XCTAssertNotNil(screenEvent?.properties)
+ XCTAssertNil(screenEvent?.option)
+
+ let properties = screenEvent?.properties
+
+ XCTAssertTrue(properties?["key_1"] as? String == "value_1")
+ XCTAssertTrue(properties?["key_2"] as? String == "value_2")
+ }
+
+ func testTrack() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.track("simple_track")
+
+ let trackEvent = resultPlugin.lastMessage as? TrackMessage
+
+ XCTAssertTrue(trackEvent?.event == "simple_track")
+ XCTAssertTrue(trackEvent?.type == .track)
+ XCTAssertNil(trackEvent?.properties)
+ XCTAssertNil(trackEvent?.option)
+ }
+
+ func testTrackWithProperties() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+ client.track("simple_track_with_props", properties: ["key_1": "value_1", "key_2": "value_2"])
+
+ let trackEvent = resultPlugin.lastMessage as? TrackMessage
+
+ XCTAssertTrue(trackEvent?.event == "simple_track_with_props")
+ XCTAssertTrue(trackEvent?.type == .track)
+ XCTAssertNotNil(trackEvent?.properties)
+ XCTAssertNil(trackEvent?.option)
+
+ let properties = trackEvent?.properties
+
+ XCTAssertTrue(properties?["key_1"] as? String == "value_1")
+ XCTAssertTrue(properties?["key_2"] as? String == "value_2")
+ }
+
+ // make sure you have Firebase added & enabled to the source in your RudderStack A/C
+ /*func testDestinationEnabled() {
+ let expectation = XCTestExpectation(description: "Firebase Expectation")
+ let myDestination = FirebaseDestination {
+ expectation.fulfill()
+ return true
+ }
+
+ client.addDestination(myDestination)
+
+ waitUntilStarted(client: client)
+
+ client.track("testDestinationEnabled")
+
+ wait(for: [expectation], timeout: 2.0)
+ }
+
+ func testDestinationNotEnabled() {
+ let expectation = XCTestExpectation(description: "MyDestination Expectation")
+ let myDestination = MyDestination {
+ expectation.fulfill()
+ return true
+ }
+
+ client.addDestination(myDestination)
+
+ waitUntilStarted(client: client)
+ client.track("testDestinationEnabled")
+
+ XCTExpectFailure {
+ wait(for: [expectation], timeout: 2.0)
+ }
+ }*/
+
+ func testAnonymousId() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ client.setAnonymousId("anonymous_id")
+
+ waitUntilStarted(client: client)
+
+ client.track("test_anonymous_id")
+
+ let anonId = client.anonymousId
+
+ XCTAssertTrue(anonId != "")
+ XCTAssertTrue(anonId == "anonymous_id")
+
+ let anonymousId = resultPlugin.lastMessage?.anonymousId
+
+ XCTAssertTrue(anonymousId != "")
+ XCTAssertTrue(anonymousId == "anonymous_id")
+ }
+
+ func testContext() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+
+ client.track("context check")
+
+ let context = resultPlugin.lastMessage?.context
+ XCTAssertNotNil(context)
+ XCTAssertNotNil(context?["screen"], "screen missing!")
+ XCTAssertNotNil(context?["network"], "network missing!")
+ XCTAssertNotNil(context?["os"], "os missing!")
+ XCTAssertNotNil(context?["timezone"], "timezone missing!")
+ XCTAssertNotNil(context?["library"], "library missing!")
+ XCTAssertNotNil(context?["device"], "device missing!")
+ XCTAssertNotNil(context?["app"], "app missing!")
+ XCTAssertNotNil(context?["locale"], "locale missing!")
+ }
+
+ func testDeviceToken() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+
+ client.setDeviceToken("device_token")
+ client.track("device token check")
+
+ let context = resultPlugin.lastMessage?.context
+ let token = context?[keyPath: "device.token"] as? String
+
+ XCTAssertTrue(token != "")
+ XCTAssertTrue(token == "device_token")
+ }
+
+ func testContextTraits() {
+ let resultPlugin = ResultPlugin()
+ client.add(plugin: resultPlugin)
+
+ waitUntilStarted(client: client)
+
+
+ client.identify("user_id", traits: ["email": "abc@def.com"])
+
+ let identifyEvent = resultPlugin.lastMessage as? IdentifyMessage
+ XCTAssertTrue(identifyEvent?.userId == "user_id")
+ let identifyTraits = identifyEvent?.traits
+ XCTAssertTrue(identifyTraits?["email"] as? String == "abc@def.com")
+
+ client.track("test context")
+
+ let trackEvent = resultPlugin.lastMessage as? TrackMessage
+ XCTAssertTrue(trackEvent?.userId == "user_id")
+ let trackTraits = trackEvent?.context?["traits"] as? [String: Any]
+ XCTAssertNotNil(trackTraits)
+ XCTAssertTrue(trackTraits?["email"] as? String == "abc@def.com")
+ XCTAssertTrue(trackTraits?["userId"] as? String == "user_id")
+
+ let clientTraits = client.traits
+ XCTAssertNotNil(clientTraits)
+ XCTAssertTrue(clientTraits?["email"] as? String == "abc@def.com")
+ XCTAssertTrue(clientTraits?["userId"] as? String == "user_id")
+ }
+}
+
+func waitUntilStarted(client: RSClient?) {
+ guard let client = client else { return }
+ if let replayQueue = client.find(pluginType: RSReplayQueuePlugin.self) {
+ while replayQueue.running == true {
+ RunLoop.main.run(until: Date.distantPast)
+ }
+ }
+}
+
+class FirebaseDestinationPlugin: RSDestinationPlugin {
+ var controller: RSController = RSController()
+ var client: RSClient?
+ var type: PluginType = .destination
+ var key: String = "Firebase"
+
+ let trackCompletion: (() -> Bool)?
+
+ init(trackCompletion: (() -> Bool)? = nil) {
+ self.trackCompletion = trackCompletion
+ }
+
+ func track(message: TrackMessage) -> TrackMessage? {
+ var returnEvent: TrackMessage? = message
+ if let completion = trackCompletion {
+ if !completion() {
+ returnEvent = nil
+ }
+ }
+ return returnEvent
+ }
+}
+
+class MyDestinationPlugin: RSDestinationPlugin {
+ var controller: RSController = RSController()
+ var client: RSClient?
+ var type: PluginType = .destination
+ var key: String = "MyDestination"
+
+ let trackCompletion: (() -> Bool)?
+
+ init(trackCompletion: (() -> Bool)? = nil) {
+ self.trackCompletion = trackCompletion
+ }
+
+ func track(message: TrackMessage) -> TrackMessage? {
+ var returnEvent: TrackMessage? = message
+ if let completion = trackCompletion {
+ if !completion() {
+ returnEvent = nil
+ }
+ }
+ return returnEvent
+ }
+}
+
+class FirebaseDestination: RudderDestination {
+ init(trackCompletion: (() -> Bool)?) {
+ super.init()
+ plugin = FirebaseDestinationPlugin(trackCompletion: trackCompletion)
+ }
+}
+
+class MyDestination: RudderDestination {
+ init(trackCompletion: (() -> Bool)?) {
+ super.init()
+ plugin = MyDestinationPlugin(trackCompletion: trackCompletion)
+ }
+}
+
+class ResultPlugin: RSPlugin {
+ let type: PluginType = .after
+ var client: RSClient?
+ var lastMessage: RSMessage?
+ var trackList = [TrackMessage]()
+ var identifyList = [IdentifyMessage]()
+
+ func execute(message: T?) -> T? where T: RSMessage {
+ lastMessage = message
+ if let message = message as? TrackMessage {
+ trackList.append(message)
+ }
+ if let message = message as? IdentifyMessage {
+ identifyList.append(message)
+ }
+ return message
+ }
+}
diff --git a/RudderTests/RSClientTests.swift.plist b/RudderTests/RSClientTests.swift.plist
new file mode 100644
index 00000000..09debe4a
Binary files /dev/null and b/RudderTests/RSClientTests.swift.plist differ
diff --git a/Tests/RudderTests/RSDatabaseTests.swift b/RudderTests/RSDatabaseTests.swift
similarity index 87%
rename from Tests/RudderTests/RSDatabaseTests.swift
rename to RudderTests/RSDatabaseTests.swift
index 18249cc5..3a8af547 100644
--- a/Tests/RudderTests/RSDatabaseTests.swift
+++ b/RudderTests/RSDatabaseTests.swift
@@ -16,18 +16,18 @@ class RSDatabaseTests: XCTestCase {
var databaseManager: RSDatabaseManager!
override func setUpWithError() throws {
- client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
- databaseManager = RSDatabaseManager(client: client)
+// client = RSClient.sharedInstance()
+// client.configure(with: RSConfig(writeKey: "WRITE_KEY").dataPlaneURL("DATA_PLANE_URL"))
+// databaseManager = RSDatabaseManager(client: client)
}
override func tearDownWithError() throws {
client = nil
}
- func testWriteEvent() {
+ /*func testWriteEvent() {
let trackMessage = TrackMessage(event: "sample_track1", properties: nil)
- .applyRawEventData()
+ .applyRawEventData(userInfo: client.userInfo)
databaseManager.write(trackMessage)
RunLoop.current.run(until: Date(timeIntervalSinceNow: 2))
@@ -42,7 +42,7 @@ class RSDatabaseTests: XCTestCase {
func testRemoveEvent() {
let trackMessage = TrackMessage(event: "sample_track1", properties: nil)
- .applyRawEventData()
+ .applyRawEventData(userInfo: client.userInfo)
databaseManager.write(trackMessage)
RunLoop.current.run(until: Date(timeIntervalSinceNow: 2))
@@ -64,7 +64,7 @@ class RSDatabaseTests: XCTestCase {
} else {
XCTFail("No events found")
}
- }
+ }*/
func fetchAllEvents() -> [[String: Any]]? {
let totalCount = databaseManager.getDBRecordCount()
diff --git a/Tests/RudderTests/RSThreadTests.swift b/RudderTests/RSThreadTests.swift
similarity index 98%
rename from Tests/RudderTests/RSThreadTests.swift
rename to RudderTests/RSThreadTests.swift
index 8da2d206..e65ad7da 100644
--- a/Tests/RudderTests/RSThreadTests.swift
+++ b/RudderTests/RSThreadTests.swift
@@ -11,7 +11,7 @@ import XCTest
class RSThreadTests: XCTestCase {
- var client: RSClient!
+ /*var client: RSClient!
override func setUpWithError() throws {
client = RSClient.sharedInstance()
@@ -89,5 +89,5 @@ class RSThreadTests: XCTestCase {
}
wait(for: [exp], timeout: 100)
- }
+ }*/
}
diff --git a/Tests/RudderTests/RSWhiteListedEventsTests.swift b/RudderTests/RSWhiteListedEventsTests.swift
similarity index 92%
rename from Tests/RudderTests/RSWhiteListedEventsTests.swift
rename to RudderTests/RSWhiteListedEventsTests.swift
index 93d8291a..176ff160 100644
--- a/Tests/RudderTests/RSWhiteListedEventsTests.swift
+++ b/RudderTests/RSWhiteListedEventsTests.swift
@@ -12,11 +12,11 @@ import XCTest
// swiftlint:disable inclusive_language
class RSWhiteListedEventsTests: XCTestCase {
- var client: RSClient!
+ /*var client: RSClient!
override func setUpWithError() throws {
client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
+ client.configure(with: RSConfig(writeKey: "WRITE_KEY").dataPlaneURL("DATA_PLANE_URL"))
}
override func tearDownWithError() throws {
@@ -54,5 +54,5 @@ class RSWhiteListedEventsTests: XCTestCase {
XCTExpectFailure {
wait(for: [expectation], timeout: 2.0)
}
- }
+ }*/
}
diff --git a/Tests/RudderTests/RSiOSLifeCycleEventTests.swift b/RudderTests/RSiOSLifeCycleEventTests.swift
similarity index 86%
rename from Tests/RudderTests/RSiOSLifeCycleEventTests.swift
rename to RudderTests/RSiOSLifeCycleEventTests.swift
index 4e9aa525..13b4aade 100644
--- a/Tests/RudderTests/RSiOSLifeCycleEventTests.swift
+++ b/RudderTests/RSiOSLifeCycleEventTests.swift
@@ -16,7 +16,7 @@ class RSiOSLifeCycleEventTests: XCTestCase {
override func setUpWithError() throws {
client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
+ client.configure(with: RSConfig(writeKey: "WRITE_KEY").dataPlaneURL("DATA_PLANE_URL"))
}
override func tearDownWithError() throws {
@@ -31,10 +31,10 @@ class RSiOSLifeCycleEventTests: XCTestCase {
client.add(plugin: iOSLifeCyclePlugin)
waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
- RSUserDefaults.saveApplicationVersion(nil)
- RSUserDefaults.saveApplicationBuild(nil)
+
+ client.userDefaults.write(application: .version, value: nil)
+ client.userDefaults.write(application: .build, value: nil)
// This is a hack that needs to be dealt with
RunLoop.current.run(until: Date(timeIntervalSinceNow: 2))
@@ -57,10 +57,10 @@ class RSiOSLifeCycleEventTests: XCTestCase {
client.add(plugin: iOSLifeCyclePlugin)
waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
- RSUserDefaults.saveApplicationVersion("2.0.0")
- RSUserDefaults.saveApplicationBuild("2")
+
+ client.userDefaults.write(application: .version, value: "2.0.0")
+ client.userDefaults.write(application: .build, value: "2")
// This is a hack that needs to be dealt with
RunLoop.current.run(until: Date(timeIntervalSinceNow: 2))
@@ -83,7 +83,7 @@ class RSiOSLifeCycleEventTests: XCTestCase {
client.add(plugin: iOSLifeCyclePlugin)
waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
+
iOSLifeCyclePlugin.application(nil, didFinishLaunchingWithOptions: nil)
@@ -100,7 +100,7 @@ class RSiOSLifeCycleEventTests: XCTestCase {
client.add(plugin: iOSLifeCyclePlugin)
waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
+
iOSLifeCyclePlugin.applicationDidEnterBackground(application: nil)
diff --git a/Tests/RudderTests/RSmacOSLifeCycleEventTests.swift b/RudderTests/RSmacOSLifeCycleEventTests.swift
similarity index 90%
rename from Tests/RudderTests/RSmacOSLifeCycleEventTests.swift
rename to RudderTests/RSmacOSLifeCycleEventTests.swift
index c936e7ef..8703d204 100644
--- a/Tests/RudderTests/RSmacOSLifeCycleEventTests.swift
+++ b/RudderTests/RSmacOSLifeCycleEventTests.swift
@@ -16,7 +16,7 @@ class RSmacOSLifeCycleEventTests: XCTestCase {
override func setUpWithError() throws {
client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
+ client.configure(with: RSConfig(writeKey: "WRITE_KEY").dataPlaneURL("DATA_PLANE_URL"))
}
override func tearDownWithError() throws {
@@ -33,8 +33,8 @@ class RSmacOSLifeCycleEventTests: XCTestCase {
waitUntilStarted(client: client)
waitUntilServerConfigDownloaded(client: client)
- RSUserDefaults.saveApplicationVersion(nil)
- RSUserDefaults.saveApplicationBuild(nil)
+ client.userDefaults.write(application: .version, value: nil)
+ client.userDefaults.write(application: .build, value: nil)
// This is a hack that needs to be dealt with
RunLoop.current.run(until: Date(timeIntervalSinceNow: 2))
@@ -59,8 +59,8 @@ class RSmacOSLifeCycleEventTests: XCTestCase {
waitUntilStarted(client: client)
waitUntilServerConfigDownloaded(client: client)
- RSUserDefaults.saveApplicationVersion("2.0.0")
- RSUserDefaults.saveApplicationBuild("2")
+ client.userDefaults.write(application: .version, value: "2.0.0")
+ client.userDefaults.write(application: .build, value: "2")
// This is a hack that needs to be dealt with
RunLoop.current.run(until: Date(timeIntervalSinceNow: 2))
diff --git a/Tests/RudderTests/RSwatchOSLifeCycleEventTests.swift b/RudderTests/RSwatchOSLifeCycleEventTests.swift
similarity index 84%
rename from Tests/RudderTests/RSwatchOSLifeCycleEventTests.swift
rename to RudderTests/RSwatchOSLifeCycleEventTests.swift
index d3174e45..30fb0ad2 100644
--- a/Tests/RudderTests/RSwatchOSLifeCycleEventTests.swift
+++ b/RudderTests/RSwatchOSLifeCycleEventTests.swift
@@ -16,7 +16,7 @@ class RSwatchOSLifeCycleEventTests: XCTestCase {
override func setUpWithError() throws {
client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
+ client.configure(with: RSConfig(writeKey: "WRITE_KEY").dataPlaneURL("DATA_PLANE_URL"))
}
override func tearDownWithError() throws {
@@ -31,11 +31,10 @@ class RSwatchOSLifeCycleEventTests: XCTestCase {
client.add(plugin: watchOSLifeCyclePlugin)
waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
- RSUserDefaults.saveApplicationVersion(nil)
- RSUserDefaults.saveApplicationBuild(nil)
-
+ client.userDefaults.write(application: .version, value: nil)
+ client.userDefaults.write(application: .build, value: nil)
+
// This is a hack that needs to be dealt with
RunLoop.current.run(until: Date(timeIntervalSinceNow: 2))
@@ -57,11 +56,10 @@ class RSwatchOSLifeCycleEventTests: XCTestCase {
client.add(plugin: watchOSLifeCyclePlugin)
waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- RSUserDefaults.saveApplicationVersion("2.0.0")
- RSUserDefaults.saveApplicationBuild("2")
+ client.userDefaults.write(application: .version, value: "2.0.0")
+ client.userDefaults.write(application: .build, value: "2")
+
// This is a hack that needs to be dealt with
RunLoop.current.run(until: Date(timeIntervalSinceNow: 2))
@@ -83,7 +81,6 @@ class RSwatchOSLifeCycleEventTests: XCTestCase {
client.add(plugin: watchOSLifeCyclePlugin)
waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
watchOSLifeCyclePlugin.applicationWillEnterForeground(watchExtension: nil)
diff --git a/Sources/Classes/Client/Plugins/RSAdvertisementIdPlugin.swift b/Sources/Classes/Client/Plugins/RSAdvertisementIdPlugin.swift
deleted file mode 100644
index df1e476e..00000000
--- a/Sources/Classes/Client/Plugins/RSAdvertisementIdPlugin.swift
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// RSAdvertisementIdPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 02/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSAdvertisingIdPlugin: RSPlatformPlugin {
- let type = PluginType.before
- var client: RSClient?
-
- var advertisingId: String?
-
- required init() { }
-
- func execute(message: T?) -> T? {
- guard var workingMessage = message else { return message }
- if var context = workingMessage.context, let advertisingId = advertisingId {
- context[keyPath: "device.advertisingId"] = advertisingId
- context[keyPath: "device.adTrackingEnabled"] = true
- workingMessage.context = context
- client?.updateContext(context)
- }
- return workingMessage
- }
-}
-
-extension RSClient {
- /**
- API for setting identifier under context.device.advertisingId.
- - Parameters:
- - advertisingId: IDFA value
- # Example #
- ```
- client.setAdvertisingId("sample_device_token")
- ```
- */
- @objc
- public func setAdvertisingId(_ advertisingId: String) {
- guard advertisingId.isNotEmpty else {
- log(message: "advertisingId can not be empty", logLevel: .warning)
- return
- }
- if let advertisingIdPlugin = self.find(pluginType: RSAdvertisingIdPlugin.self) {
- advertisingIdPlugin.advertisingId = advertisingId
- } else {
- let advertisingIdPlugin = RSAdvertisingIdPlugin()
- advertisingIdPlugin.advertisingId = advertisingId
- add(plugin: advertisingIdPlugin)
- }
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSAliasIdPlugin.swift b/Sources/Classes/Client/Plugins/RSAliasIdPlugin.swift
deleted file mode 100644
index a38f75a3..00000000
--- a/Sources/Classes/Client/Plugins/RSAliasIdPlugin.swift
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// RSAliasIdPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 31/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSAliasIdPlugin: RSPlatformPlugin {
- let type = PluginType.before
- var client: RSClient?
-
- var id: String?
-
- required init() { }
-
- func execute(message: T?) -> T? {
- guard var workingMessage = message else { return message }
- if let id = id {
- if var context = workingMessage.context {
- context[keyPath: "traits.id"] = id
- workingMessage.context = context
- client?.updateContext(context)
- }
- }
- return workingMessage
- }
-}
-
-extension RSAliasIdPlugin: RSEventPlugin {
- func reset() {
- id = nil
- }
-}
-
-extension RSClient {
- internal func setAlias(_ id: String) {
- if let aliasIdPlugin = self.find(pluginType: RSAliasIdPlugin.self) {
- aliasIdPlugin.id = id
- } else {
- let aliasIdPlugin = RSAliasIdPlugin()
- aliasIdPlugin.id = id
- add(plugin: aliasIdPlugin)
- }
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSAnonymousIdPlugin.swift b/Sources/Classes/Client/Plugins/RSAnonymousIdPlugin.swift
deleted file mode 100644
index 51247ae0..00000000
--- a/Sources/Classes/Client/Plugins/RSAnonymousIdPlugin.swift
+++ /dev/null
@@ -1,126 +0,0 @@
-//
-// RSAnonymousIdPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 02/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-// MARK: - iOS, tvOS, Catalyst
-
-#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst)
-import SystemConfiguration
-import UIKit
-#if !os(tvOS)
-import WebKit
-#endif
-#endif
-
-// MARK: - watchOS
-
-#if os(watchOS)
-import WatchKit
-import Network
-#endif
-
-// MARK: - macOS
-
-#if os(macOS)
-import Cocoa
-import WebKit
-#endif
-
-class RSAnonymousIdPlugin: RSPlatformPlugin {
- let type = PluginType.before
- var client: RSClient?
-
- var anonymousId: String?
-
- required init() {
-#if os(iOS) || os(tvOS)
- anonymousId = UIDevice.current.identifierForVendor?.uuidString.lowercased()
-#endif
-#if os(watchOS)
- anonymousId = WKInterfaceDevice.current().identifierForVendor?.uuidString.lowercased()
-#endif
-#if os(macOS)
- anonymousId = macAddress(bsd: "en0")
-#endif
- }
-
- private func macAddress(bsd: String) -> String? {
- let MAC_ADDRESS_LENGTH = 6
- let separator = ":"
-
- var length: size_t = 0
- var buffer: [CChar]
-
- let bsdIndex = Int32(if_nametoindex(bsd))
- if bsdIndex == 0 {
- return nil
- }
- let bsdData = Data(bsd.utf8)
- var managementInfoBase = [CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, bsdIndex]
-
- if sysctl(&managementInfoBase, 6, nil, &length, nil, 0) < 0 {
- return nil
- }
-
- buffer = [CChar](unsafeUninitializedCapacity: length, initializingWith: {buffer, initializedCount in
- for x in 0...stride + 1
- let rangeOfToken = infoData[indexAfterMsghdr...].range(of: bsdData)!
- let lower = rangeOfToken.upperBound
- let upper = lower + MAC_ADDRESS_LENGTH
- let macAddressData = infoData[lower..(message: T?) -> T? {
- guard var workingMessage = message else { return message }
- workingMessage.anonymousId = anonymousId
- if var context = workingMessage.context {
- context[keyPath: "traits.anonymousId"] = anonymousId
- workingMessage.context = context
- client?.updateContext(context)
- }
- return workingMessage
- }
-}
-
-extension RSClient {
- /**
- API for setting unique identifier of every call.
- - Parameters:
- - anonymousId: Unique identifier of every event
- # Example #
- ```
- client.setAnonymousId("sample_anonymous_id")
- ```
- */
- @objc
- public func setAnonymousId(_ anonymousId: String) {
- guard anonymousId.isNotEmpty else {
- log(message: "anonymousId can not be empty", logLevel: .warning)
- return
- }
- if let anonymousIdPlugin = self.find(pluginType: RSAnonymousIdPlugin.self) {
- anonymousIdPlugin.anonymousId = anonymousId
- } else {
- let anonymousIdPlugin = RSAnonymousIdPlugin()
- anonymousIdPlugin.anonymousId = anonymousId
- add(plugin: anonymousIdPlugin)
- }
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSAppTrackingConsentPlugin.swift b/Sources/Classes/Client/Plugins/RSAppTrackingConsentPlugin.swift
deleted file mode 100644
index c94e2712..00000000
--- a/Sources/Classes/Client/Plugins/RSAppTrackingConsentPlugin.swift
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// RSAppTrackingConsentPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 02/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSAppTrackingConsentPlugin: RSPlatformPlugin {
- let type = PluginType.before
- var client: RSClient?
-
- var appTrackingConsent: RSAppTrackingConsent?
-
- required init() { }
-
- func execute(message: T?) -> T? {
- guard var workingMessage = message else { return message }
- if var context = workingMessage.context, let appTrackingConsent = appTrackingConsent {
- context[keyPath: "device.attTrackingStatus"] = appTrackingConsent.rawValue
- workingMessage.context = context
- client?.updateContext(context)
- }
- return workingMessage
- }
-}
-
-extension RSClient {
- /**
- API for app tracking consent management.
- - Parameters:
- - appTrackingConsent: App tracking consent
- # Example #
- ```
- client.setAppTrackingConsent(.authorize)
- ```
- */
- @objc
- public func setAppTrackingConsent(_ appTrackingConsent: RSAppTrackingConsent) {
- if let appTrackingConsentPlugin = self.find(pluginType: RSAppTrackingConsentPlugin.self) {
- appTrackingConsentPlugin.appTrackingConsent = appTrackingConsent
- } else {
- let appTrackingConsentPlugin = RSAppTrackingConsentPlugin()
- appTrackingConsentPlugin.appTrackingConsent = appTrackingConsent
- add(plugin: appTrackingConsentPlugin)
- }
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSContextPlugin.swift b/Sources/Classes/Client/Plugins/RSContextPlugin.swift
index 11f8a2b4..0e6711a4 100644
--- a/Sources/Classes/Client/Plugins/RSContextPlugin.swift
+++ b/Sources/Classes/Client/Plugins/RSContextPlugin.swift
@@ -10,118 +10,88 @@ import Foundation
class RSContextPlugin: RSPlatformPlugin {
let type: PluginType = .before
- var client: RSClient?
-
- var context: MessageContext?
-
- var traits: MessageTraits? {
- if let traits = context?["traits"] as? MessageTraits {
- return traits
+ weak var client: RSClient? {
+ didSet {
+ initialSetup()
}
- return nil
}
private var staticContext = staticContextData()
private static var device = Vendor.current
+ private var userDefaults: RSUserDefaults?
+
+ func initialSetup() {
+ guard let client = self.client else { return }
+ userDefaults = client.userDefaults
+ }
func execute(message: T?) -> T? {
- guard var workingMessage = message else { return message }
+ guard var workingMessage = message else { return message }
var context = staticContext
insertDynamicPlatformContextData(context: &context)
insertDynamicOptionData(message: workingMessage, context: &context)
+ insertDynamicDeviceInfoData(context: &context)
+ insertSessionData(message: workingMessage, context: &context)
+ if let eventContext = workingMessage.context {
+ context.merge(eventContext) { (new, _) in new }
+ }
workingMessage.context = context
- self.context = context
+ RSSessionStorage.shared.write(.context, value: context)
return workingMessage
}
internal static func staticContextData() -> [String: Any] {
var staticContext = [String: Any]()
-
// library name
- staticContext["library"] = [
- "name": "rudder-ios-library",
- "version": RSVersion
- ]
-
+ staticContext["library"] = RSContext.LibraryInfo().dictionary
// app info
- let info = Bundle.main.infoDictionary
- staticContext["app"] = [
- "name": info?["CFBundleDisplayName"] ?? "",
- "version": info?["CFBundleShortVersionString"] ?? "",
- "build": info?["CFBundleVersion"] ?? "",
- "namespace": Bundle.main.bundleIdentifier ?? ""
- ]
+ staticContext["app"] = RSContext.AppInfo().dictionary
insertStaticPlatformContextData(context: &staticContext)
return staticContext
}
internal static func insertStaticPlatformContextData(context: inout [String: Any]) {
// device
- let device = Self.device
-
- let deviceInfo = [
- "manufacturer": device.manufacturer,
- "type": device.type,
- "model": device.model,
- "name": device.name,
- "id": device.identifierForVendor ?? ""
- ]
- context["device"] = deviceInfo
+ context["device"] = RSContext.DeviceInfo().dictionary
// os
- context["os"] = [
- "name": device.systemName,
- "version": device.systemVersion
- ]
+ context["os"] = RSContext.OSInfo().dictionary
// screen
- let screen = device.screenSize
- context["screen"] = [
- "width": screen.width,
- "height": screen.height,
- "density": screen.density
- ]
+ context["screen"] = RSContext.ScreenInfo().dictionary
// locale
- if !Locale.preferredLanguages.isEmpty {
- context["locale"] = Locale.preferredLanguages[0]
- }
+ context["locale"] = RSContext.locale()
// timezone
- context["timezone"] = TimeZone.current.identifier
+ context["timezone"] = RSContext.timezone()
}
internal func insertDynamicPlatformContextData(context: inout [String: Any]) {
- let device = Self.device
-
- // network
- let status = device.connection
-
- var cellular = false
- var wifi = false
- var bluetooth = false
-
- switch status {
- case .online(.cellular):
- cellular = true
- case .online(.wifi):
- wifi = true
- case .online(.bluetooth):
- bluetooth = true
- default:
- break
- }
-
// network connectivity
- context["network"] = [
- "bluetooth": bluetooth,
- "cellular": cellular,
- "wifi": wifi,
- "carrier": device.carrier
- ] as [String: Any]
+ context["network"] = RSContext.NetworkInfo().dictionary
+ }
+
+ internal func insertDynamicDeviceInfoData(context: inout [String: Any]) {
+ if let deviceToken: String = RSSessionStorage.shared.read(.deviceToken) {
+ context[keyPath: "device.token"] = deviceToken
+ }
+ if let advertisingId: String = RSSessionStorage.shared.read(.advertisingId), advertisingId.isNotEmpty {
+ context[keyPath: "device.advertisingId"] = advertisingId
+ context[keyPath: "device.adTrackingEnabled"] = true
+ let appTrackingConsent: RSAppTrackingConsent = RSSessionStorage.shared.read(.appTrackingConsent) ?? .notDetermined
+ context[keyPath: "device.attTrackingStatus"] = appTrackingConsent.rawValue
+ }
}
func insertDynamicOptionData(message: RSMessage, context: inout [String: Any]) {
// First priority will given to the `option` passed along with the event
+ var contextExternalIds = [[String: String]]()
+ // Fetch `externalIds` set using identify API.
+ if let externalIds: [[String: String]] = userDefaults?.read(.externalId) {
+ contextExternalIds.append(contentsOf: externalIds)
+ }
+
if let option = message.option {
- if let externalIds = option.externalIds {
- context["externalId"] = externalIds
+ // We will merge the external ids for other event calls
+ if let externalIds = option.externalIds, message.type != .identify {
+ contextExternalIds.append(contentsOf: externalIds)
}
if let customContexts = option.customContexts {
for (key, value) in customContexts {
@@ -129,14 +99,17 @@ class RSContextPlugin: RSPlatformPlugin {
}
}
}
- // TODO: Fetch `customContexts` set using setOption API.
+ if !contextExternalIds.isEmpty {
+ context["externalId"] = contextExternalIds
+ }
}
-}
-
-extension RSClient {
- func updateContext(_ context: MessageContext?) {
- if let contextPlugin = self.find(pluginType: RSContextPlugin.self) {
- contextPlugin.context = context
+
+ func insertSessionData(message: RSMessage, context: inout [String: Any]) {
+ if let sessionId = message.sessionId {
+ context["sessionId"] = sessionId
+ if let sessionStart = message.sessionStart, sessionStart {
+ context["sessionStart"] = sessionStart
+ }
}
}
}
diff --git a/Sources/Classes/Client/Plugins/RSDeviceTokenPlugin.swift b/Sources/Classes/Client/Plugins/RSDeviceTokenPlugin.swift
deleted file mode 100644
index d2bac152..00000000
--- a/Sources/Classes/Client/Plugins/RSDeviceTokenPlugin.swift
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// RSDeviceTokenPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 24/02/22.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSDeviceTokenPlugin: RSPlatformPlugin {
- let type = PluginType.before
- var client: RSClient?
-
- var token: String?
-
- required init() { }
-
- func execute(message: T?) -> T? {
- guard var workingMessage = message else { return message }
- if var context = workingMessage.context, let token = token {
- context[keyPath: "device.token"] = token
- workingMessage.context = context
- client?.updateContext(context)
- }
- return workingMessage
- }
-}
-
-extension RSClient {
- /**
- API for setting token under context.device.token.
- - Parameters:
- - token: Token of the device
- # Example #
- ```
- client.setDeviceToken("sample_device_token")
- ```
- */
- @objc
- public func setDeviceToken(_ token: String) {
- guard token.isNotEmpty else {
- log(message: "token can not be empty", logLevel: .warning)
- return
- }
- if let tokenPlugin = self.find(pluginType: RSDeviceTokenPlugin.self) {
- tokenPlugin.token = token
- } else {
- let tokenPlugin = RSDeviceTokenPlugin()
- tokenPlugin.token = token
- add(plugin: tokenPlugin)
- }
- }
-}
-
-extension Data {
- var hexString: String {
- let hexString = map { String(format: "%02.2hhx", $0) }.joined()
- return hexString
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSGDPRPlugin.swift b/Sources/Classes/Client/Plugins/RSGDPRPlugin.swift
deleted file mode 100644
index 3cd74372..00000000
--- a/Sources/Classes/Client/Plugins/RSGDPRPlugin.swift
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// RSGDPRPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 03/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSGDPRPlugin: RSPlatformPlugin {
- let type = PluginType.before
- var client: RSClient?
-
- var optOutStatus: Bool?
-
- required init() { }
-
- func execute(message: T?) -> T? {
- if RSUserDefaults.getOptStatus() == true {
- return nil
- } else {
- return message
- }
- }
-}
-
-extension RSClient {
- @objc
- public func setOptOutStatus(_ status: Bool) {
- RSUserDefaults.saveOptStatus(status)
- if let gdprPlugin = self.find(pluginType: RSGDPRPlugin.self) {
- gdprPlugin.optOutStatus = status
- } else {
- let gdprPlugin = RSGDPRPlugin()
- gdprPlugin.optOutStatus = status
- add(plugin: gdprPlugin)
- }
- }
-
- @objc
- public func getOptOutStatus() -> Bool {
- return RSUserDefaults.getOptStatus() ?? false
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSIdentifyTraitsPlugin.swift b/Sources/Classes/Client/Plugins/RSIdentifyTraitsPlugin.swift
deleted file mode 100644
index 1149dec8..00000000
--- a/Sources/Classes/Client/Plugins/RSIdentifyTraitsPlugin.swift
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-// RSIdentifyTraitsPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 31/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSIdentifyTraitsPlugin: RSPlatformPlugin {
- let type = PluginType.before
- var client: RSClient? {
- didSet {
- initialSetup()
- }
- }
-
- var traits: IdentifyTraits?
-
- required init() { }
-
- func initialSetup() {
- if let data: Data = RSUserDefaults.getTraits() {
- do {
- if let dictionary = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [String: Any] {
- traits = dictionary
- }
- } catch {
- self.client?.log(message: "Failed to decode traits: \(error)", logLevel: .error)
- }
- }
- }
-
- func execute(message: T?) -> T? {
- guard var workingMessage = message else { return message }
- if let traits = traits {
- if var context = workingMessage.context {
- context["traits"] = traits
- workingMessage.context = context
- client?.updateContext(context)
- }
- }
- return workingMessage
- }
-}
-
-extension RSIdentifyTraitsPlugin: RSEventPlugin {
- func reset() {
- traits = nil
- RSUserDefaults.saveTraits(nil)
- }
-
- func saveTraits(_ traits: [String: Any]?) {
- guard let traits = traits else {
- RSUserDefaults.saveTraits(nil)
- return
- }
- do {
- let data: Data = try NSKeyedArchiver.archivedData(withRootObject: traits, requiringSecureCoding: false)
- RSUserDefaults.saveTraits(data)
- } catch {
- self.client?.log(message: "Failed to encode traits: \(error)", logLevel: .error)
- }
- }
-}
-
-extension RSClient {
- internal func setTraits(_ traits: IdentifyTraits?, _ newUserId: String) {
- if let traitsPlugin = self.find(pluginType: RSIdentifyTraitsPlugin.self) {
- var updatedTraits = traits
- if let exisitingUserId = RSUserDefaults.getUserId(), exisitingUserId == newUserId {
- guard let newTraits = traits else { return }
- if var existingTraits = traitsPlugin.traits {
- existingTraits.merge(newTraits) { (_, new) in new }
- updatedTraits = existingTraits
- }
- }
- traitsPlugin.traits = updatedTraits
- traitsPlugin.saveTraits(updatedTraits)
- } else {
- let traitsPlugin = RSIdentifyTraitsPlugin()
- traitsPlugin.traits = traits
- traitsPlugin.saveTraits(traits)
- add(plugin: traitsPlugin)
- }
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSIntegrationPlugin.swift b/Sources/Classes/Client/Plugins/RSIntegrationPlugin.swift
index eddb411a..65a81274 100644
--- a/Sources/Classes/Client/Plugins/RSIntegrationPlugin.swift
+++ b/Sources/Classes/Client/Plugins/RSIntegrationPlugin.swift
@@ -10,7 +10,7 @@ import Foundation
class RSIntegrationPlugin: RSPlatformPlugin {
let type: PluginType = .before
- var client: RSClient?
+ weak var client: RSClient?
func execute(message: T?) -> T? {
guard var workingMessage = message else { return message }
@@ -19,8 +19,8 @@ class RSIntegrationPlugin: RSPlatformPlugin {
if messageIntegrations["All"] == nil {
workingMessage.integrations?["All"] = true
}
- } else if let optionPlugin = client?.find(pluginType: RSOptionPlugin.self) {
- if let integrations = optionPlugin.option?.integrations {
+ } else if let globalOption: RSOption = RSSessionStorage.shared.read(.option) {
+ if let integrations = globalOption.integrations {
workingMessage.integrations = integrations
if integrations["All"] == nil {
workingMessage.integrations?["All"] = true
diff --git a/Sources/Classes/Client/Plugins/RSLoggerPlugin.swift b/Sources/Classes/Client/Plugins/RSLoggerPlugin.swift
deleted file mode 100644
index a0dfda2f..00000000
--- a/Sources/Classes/Client/Plugins/RSLoggerPlugin.swift
+++ /dev/null
@@ -1,155 +0,0 @@
-//
-// RSLoggerPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 24/02/22.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-// MARK: - Plugin Implementation
-
-class RSLoggerPlugin: RSUtilityPlugin {
- var logLevel = RSLogLevel.debug
-
- var client: RSClient? {
- didSet {
- addTargets()
- }
- }
-
- let type = PluginType.utility
-
- fileprivate var loggingMediator = [RSLoggingType: RSLogger]()
-
- // Default to no, enable to see local logs
- static var loggingEnabled = false
-
- // For use only. Note: This will contain the last created instance
- // of analytics when used in a multi-analytics environment.
- static var sharedAnalytics: RSClient?
-
- #if DEBUG
- static var globalLogger: RSLoggerPlugin {
- let logger = RSLoggerPlugin()
- logger.addTargets()
- return logger
- }
- #endif
-
- required init() { }
-
- func configure(client: RSClient) {
- self.client = client
- RSLoggerPlugin.sharedAnalytics = client
- addTargets()
- }
-
- func addTargets() {
- try? add(target: RSConsoleLogger(), for: RSLoggingType.log)
- }
-
- func loggingEnabled(_ enabled: Bool) {
- RSLoggerPlugin.loggingEnabled = enabled
- }
-
- func log(_ logMessage: RSLogMessage, destination: RSLoggingType.LogDestination) {
- if client?.config?.logLevel == .verbose || logMessage.logLevel == client?.config?.logLevel {
- for (logType, target) in loggingMediator where logType.contains(destination) {
- target.parseLog(logMessage)
- }
- }
- }
-
- func add(target: RSLogger, for loggingType: RSLoggingType) throws {
-
- // Verify the target does not exist, if it does bail out
- let filtered = loggingMediator.filter { (type: RSLoggingType, existingTarget: RSLogger) in
- Swift.type(of: existingTarget) == Swift.type(of: target)
- }
- if filtered.isEmpty == false { throw NSError(domain: "Target already exists", code: 2002, userInfo: nil) }
-
- // Finally add the target
- loggingMediator[loggingType] = target
- }
-}
-
-// MARK: - Types
-
-struct LogFactory {
- static func buildLog(destination: RSLoggingType.LogDestination,
- title: String,
- message: String,
- logLevel: RSLogLevel = .debug,
- function: String? = nil,
- line: Int? = nil,
- event: RSMessage? = nil,
- sender: Any? = nil,
- value: Double? = nil,
- tags: [String]? = nil) -> RSLogMessage {
-
- switch destination {
- case .log:
- return GenericLog(logLevel: logLevel, message: message, function: function, line: line)
- case .metric:
- return MetricLog(title: title, message: message, value: value ?? 1, event: event, function: function, line: line)
- }
- }
-
- fileprivate struct GenericLog: RSLogMessage {
- var logLevel: RSLogLevel
- var title: String?
- var message: String
- var event: RSMessage?
- var function: String?
- var line: Int?
- var logType: RSLoggingType.LogDestination = .log
- var dateTime = Date()
- }
-
- fileprivate struct MetricLog: RSLogMessage {
- var title: String?
- var logLevel: RSLogLevel = .debug
- var message: String
- var value: Double
- var event: RSMessage?
- var function: String?
- var line: Int?
- var logType: RSLoggingType.LogDestination = .metric
- var dateTime = Date()
- }
-}
-
-extension RSClient {
- static func rsLog(message: String, logLevel: RSLogLevel? = nil, function: String = #function, line: Int = #line) {
- if let shared = RSLoggerPlugin.sharedAnalytics {
- shared.apply { plugin in
- if let loggerPlugin = plugin as? RSLoggerPlugin {
- var filterKind = loggerPlugin.logLevel
- if let logKind = logLevel {
- filterKind = logKind
- }
-
- let log = LogFactory.buildLog(destination: .log, title: "", message: message, logLevel: filterKind, function: function, line: line)
- loggerPlugin.log(log, destination: .log)
- }
- }
- } else {
- #if DEBUG
- let log = LogFactory.buildLog(destination: .log, title: "", message: message, logLevel: .debug, function: function, line: line)
- RSLoggerPlugin.globalLogger.log(log, destination: .log)
- #endif
- }
- }
-
- static func rsMetric(_ type: RSMetricType, name: String, value: Double, tags: [String]? = nil) {
- RSLoggerPlugin.sharedAnalytics?.apply { plugin in
-
- if let loggerPlugin = plugin as? RSLoggerPlugin {
- let log = LogFactory.buildLog(destination: .metric, title: type.toString(), message: name, value: value, tags: tags)
- loggerPlugin.log(log, destination: .metric)
- }
- }
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSOptionPlugin.swift b/Sources/Classes/Client/Plugins/RSOptionPlugin.swift
deleted file mode 100644
index fb418cd8..00000000
--- a/Sources/Classes/Client/Plugins/RSOptionPlugin.swift
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// RSOptionPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 02/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSOptionPlugin: RSPlatformPlugin {
- let type: PluginType = .before
- var client: RSClient?
-
- var option: RSOption?
-
- required init() { }
-}
-
-extension RSClient {
- /**
- API for setting enable/disable sending the events across all the event calls made using the SDK to the specified destinations.
- - Parameters:
- - option: Options related to every API call
- # Example #
- ```
- let defaultOption = RSOption()
- defaultOption.putIntegration("Amplitude", isEnabled: true)
-
- client.setOption(defaultOption)
- ```
- */
- @objc
- public func setOption(_ option: RSOption) {
- if let optionPlugin = self.find(pluginType: RSOptionPlugin.self) {
- optionPlugin.option = option
- } else {
- let optionPlugin = RSOptionPlugin()
- optionPlugin.option = option
- add(plugin: optionPlugin)
- }
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSReplayQueuePlugin.swift b/Sources/Classes/Client/Plugins/RSReplayQueuePlugin.swift
index 132dd407..8aadbfa3 100644
--- a/Sources/Classes/Client/Plugins/RSReplayQueuePlugin.swift
+++ b/Sources/Classes/Client/Plugins/RSReplayQueuePlugin.swift
@@ -9,46 +9,66 @@
import Foundation
internal class RSReplayQueuePlugin: RSPlugin {
- static let maxSize = 1000
-
- @RSAtomic var running: Bool = true
-
let type: PluginType = .before
+ weak var client: RSClient?
- var client: RSClient?
-
- let syncQueue = DispatchQueue(label: "replayQueue.rudder.com")
- var queuedEvents = [RSMessage]()
+ private let syncQueue = DispatchQueue(label: "replayQueue.rudder.com")
+ private var queuedEvents = [RSMessage]()
+ @RSAtomic var running = true
+ static let maxSize = 1000
required init() { }
func execute(message: T?) -> T? {
- if running == true, let e = message {
- syncQueue.sync {
- if queuedEvents.count >= Self.maxSize {
- queuedEvents.removeFirst()
+ if running, let e = message {
+ syncQueue.async { [weak self] in
+ guard let self = self else { return }
+ if self.queuedEvents.count >= Self.maxSize {
+ self.queuedEvents.removeFirst()
}
- queuedEvents.append(e)
+ self.queuedEvents.append(e)
}
- return nil
}
return message
}
func update(serverConfig: RSServerConfig, type: UpdateType) {
- guard client?.checkServerConfigInProgress == true else { return }
- running = false
- replayEvents()
+ if type == .refresh {
+ replayEvents(isSourceEnabled: serverConfig.enabled)
+ } else if type == .initial, serverConfig.enabled {
+ // if source config is cached and source is enabled. we no longer need to add the events to queue.
+ running = false
+ }
}
}
extension RSReplayQueuePlugin {
- internal func replayEvents() {
- syncQueue.sync {
- for event in queuedEvents {
- client?.process(message: event)
+ internal func replayEvents(isSourceEnabled: Bool) {
+ syncQueue.async { [weak self] in
+ guard let self = self else { return }
+ // send events to device mode destinations only.
+ // we will wait for 2 seconds to finish the destinations to be initialized.
+ DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval(2)) { [weak self] in
+ guard let self = self else { return }
+ self.running = false
+ if isSourceEnabled {
+ if let destinationPlugins = self.getExternalDestinationPlugins() {
+ for event in self.queuedEvents {
+ destinationPlugins.forEach { plugin in
+ _ = plugin.execute(message: event)
+ }
+ }
+ }
+ }
+ self.queuedEvents.removeAll()
}
- queuedEvents.removeAll()
+
}
}
+
+ private func getExternalDestinationPlugins() -> [RSDestinationPlugin]? {
+ return (self.client?.controller.plugins[.destination]?.plugins as? [RSDestinationPlugin])?.filter({ plugin in
+ return plugin.key != RUDDER_DESTINATION_KEY
+ })
+ }
}
diff --git a/Sources/Classes/Client/Plugins/RSSessionStoragePlugin.swift b/Sources/Classes/Client/Plugins/RSSessionStoragePlugin.swift
new file mode 100644
index 00000000..5884529b
--- /dev/null
+++ b/Sources/Classes/Client/Plugins/RSSessionStoragePlugin.swift
@@ -0,0 +1,43 @@
+//
+// RSSessionStoragePlugin.swift
+// Rudder
+//
+// Created by Pallab Maiti on 07/12/23.
+// Copyright © 2023 Rudder Labs India Pvt Ltd. All rights reserved.
+//
+
+import Foundation
+
+// This class has no use at the moment. But will be needed when multiple instance will come in place. We will remove RSSessionStorage
+class RSSessionStoragePlugin: RSPlatformPlugin {
+ let type: PluginType = .before
+ var client: RSClient?
+
+ private var deviceToken: String?
+ private var advertisingId: String?
+ private var appTrackingConsent: RSAppTrackingConsent?
+ private var option: RSOption?
+
+ func execute(message: T?) -> T? {
+ guard var workingMessage = message else { return message }
+ if let messageIntegrations = workingMessage.option?.integrations {
+ workingMessage.integrations = messageIntegrations
+ if messageIntegrations["All"] == nil {
+ workingMessage.integrations?["All"] = true
+ }
+ } else if let globalOption = option {
+ if let integrations = globalOption.integrations {
+ workingMessage.integrations = integrations
+ if integrations["All"] == nil {
+ workingMessage.integrations?["All"] = true
+ }
+ } else {
+ workingMessage.integrations = ["All": true]
+ }
+ } else {
+ workingMessage.integrations = ["All": true]
+ }
+ return message
+ }
+
+}
diff --git a/Sources/Classes/Client/Plugins/RSUserIdPlugin.swift b/Sources/Classes/Client/Plugins/RSUserIdPlugin.swift
deleted file mode 100644
index 11ce8301..00000000
--- a/Sources/Classes/Client/Plugins/RSUserIdPlugin.swift
+++ /dev/null
@@ -1,71 +0,0 @@
-//
-// RSUserIdPlugin.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 01/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSUserIdPlugin: RSPlatformPlugin {
- let type = PluginType.before
- var client: RSClient? {
- didSet {
- initialSetup()
- }
- }
-
- var userId: String?
-
- required init() { }
-
- func initialSetup() {
- userId = RSUserDefaults.getUserId()
- }
-
- func execute(message: T?) -> T? {
- guard var workingMessage = message else { return message }
- if let userId = userId {
- workingMessage.userId = userId
- if var context = workingMessage.context {
- context[keyPath: "traits.userId"] = userId
- workingMessage.context = context
- client?.updateContext(context)
- }
- }
- return workingMessage
- }
-}
-
-extension RSUserIdPlugin: RSEventPlugin {
- func reset() {
- userId = nil
- RSUserDefaults.saveUserId(nil)
- }
-}
-
-extension RSClient {
- internal func setUserId(_ userId: String) {
- if let userIdPlugin = self.find(pluginType: RSUserIdPlugin.self) {
- userIdPlugin.userId = userId
- RSUserDefaults.saveUserId(userId)
- } else {
- let userIdPlugin = RSUserIdPlugin()
- userIdPlugin.userId = userId
- RSUserDefaults.saveUserId(userId)
- add(plugin: userIdPlugin)
- }
- }
-}
-
-extension AliasMessage {
- internal func applyAlias(newId: String, client: RSClient) -> Self {
- var result: Self = self
- result.userId = newId
- if let userIdPlugin = client.find(pluginType: RSUserIdPlugin.self), let previousId = userIdPlugin.userId {
- result.previousId = previousId
- }
- return result
- }
-}
diff --git a/Sources/Classes/Client/Plugins/RSUserSessionPlugin.swift b/Sources/Classes/Client/Plugins/RSUserSessionPlugin.swift
index 9ea2158f..c1f219d7 100644
--- a/Sources/Classes/Client/Plugins/RSUserSessionPlugin.swift
+++ b/Sources/Classes/Client/Plugins/RSUserSessionPlugin.swift
@@ -15,25 +15,39 @@ class RSUserSessionPlugin: RSPlatformPlugin, RSEventPlugin {
}
}
+ private var userDefaults: RSUserDefaults?
private var sessionTimeOut: Int?
- private var isNewSessionStarted: Bool = false
+ private var isNewSessionStarted = false
- private var sessionId: Int?
- private var lastEventTimeStamp: Int?
+ var sessionId: Int? {
+ userDefaults?.read(.sessionId)
+ }
+
+ private var lastEventTimeStamp: Int? {
+ userDefaults?.read(.lastEventTimeStamp)
+ }
- private var isAutomaticSessionTrackingStatus = false
- private var isSessionStoppedStatus = false
- private var isManualSessionTrackingStatus = false
+ private var automaticSessionTrackingStatus: Bool {
+ userDefaults?.read(.automaticSessionTrackingStatus) ?? false
+ }
+
+ private var sessionStoppedStatus: Bool {
+ userDefaults?.read(.sessionStoppedStatus) ?? false
+ }
+
+ private var manualSessionTrackingStatus: Bool {
+ userDefaults?.read(.manualSessionTrackingStatus) ?? false
+ }
private var isSessionTrackingAllowed: Bool {
- if !isSessionStoppedStatus && (isManualSessionTrackingStatus || isAutomaticSessionTrackingAllowed) {
+ if !sessionStoppedStatus && (manualSessionTrackingStatus || isAutomaticSessionTrackingAllowed) {
return true
}
return false
}
private var isAutomaticSessionTrackingAllowed: Bool {
- guard let clientConfig = client?.config, clientConfig.trackLifecycleEvents, clientConfig.automaticSessionTracking else {
+ guard let config = client?.config, config.trackLifecycleEvents, config.automaticSessionTracking else {
return false
}
return true
@@ -42,40 +56,34 @@ class RSUserSessionPlugin: RSPlatformPlugin, RSEventPlugin {
required init() {}
func initialSetup() {
- self.sessionTimeOut = client?.config?.sessionTimeout
- self.sessionId = RSUserDefaults.getSessionId()
- self.lastEventTimeStamp = RSUserDefaults.getLastEventTimeStamp()
+ guard let client = self.client else { return }
+ sessionTimeOut = client.config?.sessionTimeout
+ userDefaults = client.userDefaults
if isAutomaticSessionTrackingAllowed {
- if let previousAutomaticSessionTrackingStatus = RSUserDefaults.getAutomaticSessionTrackingStatus(),
- (isSessionExpired() || !previousAutomaticSessionTrackingStatus) {
- startNewSession(nil)
- RSUserDefaults.saveAutomaticSessionTrackingStatus(true)
- RSUserDefaults.saveManualSessionTrackingStatus(false)
- RSUserDefaults.saveSessionStoppedStatus(false)
+ if isSessionExpired() || !automaticSessionTrackingStatus {
+ startNewSession()
+ userDefaults?.write(.automaticSessionTrackingStatus, value: true)
+ userDefaults?.write(.manualSessionTrackingStatus, value: false)
+ userDefaults?.write(.sessionStoppedStatus, value: false)
}
} else {
- RSUserDefaults.saveAutomaticSessionTrackingStatus(false)
+ userDefaults?.write(.automaticSessionTrackingStatus, value: false)
}
- refreshSesionParams()
}
func execute(message: T?) -> T? {
guard var workingMessage = message else { return message }
if isSessionTrackingAllowed {
- if var context = workingMessage.context,
- let sessionId = self.sessionId {
- context[keyPath: "sessionId"] = sessionId
+ if let sessionId = self.sessionId {
+ workingMessage.sessionId = sessionId
if isNewSessionStarted {
- context[keyPath: "sessionStart"] = true
+ workingMessage.sessionStart = true
isNewSessionStarted = false
}
- workingMessage.context = context
- client?.updateContext(context)
}
let currentEventTimeStamp = RSUtils.getTimeStamp()
- RSUserDefaults.saveLastEventTimeStamp(currentEventTimeStamp)
- self.lastEventTimeStamp = currentEventTimeStamp
+ userDefaults?.write(.lastEventTimeStamp, value: currentEventTimeStamp)
}
return workingMessage
}
@@ -90,53 +98,42 @@ class RSUserSessionPlugin: RSPlatformPlugin, RSEventPlugin {
return timeDifference >= Double(sessionTimeOut / 1000)
}
- func startNewSession(_ newSessionId: Int?) {
- var sessionId: Int = newSessionId ?? RSUtils.getTimeStamp()
- client?.log(message: "New session is started", logLevel: .verbose)
+ func startNewSession(_ sessionId: Int? = nil) {
isNewSessionStarted = true
- RSUserDefaults.saveSessionId(sessionId)
- self.sessionId = sessionId
- }
-
- private func refreshSesionParams() {
- self.isAutomaticSessionTrackingStatus = RSUserDefaults.getAutomaticSessionTrackingStatus() ?? false
- self.isManualSessionTrackingStatus = RSUserDefaults.getManualSessionTrackingStatus() ?? false
- self.isSessionStoppedStatus = RSUserDefaults.getSessionStoppedStatus() ?? false
- self.lastEventTimeStamp = RSUserDefaults.getLastEventTimeStamp()
+ userDefaults?.write(.sessionId, value: sessionId ?? RSUtils.getTimeStamp())
+ Logger.log(message: "New session is started", logLevel: .verbose)
}
}
extension RSUserSessionPlugin {
- func startManualSession(_ sessionId: Int?) {
- RSUserDefaults.saveAutomaticSessionTrackingStatus(false)
- RSUserDefaults.saveManualSessionTrackingStatus(true)
- RSUserDefaults.saveSessionStoppedStatus(false)
- RSUserDefaults.saveLastEventTimeStamp(nil)
-
- refreshSesionParams()
+ func startManualSession(_ sessionId: Int? = nil) {
+ userDefaults?.write(.automaticSessionTrackingStatus, value: false)
+ userDefaults?.write(.manualSessionTrackingStatus, value: true)
+ userDefaults?.write(.sessionStoppedStatus, value: false)
+ userDefaults?.remove(.lastEventTimeStamp)
startNewSession(sessionId)
}
func endSession() {
- RSUserDefaults.saveAutomaticSessionTrackingStatus(false)
- RSUserDefaults.saveManualSessionTrackingStatus(false)
- RSUserDefaults.saveSessionStoppedStatus(true)
- RSUserDefaults.saveLastEventTimeStamp(nil)
-
- refreshSesionParams()
+ userDefaults?.write(.automaticSessionTrackingStatus, value: false)
+ userDefaults?.write(.manualSessionTrackingStatus, value: false)
+ userDefaults?.write(.sessionStoppedStatus, value: true)
+ userDefaults?.remove(.lastEventTimeStamp)
}
func reset() {
if isSessionTrackingAllowed {
- RSUserDefaults.saveLastEventTimeStamp(nil)
- startNewSession(nil)
+ if automaticSessionTrackingStatus {
+ userDefaults?.write(.lastEventTimeStamp, value: RSUtils.getTimeStamp())
+ }
+ startNewSession()
}
}
func refreshSessionIfNeeded() {
- if isSessionTrackingAllowed, isAutomaticSessionTrackingStatus, isSessionExpired() {
- startNewSession(nil)
+ if isSessionTrackingAllowed, automaticSessionTrackingStatus, isSessionExpired() {
+ startNewSession()
}
}
}
@@ -153,22 +150,22 @@ extension RSClient {
@objc
public func startSession() {
if let userSessionPlugin = self.find(pluginType: RSUserSessionPlugin.self) {
- userSessionPlugin.startManualSession(nil)
+ userSessionPlugin.startManualSession()
} else {
- log(message: "SDK is not yet initialised. Hence manual session cannot be started", logLevel: .debug)
+ Logger.log(message: "SDK is not yet initialised. Hence manual session cannot be started", logLevel: .debug)
}
}
@objc
public func startSession(_ sessionId: Int) {
guard String(sessionId).count >= 10 else {
- log(message: "RSClient: startSession: Length of the sessionId should be at least 10: \(sessionId)", logLevel: .error)
+ Logger.log(message: "RSClient: startSession: Length of the sessionId should be at least 10: \(sessionId)", logLevel: .error)
return
}
if let userSessionPlugin = self.find(pluginType: RSUserSessionPlugin.self) {
userSessionPlugin.startManualSession(sessionId)
} else {
- log(message: "SDK is not yet initialised. Hence manual session cannot be started", logLevel: .debug)
+ Logger.log(message: "SDK is not yet initialised. Hence manual session cannot be started", logLevel: .debug)
}
}
diff --git a/Sources/Classes/Client/Plugins/RudderDestinationPlugin.swift b/Sources/Classes/Client/Plugins/RudderDestinationPlugin.swift
index 47bcf879..483d34c4 100644
--- a/Sources/Classes/Client/Plugins/RudderDestinationPlugin.swift
+++ b/Sources/Classes/Client/Plugins/RudderDestinationPlugin.swift
@@ -10,9 +10,9 @@ import Foundation
class RudderDestinationPlugin: RSDestinationPlugin {
let type = PluginType.destination
- let key: String = "RudderStack"
+ let key: String = RUDDER_DESTINATION_KEY
let controller = RSController()
- var client: RSClient? {
+ weak var client: RSClient? {
didSet {
initialSetup()
}
@@ -23,28 +23,106 @@ class RudderDestinationPlugin: RSDestinationPlugin {
private var databaseManager: RSDatabaseManager?
private var serviceManager: RSServiceManager?
+ private var config: RSConfig?
+ private var userDefaults: RSUserDefaults?
+
+ @RSAtomic var isSourceEnabled = false
+ @RSAtomic var isFlushingStarted = false
private let lock = NSLock()
func initialSetup() {
- guard let client = self.client, let config = client.config else { return }
+ guard let client = self.client else { return }
+ config = client.config
+ userDefaults = client.userDefaults
databaseManager = RSDatabaseManager(client: client)
- serviceManager = RSServiceManager(client: client)
- flushTimer = RSRepeatingTimer(interval: TimeInterval(config.sleepTimeOut)) { [weak self] in
- guard let self = self else { return }
- self.periodicFlush()
+ if isUnitTesting {
+ let configuration = URLSessionConfiguration.default
+ configuration.protocolClasses = [MockURLProtocol.self]
+ let urlSession = URLSession.init(configuration: configuration)
+ serviceManager = RSServiceManager(urlSession: urlSession, client: client)
+
+ let data = """
+ {
+
+ }
+ """.data(using: .utf8)
+
+ MockURLProtocol.requestHandler = { _ in
+ let response = HTTPURLResponse(url: URL(string: "https://some.rudderstack.com.url")!, statusCode: 500, httpVersion: nil, headerFields: nil)!
+ return (response, data)
+ }
+ } else {
+ serviceManager = RSServiceManager(client: client)
}
}
func execute(message: T?) -> T? {
let result: T? = message
if let r = result {
- let modified = configureCloudDestinations(message: r)
- queueEvent(message: modified)
+ saveEvent(message: r)
}
return result
}
+ func update(serverConfig: RSServerConfig, type: UpdateType) {
+ if type == .refresh {
+ if isSourceEnabled, !serverConfig.enabled {
+ // if source was enabled before, but it has been disabled now; then cancel flushing
+ Logger.logDebug("Source has been disabled in your dashboard. Flushing canceled.")
+ flushTimer?.cancel()
+ } else if !isSourceEnabled {
+ if serverConfig.enabled {
+ // if source was disabled before, but it has been enabled now; then resume flushing
+ Logger.logDebug("Source has been enabled in your dashboard. Flushing resumed.")
+ flushTimer?.resume()
+ } else {
+ // if source was disabled before, still it has been disabled now; then cancel flushing
+ Logger.logDebug("Source is still disabled in your dashboard. Flushing canceled.")
+ flushTimer?.cancel()
+ }
+ }
+ }
+ isSourceEnabled = serverConfig.enabled
+ startFlushing()
+ }
+
+ func startFlushing() {
+ guard !isFlushingStarted else {
+ return
+ }
+ isFlushingStarted = true
+ Logger.logDebug("Flushing started.")
+ var sleepCount = 0
+ flushTimer = RSRepeatingTimer(interval: TimeInterval(1)) { [weak self] in
+ guard let self = self else { return }
+ self.uploadsQueue.async {
+ guard self.isSourceEnabled else {
+ // if source is disabled; then suspend flushing
+ Logger.logDebug("Source is disabled in your dashboard. Flushing suspended.")
+ self.flushTimer?.suspend()
+ return
+ }
+ guard let recordCount = self.databaseManager?.getDBRecordCount(), let config = self.config else {
+ return
+ }
+ if recordCount >= config.dbCountThreshold || sleepCount >= config.sleepTimeOut {
+ if recordCount > 0 {
+ self.flushTimer?.suspend()
+ self.flush(sleepCount: 0) { _ in
+ sleepCount = 0
+ self.flushTimer?.resume()
+ }
+ } else {
+ sleepCount = 0
+ }
+ } else {
+ sleepCount += 1
+ }
+ }
+ }
+ }
+
internal func enterForeground() {
flushTimer?.resume()
}
@@ -58,137 +136,143 @@ class RudderDestinationPlugin: RSDestinationPlugin {
enterBackground()
}
- private func queueEvent(message: T) {
+ private func saveEvent(message: T) {
guard let databaseManager = self.databaseManager else { return }
databaseManager.write(message)
}
}
extension RudderDestinationPlugin {
- internal func configureCloudDestinations(message: T) -> T {
- guard let serverConfig = client?.serverConfig else { return message }
- guard let plugins = client?.controller.plugins[.destination]?.plugins as? [RSDestinationPlugin] else { return message }
- guard let customerValues = message.integrations else { return message }
-
- var merged = [String: Bool]()
-
- for plugin in plugins {
- var hasSettings = false
- if let destinations = serverConfig.destinations {
- if let destination = destinations.first(where: { $0.destinationDefinition?.displayName == plugin.key }), destination.enabled {
- hasSettings = true
- }
- }
- if hasSettings {
- merged[plugin.key] = false
+
+ func flush() {
+ DispatchQueue.global(qos: .userInitiated).async { [weak self] in
+ guard let self = self, let databaseManager = self.databaseManager, let config = self.config else {
+ return
}
+ let totalBatchCount = RSUtils.getNumberOfBatch(from: databaseManager.getDBRecordCount(), and: config.flushQueueSize)
+ self.flushBatch(index: 0, totalBatchCount: totalBatchCount)
}
-
- for (key, value) in customerValues {
- merged[key] = value
- }
-
- var modified = message
- modified.integrations = merged
-
- return modified
}
-}
-
-extension RudderDestinationPlugin {
- func flush() {
- DispatchQueue.global(qos: .userInitiated).async { [weak self] in
- guard let self = self, let databaseManager = self.databaseManager, let config = self.client?.config else {
+ private func flushBatch(index: Int, totalBatchCount: Int) {
+ guard index < totalBatchCount else {
+ Logger.logDebug("All batches have been flushed successfully")
+ return
+ }
+ Logger.log(message: "Flushing batch \(index + 1)/\(totalBatchCount)", logLevel: .debug)
+ flush(retryCount: 0) { [weak self] result in
+ guard let self = self else {
return
}
- let uploadGroup = DispatchGroup()
- let numberOfBatch = RSUtils.getNumberOfBatch(from: databaseManager.getDBRecordCount(), and: config.flushQueueSize)
- for i in 0..) {
+ let maxRetryCount = 3
+
+ guard retryCount < maxRetryCount else {
+ completion(.failure(NSError(code: .SERVER_ERROR)))
+ return
+ }
+
+ flushEventsToServer { result in
+ self.lock.unlock()
+ switch result {
+ case .success:
+ completion(.success(true))
+ case .failure(let error):
+ if error.code == RSErrorCode.WRONG_WRITE_KEY.rawValue {
+ Logger.log(message: "Wrong write key", logLevel: .error)
+ completion(.failure(error))
+ } else {
+ Logger.log(message: "Failed to flush batch \(index + 1)/\(totalBatchCount), \(3 - retryCount) retries left", logLevel: .debug)
+ DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval(retryCount)) {
+ flush(retryCount: retryCount + 1, completion: completion)
+ }
+ }
}
- uploadGroup.leave()
}
- uploadGroup.wait()
}
}
- func periodicFlush() {
- uploadsQueue.async { [weak self] in
- guard let self = self else { return }
- self.prepareEventsToFlush()
+ private func flush(sleepCount: Int, completion: @escaping Handler) {
+ flushEventsToServer { result in
+ self.lock.unlock()
+ switch result {
+ case .success:
+ completion(.success(true))
+ case .failure(let error):
+ let errorCode = RSErrorCode(rawValue: error.code)
+ switch errorCode {
+ case .SERVER_ERROR:
+ DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval(sleepCount + 1)) {
+ self.flush(sleepCount: sleepCount + 1, completion: completion)
+ }
+ default:
+ Logger.logError("Aborting flush. Error code: \((errorCode ?? RSErrorCode.UNKNOWN).rawValue)")
+ completion(.failure(NSError(code: .UNKNOWN)))
+ }
+ }
}
}
-
- @discardableResult
- func prepareEventsToFlush() -> RSErrorCode? {
+
+ private func flushEventsToServer(_ completion: Handler? = nil) {
lock.lock()
- guard let databaseManager = databaseManager, let config = client?.config else {
- return .UNKNOWN
+ guard let databaseManager = databaseManager, let config = config else {
+ completion?(.failure(NSError(code: .UNKNOWN)))
+ return
}
- var errorCode: RSErrorCode?
let recordCount = databaseManager.getDBRecordCount()
- client?.log(message: "DBRecordCount \(recordCount)", logLevel: .debug)
+ Logger.log(message: "DBRecordCount \(recordCount)", logLevel: .debug)
if recordCount > config.dbCountThreshold {
- client?.log(message: "Old DBRecordCount \(recordCount - config.dbCountThreshold)", logLevel: .debug)
+ Logger.log(message: "Old DBRecordCount \(recordCount - config.dbCountThreshold)", logLevel: .debug)
let dbMessage = databaseManager.getEvents(recordCount - config.dbCountThreshold)
if let messageIds = dbMessage?.messageIds {
databaseManager.removeEvents(messageIds)
}
}
- client?.log(message: "Fetching events to flush to sever", logLevel: .debug)
+ Logger.log(message: "Fetching events to flush to sever", logLevel: .debug)
guard let dbMessage = databaseManager.getEvents(config.flushQueueSize) else {
- return .UNKNOWN
+ completion?(.failure(NSError(code: .UNKNOWN)))
+ return
}
- if dbMessage.messages.isEmpty == false {
+ if !dbMessage.messages.isEmpty {
let params = RSUtils.getJSON(from: dbMessage)
- client?.log(message: "Payload: \(params)", logLevel: .debug)
- client?.log(message: "EventCount: \(dbMessage.messages.count)", logLevel: .debug)
+ Logger.log(message: "Payload: \(params)", logLevel: .debug)
+ Logger.log(message: "EventCount: \(dbMessage.messages.count)", logLevel: .debug)
if !params.isEmpty {
- errorCode = self.flushEventsToServer(params: params)
- if errorCode == nil {
- client?.log(message: "clearing events from DB", logLevel: .debug)
- databaseManager.removeEvents(dbMessage.messageIds)
- } else if errorCode == .WRONG_WRITE_KEY {
- client?.log(message: "Wrong WriteKey. Aborting.", logLevel: .error)
- } else if errorCode == .SERVER_ERROR {
- client?.log(message: "Server error. Aborting.", logLevel: .error)
- }
+ serviceManager?.flushEvents(params: params, { result in
+ switch result {
+ case .success:
+ Logger.log(message: "clearing events from DB", logLevel: .debug)
+ databaseManager.removeEvents(dbMessage.messageIds)
+ completion?(.success(true))
+ case .failure(let error):
+ completion?(.failure(error))
+ }
+ })
+ } else {
+ completion?(.failure(NSError(code: .UNKNOWN)))
}
+ } else {
+ completion?(.failure(NSError(code: .UNKNOWN)))
}
- lock.unlock()
- return errorCode
}
- func flushEventsToServer(params: String) -> RSErrorCode? {
- var errorCode: RSErrorCode?
- let semaphore = DispatchSemaphore(value: 0)
- serviceManager?.flushEvents(params: params) { result in
- switch result {
- case .success:
- errorCode = nil
- case .failure(let error):
- errorCode = RSErrorCode(rawValue: error.code)
+ private func periodicFlush() {
+ uploadsQueue.async { [weak self] in
+ guard let self = self else { return }
+ self.flushEventsToServer { _ in
+ self.lock.unlock()
}
- semaphore.signal()
}
- semaphore.wait()
- return errorCode
}
}
diff --git a/Sources/Classes/Client/RSClient+Plugins.swift b/Sources/Classes/Client/RSClient+Plugins.swift
index 196583f3..c93149cd 100644
--- a/Sources/Classes/Client/RSClient+Plugins.swift
+++ b/Sources/Classes/Client/RSClient+Plugins.swift
@@ -12,14 +12,9 @@ extension RSClient {
internal func addPlugins() {
add(plugin: RSReplayQueuePlugin())
-
- let logPlugin = RSLoggerPlugin()
- logPlugin.loggingEnabled(config?.logLevel != RSLogLevel.none)
- add(plugin: logPlugin)
-
add(plugin: RSIntegrationPlugin())
add(plugin: RudderDestinationPlugin())
- add(plugin: RSGDPRPlugin())
+ add(plugin: RSUserSessionPlugin())
if let platformPlugins = platformPlugins() {
for plugin in platformPlugins {
@@ -34,15 +29,7 @@ extension RSClient {
var plugins = [RSPlatformPlugin]()
plugins.append(RSContextPlugin())
-
- plugins.append(RSIdentifyTraitsPlugin())
- plugins.append(RSAliasIdPlugin())
- plugins.append(RSUserIdPlugin())
- plugins.append(RSAnonymousIdPlugin())
- plugins.append(RSAppTrackingConsentPlugin())
- plugins.append(RSAdvertisingIdPlugin())
- plugins.append(RSUserSessionPlugin())
-
+
plugins += Vendor.current.requiredPlugins
if config?.trackLifecycleEvents == true {
@@ -77,32 +64,22 @@ extension RSClient {
}
}
-#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst)
+#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) || os(watchOS)
import UIKit
extension RSClient {
internal func setupServerConfigCheck() {
- checkServerConfig()
- NotificationCenter.default.addObserver(forName: UIApplication.willEnterForegroundNotification, object: nil, queue: OperationQueue.main) { (notification) in
- guard let app = notification.object as? UIApplication else { return }
- if app.applicationState == .background {
- self.checkServerConfig()
- }
- }
- }
-}
-#elseif os(watchOS)
-extension RSClient {
- internal func setupServerConfigCheck() {
- checkServerConfig()
+ setupDownloadServerConfig()
}
}
+
#elseif os(macOS)
import Cocoa
extension RSClient {
internal func setupServerConfigCheck() {
- checkServerConfig()
- RSRepeatingTimer.schedule(interval: .days(1), queue: .main) {
- self.checkServerConfig()
+ setupDownloadServerConfig()
+ RSRepeatingTimer.schedule(interval: .days(1), queue: .main) { [weak self] in
+ guard let self = self else { return }
+ self.setupDownloadServerConfig()
}
}
}
@@ -116,70 +93,93 @@ extension RSClient {
}
func update(plugin: RSPlugin, serverConfig: RSServerConfig, type: UpdateType) {
- plugin.update(serverConfig: serverConfig, type: type)
+ // if the server config is not cached. we send the updateType to external destination as initial
+ var updateType = type
+ if !isServerConfigCached, type == .refresh, let destination = plugin as? RSDestinationPlugin, destination.key != RUDDER_DESTINATION_KEY {
+ updateType = .initial
+ }
+ plugin.update(serverConfig: serverConfig, type: updateType)
if let dest = plugin as? RSDestinationPlugin {
- dest.apply { (subPlugin) in
- subPlugin.update(serverConfig: serverConfig, type: type)
+ dest.apply { subPlugin in
+ subPlugin.update(serverConfig: serverConfig, type: updateType)
}
}
}
- func checkServerConfig() {
- assert(Thread.isMainThread)
- guard !self.checkServerConfigInProgress else { return }
-
- self.checkServerConfigInProgress = true
- self.checkServerConfig(retryCount: 0) {
- assert(Thread.isMainThread)
- self.checkServerConfigInProgress = false
+ func setupDownloadServerConfig() {
+ DispatchQueue.main.async { [weak self] in
+ guard let self = self else { return }
+
+ self.downloadServerConfig(retryCount: 0) { }
}
}
- private func checkServerConfig(retryCount: Int, completion: @escaping ( ) -> Void) {
- assert(Thread.isMainThread)
+ private func downloadServerConfig(retryCount: Int, completion: @escaping () -> Void) {
+ if isUnitTesting {
+ checkServerConfigForUnitTesting(completion: completion)
+ return
+ }
let maxRetryCount = 4
guard retryCount < maxRetryCount else {
- log(message: "Server config download failed. Using last stored config from storage", logLevel: .debug)
+ Logger.log(message: "Server config download failed.", logLevel: .debug)
completion()
return
}
- let updateType: UpdateType = self.serverConfig == nil ? .initial : .refresh
-
- fetchServerConfig { result in
- assert(Thread.isMainThread)
-
+ serviceManager?.downloadServerConfig({ [weak self] result in
+ guard let self = self else { return }
switch result {
case .success(let serverConfig):
+ Logger.log(message: "Server config download successful.", logLevel: .debug)
self.serverConfig = serverConfig
- self.update(serverConfig: serverConfig, type: updateType)
- RSUserDefaults.saveServerConfig(serverConfig)
- RSUserDefaults.updateLastUpdatedTime(RSUtils.getTimeStamp())
- self.log(message: "server config download successful", logLevel: .debug)
+ self.update(serverConfig: serverConfig, type: .refresh)
+ self.userDefaults.write(.serverConfig, value: serverConfig)
+ self.isServerConfigCached = true
completion()
-
+
case .failure(let error):
if error.code == RSErrorCode.WRONG_WRITE_KEY.rawValue {
- self.log(message: "Wrong write key", logLevel: .error)
- self.checkServerConfig(retryCount: maxRetryCount, completion: completion)
+ Logger.log(message: "Wrong write key", logLevel: .error)
+ self.downloadServerConfig(retryCount: maxRetryCount, completion: completion)
} else {
- self.log(message: "Retrying download in \(retryCount) seconds", logLevel: .debug)
+ Logger.log(message: "Retrying download in \(retryCount) seconds", logLevel: .debug)
DispatchQueue.main.asyncAfter(deadline: .now() + TimeInterval(retryCount)) {
- self.checkServerConfig(retryCount: retryCount + 1, completion: completion)
+ self.downloadServerConfig(retryCount: retryCount + 1, completion: completion)
}
}
}
- }
+ })
}
- private func fetchServerConfig(completion: @escaping (HandlerResult) -> Void) {
- let serviceManager = RSServiceManager(client: self)
- serviceManager.downloadServerConfig { result in
- DispatchQueue.main.async {
- completion(result)
- }
+ private func checkServerConfigForUnitTesting(completion: @escaping () -> Void) {
+ var configFileName = ""
+ switch RSClient.sourceConfigType {
+ default:
+ configFileName = "ServerConfig"
}
+
+ let path = TestUtils.shared.getPath(forResource: configFileName, ofType: "json")
+ do {
+ let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
+ let serverConfig = try JSONDecoder().decode(RSServerConfig.self, from: data)
+ self.serverConfig = serverConfig
+ self.update(serverConfig: serverConfig, type: .initial)
+ self.userDefaults.write(.serverConfig, value: serverConfig)
+ } catch { }
+
+ completion()
}
}
+
+extension RSClient {
+ static var sourceConfigType: SourceConfigType = .standard
+}
+
+// swiftlint:disable inclusive_language
+enum SourceConfigType {
+ case whiteList
+ case blackList
+ case standard
+}
diff --git a/Sources/Classes/Client/RSClient.swift b/Sources/Classes/Client/RSClient.swift
index f1f4322b..2c3229af 100644
--- a/Sources/Classes/Client/RSClient.swift
+++ b/Sources/Classes/Client/RSClient.swift
@@ -8,16 +8,30 @@
import Foundation
+// swiftlint:disable file_length
@objc
open class RSClient: NSObject {
var config: RSConfig?
var controller: RSController
var serverConfig: RSServerConfig?
- internal var checkServerConfigInProgress = false
+ var serviceManager: RSServiceManager?
+ @RSAtomic var isServerConfigCached = false
static let shared = RSClient()
+ var userDefaults = RSUserDefaults()
+ var userInfo: RSUserInfo? {
+ let userId: String? = userDefaults.read(.userId)
+ let traits: JSON? = userDefaults.read(.traits)
+ var anonymousId: String? = userDefaults.read(.anonymousId)
+ if anonymousId == nil {
+ anonymousId = RSUtils.getUniqueId()
+ userDefaults.write(.anonymousId, value: anonymousId)
+ }
+ return RSUserInfo(anonymousId: anonymousId, userId: userId, traits: traits)
+ }
private override init() {
- serverConfig = RSUserDefaults.getServerConfig()
+ serverConfig = userDefaults.read(.serverConfig)
+ isServerConfigCached = serverConfig != nil
controller = RSController()
}
@@ -43,7 +57,14 @@ open class RSClient: NSObject {
*/
@objc
public func configure(with config: RSConfig) {
+ // Config can be set only one time per session.
+ guard self.config == nil else { return }
self.config = config
+ Logger.logLevel = config.logLevel
+ if config.writeKey.isEmpty {
+ Logger.logError("Invalid writeKey: Provided writeKey is empty")
+ }
+ serviceManager = RSServiceManager(client: self)
addPlugins()
}
@@ -69,6 +90,11 @@ open class RSClient: NSObject {
_track(eventName, properties: properties, option: nil)
}
+ @objc
+ public func track(_ eventName: String, option: RSOption) {
+ _track(eventName, properties: nil, option: option)
+ }
+
@objc
public func track(_ eventName: String) {
_track(eventName, properties: nil, option: nil)
@@ -96,6 +122,11 @@ open class RSClient: NSObject {
_identify(userId, traits: traits, option: nil)
}
+ @objc
+ public func identify(_ userId: String, option: RSOption) {
+ _identify(userId, traits: nil, option: option)
+ }
+
@objc
public func identify(_ userId: String) {
_identify(userId, traits: nil, option: nil)
@@ -123,6 +154,11 @@ open class RSClient: NSObject {
_screen(screenName, category: category, properties: properties, option: nil)
}
+ @objc
+ public func screen(_ screenName: String, properties: ScreenProperties, option: RSOption) {
+ _screen(screenName, category: nil, properties: properties, option: option)
+ }
+
@objc
public func screen(_ screenName: String, properties: ScreenProperties) {
_screen(screenName, category: nil, properties: properties, option: nil)
@@ -133,6 +169,11 @@ open class RSClient: NSObject {
_screen(screenName, category: category, properties: nil, option: nil)
}
+ @objc
+ public func screen(_ screenName: String, option: RSOption) {
+ _screen(screenName, category: nil, properties: nil, option: option)
+ }
+
@objc
public func screen(_ screenName: String) {
_screen(screenName, category: nil, properties: nil, option: nil)
@@ -160,6 +201,11 @@ open class RSClient: NSObject {
_group(groupId, traits: traits, option: nil)
}
+ @objc
+ public func group(_ groupId: String, option: RSOption) {
+ _group(groupId, traits: nil, option: option)
+ }
+
@objc
public func group(_ groupId: String) {
_group(groupId, traits: nil, option: nil)
@@ -189,18 +235,25 @@ open class RSClient: NSObject {
extension RSClient {
internal func _track(_ eventName: String, properties: TrackProperties? = nil, option: RSOption? = nil) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOutAndEventDrop, logLevel: .debug)
+ return
+ }
guard eventName.isNotEmpty else {
- log(message: "eventName can not be empty", logLevel: .warning)
+ Logger.log(message: "eventName can not be empty", logLevel: .warning)
return
}
let message = TrackMessage(event: eventName, properties: properties, option: option)
- .applyRawEventData()
- process(message: message)
+ process(incomingMessage: message)
}
internal func _screen(_ screenName: String, category: String? = nil, properties: ScreenProperties? = nil, option: RSOption? = nil) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOutAndEventDrop, logLevel: .debug)
+ return
+ }
guard screenName.isNotEmpty else {
- log(message: "screenName can not be empty", logLevel: .warning)
+ Logger.log(message: "screenName can not be empty", logLevel: .warning)
return
}
var screenProperties = ScreenProperties()
@@ -209,43 +262,62 @@ extension RSClient {
}
screenProperties["name"] = screenName
let message = ScreenMessage(title: screenName, category: category, properties: screenProperties, option: option)
- .applyRawEventData()
- process(message: message)
+ process(incomingMessage: message)
}
internal func _group(_ groupId: String, traits: [String: String]? = nil, option: RSOption? = nil) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOutAndEventDrop, logLevel: .debug)
+ return
+ }
guard groupId.isNotEmpty else {
- log(message: "groupId can not be empty", logLevel: .warning)
+ Logger.log(message: "groupId can not be empty", logLevel: .warning)
return
}
let message = GroupMessage(groupId: groupId, traits: traits, option: option)
- .applyRawEventData()
- process(message: message)
+ process(incomingMessage: message)
}
internal func _alias(_ newId: String, option: RSOption? = nil) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOutAndEventDrop, logLevel: .debug)
+ return
+ }
guard newId.isNotEmpty else {
- log(message: "newId can not be empty", logLevel: .warning)
+ Logger.log(message: "newId can not be empty", logLevel: .warning)
return
}
- let message = AliasMessage(newId: newId, option: option)
- .applyAlias(newId: newId, client: self)
- .applyRawEventData()
- setAlias(newId)
- setUserId(newId)
- process(message: message)
+ let previousId: String? = userDefaults.read(.userId)
+ userDefaults.write(.userId, value: newId)
+ var dict: [String: Any] = ["id": newId]
+ if let json: JSON = userDefaults.read(.traits), let traits = json.dictionaryValue {
+ dict.merge(traits) { (_, new) in new }
+ }
+ userDefaults.write(.traits, value: try? JSON(dict))
+ let message = AliasMessage(newId: newId, previousId: previousId, option: option)
+ process(incomingMessage: message)
}
internal func _identify(_ userId: String, traits: IdentifyTraits? = nil, option: RSOption? = nil) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOutAndEventDrop, logLevel: .debug)
+ return
+ }
guard userId.isNotEmpty else {
- log(message: "userId can not be empty", logLevel: .warning)
+ Logger.log(message: "userId can not be empty", logLevel: .warning)
return
}
+ userDefaults.write(.userId, value: userId)
+
+ if let traits = traits {
+ userDefaults.write(.traits, value: try? JSON(traits))
+ }
+
+ if let externalIds = option?.externalIds {
+ userDefaults.write(.externalId, value: try? JSON(externalIds))
+ }
let message = IdentifyMessage(userId: userId, traits: traits, option: option)
- .applyRawEventData()
- setTraits(traits, userId)
- setUserId(userId)
- process(message: message)
+ process(incomingMessage: message)
}
}
@@ -257,10 +329,11 @@ extension RSClient {
*/
@objc
public var anonymousId: String? {
- if let anonymousIdPlugin = self.find(pluginType: RSAnonymousIdPlugin.self) {
- return anonymousIdPlugin.anonymousId
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return nil
}
- return nil
+ return userDefaults.read(.anonymousId)
}
/**
@@ -268,32 +341,39 @@ extension RSClient {
*/
@objc
public var userId: String? {
- if let userIdPlugin = self.find(pluginType: RSUserIdPlugin.self) {
- return userIdPlugin.userId
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return nil
}
- return nil
+ return userDefaults.read(.userId)
}
/**
Returns the context that were specified in the last call.
*/
@objc
- public var context: MessageContext? {
- if let contextPlugin = self.find(pluginType: RSContextPlugin.self) {
- return contextPlugin.context
+ public var context: RSContext? {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return nil
}
- return nil
+ if let currentContext: RSContext = RSSessionStorage.shared.read(.context) {
+ return currentContext
+ }
+ return RSContext(userDefaults: userDefaults)
}
/**
Returns the traits that were specified in the last identify call.
*/
@objc
- public var traits: MessageTraits? {
- if let contextPlugin = self.find(pluginType: RSContextPlugin.self) {
- return contextPlugin.traits
+ public var traits: IdentifyTraits? {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return nil
}
- return nil
+ let traits: JSON? = RSContext.traits(userDefaults: userDefaults)
+ return traits?.dictionaryValue
}
/**
@@ -308,11 +388,24 @@ extension RSClient {
}
}
+ /**
+ API for reset current slate. Traits, UserID's, anonymousId, etc are all cleared or reset. This command will also be sent to each destination present in the system.
+ */
+ @objc
+ public func reset(and refreshAnonymousId: Bool) {
+ if refreshAnonymousId {
+ userDefaults.write(.anonymousId, value: RSUtils.getUniqueId())
+ }
+ reset()
+ }
+
/**
API for reset current slate. Traits, UserID's, anonymousId, etc are all cleared or reset. This command will also be sent to each destination present in the system.
*/
@objc
public func reset() {
+ userDefaults.reset()
+ RSSessionStorage.shared.reset()
apply { plugin in
if let p = plugin as? RSEventPlugin {
p.reset()
@@ -333,8 +426,27 @@ extension RSClient {
*/
@objc
public var configuration: RSConfig? {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return nil
+ }
return config
}
+
+ /**
+ Returns id of an active session.
+ */
+ @objc
+ public var sessionId: String? {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return nil
+ }
+ if let userSessionPlugin = self.find(pluginType: RSUserSessionPlugin.self), let sessionId = userSessionPlugin.sessionId {
+ return "\(sessionId)"
+ }
+ return nil
+ }
}
extension RSClient {
@@ -365,7 +477,17 @@ extension RSClient {
}
extension RSClient {
+ func process(incomingMessage: RSMessage) {
+ let message = incomingMessage.applyRawEventData(userInfo: userInfo)
+ process(message: message)
+ }
+
func process(message: RSMessage) {
+ if let serverConfig = serverConfig, !serverConfig.enabled {
+ Logger.logDebug("Source is disabled in your dashboard. Hence event is dropped.")
+ return
+ }
+
switch message {
case let e as TrackMessage:
controller.process(incomingEvent: e)
@@ -382,3 +504,127 @@ extension RSClient {
}
}
}
+
+extension RSClient {
+ /**
+ API for setting unique identifier of every call.
+ - Parameters:
+ - anonymousId: Unique identifier of every event
+ # Example #
+ ```
+ RSClient.sharedInstance().setAnonymousId("sample_anonymous_id")
+ ```
+ */
+ @objc
+ public func setAnonymousId(_ anonymousId: String) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return
+ }
+ guard anonymousId.isNotEmpty else {
+ Logger.log(message: "anonymousId can not be empty", logLevel: .warning)
+ return
+ }
+ userDefaults.write(.anonymousId, value: anonymousId)
+ }
+
+ /**
+ API for setting enable/disable sending the events across all the event calls made using the SDK to the specified destinations.
+ - Parameters:
+ - option: Options related to every API call
+ # Example #
+ ```
+ let defaultOption = RSOption()
+ defaultOption.putIntegration("Amplitude", isEnabled: true)
+
+ RSClient.sharedInstance().setOption(defaultOption)
+ ```
+ */
+ @objc
+ public func setOption(_ option: RSOption) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return
+ }
+ RSSessionStorage.shared.write(.option, value: option)
+ }
+
+ /**
+ API for setting token under context.device.token.
+ - Parameters:
+ - token: Token of the device
+ # Example #
+ ```
+ RSClient.sharedInstance().setDeviceToken("sample_device_token")
+ ```
+ */
+ @objc
+ public func setDeviceToken(_ token: String) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return
+ }
+ guard token.isNotEmpty else {
+ Logger.log(message: "token can not be empty", logLevel: .warning)
+ return
+ }
+ RSSessionStorage.shared.write(.deviceToken, value: token)
+ }
+
+ /**
+ API for setting identifier under context.device.advertisingId.
+ - Parameters:
+ - advertisingId: IDFA value
+ # Example #
+ ```
+ RSClient.sharedInstance().setAdvertisingId("sample_advertising_id")
+ ```
+ */
+ @objc
+ public func setAdvertisingId(_ advertisingId: String) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return
+ }
+ guard advertisingId.isNotEmpty else {
+ Logger.log(message: "advertisingId can not be empty", logLevel: .warning)
+ return
+ }
+ if advertisingId != "00000000-0000-0000-0000-000000000000" {
+ RSSessionStorage.shared.write(.advertisingId, value: advertisingId)
+ }
+ }
+
+ /**
+ API for app tracking consent management.
+ - Parameters:
+ - appTrackingConsent: App tracking consent
+ # Example #
+ ```
+ RSClient.sharedInstance().setAppTrackingConsent(.authorize)
+ ```
+ */
+ @objc
+ public func setAppTrackingConsent(_ appTrackingConsent: RSAppTrackingConsent) {
+ if let optOutStatus: Bool = userDefaults.read(.optStatus), optOutStatus {
+ Logger.log(message: LogMessages.optOut, logLevel: .debug)
+ return
+ }
+ RSSessionStorage.shared.write(.appTrackingConsent, value: appTrackingConsent)
+ }
+
+ /**
+ API for enable or disable tracking user activities.
+ - Parameters:
+ - status: Enable or disable tracking
+ # Example #
+ ```
+ RSClient.sharedInstance().setOptOutStatus(false)
+ ```
+ */
+ @objc
+ public func setOptOutStatus(_ status: Bool) {
+ userDefaults.write(.optStatus, value: status)
+ Logger.log(message: "User has been Opted \(status ? "out" : "in")", logLevel: .debug)
+ }
+}
diff --git a/Sources/Classes/Client/RSController.swift b/Sources/Classes/Client/RSController.swift
index 5b72cd54..8ae5ca8b 100644
--- a/Sources/Classes/Client/RSController.swift
+++ b/Sources/Classes/Client/RSController.swift
@@ -67,8 +67,7 @@ class Mediator {
plugins.forEach { (plugin) in
if let r = result {
- // Drop the event return because we don't care about the
- // final result.
+ // Drop the event return because we don't care about the final result.
if plugin is RSDestinationPlugin {
_ = plugin.execute(message: r)
} else {
@@ -191,7 +190,7 @@ extension RSDestinationPlugin {
}
func isDestinationEnabled(message: RSMessage) -> Bool {
- var customerDisabled = false
+ var customerDisabled: Bool?
if let integration = message.integrations?.first(where: { key, _ in
return key == self.key
@@ -199,14 +198,23 @@ extension RSDestinationPlugin {
customerDisabled = true
}
- var hasSettings = false
+ var hasSettings: Bool?
if let destinations = client?.serverConfig?.destinations {
if let destination = destinations.first(where: { $0.destinationDefinition?.displayName == self.key }), destination.enabled {
hasSettings = true
}
}
- return (hasSettings == true && customerDisabled == false)
+ if customerDisabled == nil, hasSettings == nil {
+ return false
+ }
+ if customerDisabled == true {
+ return false
+ }
+ if hasSettings == true {
+ return true
+ }
+ return false
}
// swiftlint:disable inclusive_language
@@ -215,8 +223,6 @@ extension RSDestinationPlugin {
switch message {
case let e as TrackMessage:
return list.contains(e.event)
- case let e as ScreenMessage:
- return list.contains(e.name)
default:
break
}
@@ -244,41 +250,32 @@ extension RSDestinationPlugin {
}
func process(incomingEvent: E) -> E? {
- // This will process plugins (think destination middleware) that are tied
- // to this destination.
-
- var result: E?
+ guard isDestinationEnabled(message: incomingEvent) else {
+ Logger.logDebug("Destination is not enabled.")
+ return nil
+ }
- if isDestinationEnabled(message: incomingEvent) {
- // check event is allowed
- if isEventAllowed(message: incomingEvent) {
- // apply .before and .enrichment types first ...
- let beforeResult = controller.applyPlugins(type: .before, event: incomingEvent)
- let enrichmentResult = controller.applyPlugins(type: .enrichment, event: beforeResult)
-
- // now we execute any overrides we may have made. basically, the idea is to take an
- // incoming event, like identify, and map it to whatever is appropriate for this destination.
- var destinationResult: E?
- switch enrichmentResult {
- case let e as IdentifyMessage:
- destinationResult = identify(message: e) as? E
- case let e as TrackMessage:
- destinationResult = track(message: e) as? E
- case let e as ScreenMessage:
- destinationResult = screen(message: e) as? E
- case let e as GroupMessage:
- destinationResult = group(message: e) as? E
- case let e as AliasMessage:
- destinationResult = alias(message: e) as? E
- default:
- break
- }
+ guard isEventAllowed(message: incomingEvent) else {
+ Logger.logDebug("Event is filtered by Client-side event filtering.")
+ return nil
+ }
- // apply .after plugins ...
- result = controller.applyPlugins(type: .after, event: destinationResult)
- }
+ var destinationResult: E?
+ switch incomingEvent {
+ case let e as IdentifyMessage:
+ destinationResult = identify(message: e) as? E
+ case let e as TrackMessage:
+ destinationResult = track(message: e) as? E
+ case let e as ScreenMessage:
+ destinationResult = screen(message: e) as? E
+ case let e as GroupMessage:
+ destinationResult = group(message: e) as? E
+ case let e as AliasMessage:
+ destinationResult = alias(message: e) as? E
+ default:
+ break
}
- return result
+ return destinationResult
}
}
diff --git a/Sources/Classes/Client/RSDatabaseManager.swift b/Sources/Classes/Client/RSDatabaseManager.swift
index d5c9be7b..d745ea70 100644
--- a/Sources/Classes/Client/RSDatabaseManager.swift
+++ b/Sources/Classes/Client/RSDatabaseManager.swift
@@ -25,17 +25,17 @@ class RSDatabaseManager {
func createTable() {
var createTableStatement: OpaquePointer?
let createTableString = "CREATE TABLE IF NOT EXISTS events( id INTEGER PRIMARY KEY AUTOINCREMENT, message TEXT NOT NULL, updated INTEGER NOT NULL);"
- client.log(message: "createTableSQL: \(createTableString)", logLevel: .debug)
+ Logger.log(message: "createTableSQL: \(createTableString)", logLevel: .debug)
if sqlite3_prepare_v2(database, createTableString, -1, &createTableStatement, nil) ==
SQLITE_OK {
if sqlite3_step(createTableStatement) == SQLITE_DONE {
- client.log(message: ("DB Schema created"), logLevel: .debug)
+ Logger.log(message: ("DB Schema created"), logLevel: .debug)
} else {
- client.log(message: "DB Schema creation error", logLevel: .error)
+ Logger.log(message: "DB Schema creation error", logLevel: .error)
}
} else {
let errorMessage = String(cString: sqlite3_errmsg(database))
- client.log(message: "DB Schema CREATE statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
+ Logger.log(message: "DB Schema CREATE statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
}
sqlite3_finalize(createTableStatement)
}
@@ -46,15 +46,15 @@ class RSDatabaseManager {
if sqlite3_prepare_v2(database, insertStatementString, -1, &insertStatement, nil) == SQLITE_OK {
sqlite3_bind_text(insertStatement, 1, ((message.replacingOccurrences(of: "'", with: "''")) as NSString).utf8String, -1, nil)
sqlite3_bind_int(insertStatement, 2, Int32(RSUtils.getTimeStamp()))
- client.log(message: "saveEventSQL: \(insertStatementString)", logLevel: .debug)
+ Logger.log(message: "saveEventSQL: \(insertStatementString)", logLevel: .debug)
if sqlite3_step(insertStatement) == SQLITE_DONE {
- client.log(message: "Event inserted to table", logLevel: .debug)
+ Logger.log(message: "Event inserted to table", logLevel: .debug)
} else {
- client.log(message: "Event insertion error", logLevel: .error)
+ Logger.log(message: "Event insertion error", logLevel: .error)
}
} else {
let errorMessage = String(cString: sqlite3_errmsg(database))
- client.log(message: "Event INSERT statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
+ Logger.log(message: "Event INSERT statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
}
sqlite3_finalize(insertStatement)
}
@@ -62,16 +62,16 @@ class RSDatabaseManager {
private func clearEvents(_ messageIds: [String]) {
var deleteStatement: OpaquePointer?
let deleteStatementString = "DELETE FROM events WHERE id IN (\((messageIds as NSArray).componentsJoined(by: ",") as NSString));"
- client.log(message: "deleteEventSQL: \(deleteStatementString)", logLevel: .debug)
+ Logger.log(message: "deleteEventSQL: \(deleteStatementString)", logLevel: .debug)
if sqlite3_prepare_v2(database, deleteStatementString, -1, &deleteStatement, nil) == SQLITE_OK {
if sqlite3_step(deleteStatement) == SQLITE_DONE {
- client.log(message: "Events deleted from DB", logLevel: .debug)
+ Logger.log(message: "Events deleted from DB", logLevel: .debug)
} else {
- client.log(message: "Event deletion error", logLevel: .error)
+ Logger.log(message: "Event deletion error", logLevel: .error)
}
} else {
let errorMessage = String(cString: sqlite3_errmsg(database))
- client.log(message: "Event DELETE statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
+ Logger.log(message: "Event DELETE statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
}
sqlite3_finalize(deleteStatement)
}
@@ -80,7 +80,7 @@ class RSDatabaseManager {
var queryStatement: OpaquePointer?
var message: RSDBMessage?
let queryStatementString = "SELECT * FROM events ORDER BY updated ASC LIMIT \(count);"
- client.log(message: "countSQL: \(queryStatementString)", logLevel: .debug)
+ Logger.log(message: "countSQL: \(queryStatementString)", logLevel: .debug)
if sqlite3_prepare_v2(database, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK {
var messages = [String]()
var messageIds = [String]()
@@ -95,7 +95,7 @@ class RSDatabaseManager {
message = RSDBMessage(messages: messages, messageIds: messageIds)
} else {
let errorMessage = String(cString: sqlite3_errmsg(database))
- client.log(message: "Event SELECT statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
+ Logger.log(message: "Event SELECT statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
}
sqlite3_finalize(queryStatement)
return message
@@ -104,16 +104,16 @@ class RSDatabaseManager {
private func fetchDBRecordCount() -> Int {
var queryStatement: OpaquePointer?
let queryStatementString = "SELECT COUNT(*) FROM 'events'"
- client.log(message: "countSQL: \(queryStatementString)", logLevel: .debug)
+ Logger.log(message: "countSQL: \(queryStatementString)", logLevel: .debug)
var count = 0
if sqlite3_prepare_v2(database, queryStatementString, -1, &queryStatement, nil) == SQLITE_OK {
- client.log(message: "count fetched from DB", logLevel: .debug)
+ Logger.log(message: "count fetched from DB", logLevel: .debug)
while sqlite3_step(queryStatement) == SQLITE_ROW {
count = Int(sqlite3_column_int(queryStatement, 0))
}
} else {
let errorMessage = String(cString: sqlite3_errmsg(database))
- client.log(message: "count SELECT statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
+ Logger.log(message: "count SELECT statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
}
sqlite3_finalize(queryStatement)
return count
@@ -123,15 +123,15 @@ class RSDatabaseManager {
var deleteStatement: OpaquePointer?
let deleteStatementString = "DELETE FROM 'events';"
if sqlite3_prepare_v2(database, deleteStatementString, -1, &deleteStatement, nil) == SQLITE_OK {
- client.log(message: "deleteEventSQL: \(deleteStatementString)", logLevel: .debug)
+ Logger.log(message: "deleteEventSQL: \(deleteStatementString)", logLevel: .debug)
if sqlite3_step(deleteStatement) == SQLITE_DONE {
- client.log(message: "Events deleted from DB", logLevel: .debug)
+ Logger.log(message: "Events deleted from DB", logLevel: .debug)
} else {
- client.log(message: "Event deletion error", logLevel: .error)
+ Logger.log(message: "Event deletion error", logLevel: .error)
}
} else {
let errorMessage = String(cString: sqlite3_errmsg(database))
- client.log(message: "Event DELETE statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
+ Logger.log(message: "Event DELETE statement is not prepared, Reason: \(errorMessage)", logLevel: .error)
}
sqlite3_finalize(deleteStatement)
}
@@ -143,24 +143,23 @@ extension RSDatabaseManager {
guard let self = self else { return }
self.lock.lock()
do {
- let jsonObject = RSUtils.handleUrlAndDateTypes(message.dictionaryValue)
- if JSONSerialization.isValidJSONObject(jsonObject) {
+ if let jsonObject = RSUtils.handleUrlAndDateTypes(message.dictionaryValue), JSONSerialization.isValidJSONObject(jsonObject) {
let jsonData = try JSONSerialization.data(withJSONObject: jsonObject)
if let jsonString = String(data: jsonData, encoding: .utf8) {
- self.client.log(message: "dump: \(jsonString)", logLevel: .debug)
+ Logger.log(message: "dump: \(jsonString)", logLevel: .debug)
if jsonString.getUTF8Length() > MAX_EVENT_SIZE {
- self.client.log(message: "dump: Event size exceeds the maximum permitted event size \(MAX_EVENT_SIZE)", logLevel: .error)
+ Logger.log(message: "dump: Event size exceeds the maximum permitted event size \(MAX_EVENT_SIZE)", logLevel: .error)
return
}
self.saveEvent(jsonString)
} else {
- self.client.log(message: "dump: Can not convert to JSON", logLevel: .error)
+ Logger.log(message: "dump: Can not convert to JSON", logLevel: .error)
}
} else {
- self.client.log(message: "dump: Not a valid JSON object", logLevel: .error)
+ Logger.log(message: "dump: Not a valid JSON object", logLevel: .error)
}
} catch {
- self.client.log(message: "dump: \(error.localizedDescription)", logLevel: .error)
+ Logger.log(message: "dump: \(error.localizedDescription)", logLevel: .error)
}
self.lock.unlock()
}
diff --git a/Sources/Classes/Common/Constants/LogMessages.swift b/Sources/Classes/Common/Constants/LogMessages.swift
new file mode 100644
index 00000000..4b56429f
--- /dev/null
+++ b/Sources/Classes/Common/Constants/LogMessages.swift
@@ -0,0 +1,14 @@
+//
+// LogMessages.swift
+// Rudder
+//
+// Created by Pallab Maiti on 28/11/23.
+// Copyright © 2023 Rudder Labs India Pvt Ltd. All rights reserved.
+//
+
+import Foundation
+
+struct LogMessages {
+ static let optOut = "User has been Opted out"
+ static let optOutAndEventDrop = "User has been Opted out, hence dropping the event"
+}
diff --git a/Sources/Classes/Common/Constants/RSConstants.swift b/Sources/Classes/Common/Constants/RSConstants.swift
index a6e7bd22..75cc669b 100644
--- a/Sources/Classes/Common/Constants/RSConstants.swift
+++ b/Sources/Classes/Common/Constants/RSConstants.swift
@@ -8,15 +8,8 @@
import Foundation
-public let RSDataPlaneUrl = "https://hosted.rudderlabs.com"
-public let RSFlushQueueSize: Int = 30
-public let RSDBCountThreshold: Int = 10000
-public let RSSleepTimeout: Int = 10
-public let RSControlPlaneUrl = "https://api.rudderlabs.com"
-public let RSTrackLifeCycleEvents = true
-public let RSRecordScreenViews = false
-let RETRY_FLUSH_COUNT = 3
let TAG = "RudderStack"
+let RUDDER_DESTINATION_KEY = "RudderStack"
let RSServerConfigKey = "rs_server_config"
let RSServerLastUpdatedKey = "rs_server_last_updated"
let RSTraitsKey = "rs_traits"
@@ -28,13 +21,31 @@ let RSAnonymousIdKey = "rs_anonymous_id"
let RSOptStatusKey = "rs_opt_status"
let RSOptInTimeKey = "rs_opt_in_time"
let RSOptOutTimeKey = "rs_opt_out_time"
-let MAX_EVENT_SIZE: UInt = 32 * 1024
-let MAX_BATCH_SIZE: UInt = 500 * 1024
-let RSAutoSessionTracking: Bool = true
-let RSSessionTimeout: Int = 300000
-let RSSessionInActivityMinimumTimeOut = 0
let RSSessionIdKey = "rl_session_id"
let RSLastEventTimeStamp = "rl_last_event_time_stamp"
let RSSessionAutoTrackStatus = "rl_session_auto_track_status"
let RSSessionManualTrackStatus = "rl_session_manual_track_status"
let RSSessionStoppedStatus = "rl_session_stopped_status"
+
+let DEFAULT_DATA_PLANE_URL = "https://hosted.rudderlabs.com"
+let DEFAULT_CONTROL_PLANE_URL = "https://api.rudderlabs.com"
+let DEFAULT_TRACK_LIFE_CYCLE_EVENTS_STATUS = true
+let DEFAULT_RECORD_SCREEN_VIEWS_STATUS = false
+let DEFAULT_AUTO_SESSION_TRACKING_STATUS = true
+
+let DEFAULT_FLUSH_QUEUE_SIZE = 30
+let MAX_FLUSH_QUEUE_SIZE = 100
+let MIN_FLUSH_QUEUE_SIZE = 1
+
+let DEFAULT_DB_COUNT_THRESHOLD = 10000
+let MIN_DB_COUNT_THRESHOLD = 1
+
+let DEFAULT_SLEEP_TIMEOUT = 10
+let MIN_SLEEP_TIMEOUT = 10
+
+let DEFAULT_SESSION_TIMEOUT: Int = 300000
+let MIN_SESSION_TIMEOUT = 0
+
+let MAX_EVENT_SIZE: UInt = 32 * 1024
+let MAX_BATCH_SIZE: UInt = 500 * 1024
+let RETRY_FLUSH_COUNT = 3
diff --git a/Sources/Classes/Common/Constants/RSUserDefaults.swift b/Sources/Classes/Common/Constants/RSUserDefaults.swift
deleted file mode 100644
index e80b31ba..00000000
--- a/Sources/Classes/Common/Constants/RSUserDefaults.swift
+++ /dev/null
@@ -1,133 +0,0 @@
-//
-// RSUserDefaults.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 17/08/21.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSUserDefaults {
- static func getLastUpdatedTime() -> Int? {
- return UserDefaults.standard.lastUpdateTime
- }
-
- static func updateLastUpdatedTime(_ time: Int) {
- UserDefaults.standard.lastUpdateTime = time
- }
-
- static func getServerConfig() -> RSServerConfig? {
- return UserDefaults.standard.serverConfig
- }
-
- static func saveServerConfig(_ serverConfig: RSServerConfig) {
- UserDefaults.standard.serverConfig = serverConfig
- }
-
- static func getApplicationVersion() -> String? {
- return UserDefaults.standard.applicationVersion
- }
-
- static func saveApplicationVersion(_ version: String?) {
- UserDefaults.standard.applicationVersion = version
- }
-
- static func getApplicationBuild() -> String? {
- return UserDefaults.standard.applicationBuild
- }
-
- static func saveApplicationBuild(_ build: String?) {
- UserDefaults.standard.applicationBuild = build
- }
-
- static func getOptStatus() -> Bool? {
- return UserDefaults.standard.optStatus
- }
-
- static func saveOptStatus(_ optStatus: Bool) {
- UserDefaults.standard.optStatus = optStatus
- }
-
- static func getOptInTime() -> Int? {
- return UserDefaults.standard.optInTime
- }
-
- static func updateOptInTime(_ optInTime: Int?) {
- UserDefaults.standard.optInTime = optInTime
- }
-
- static func getOptOutTime() -> Int? {
- return UserDefaults.standard.optOutTime
- }
-
- static func updateOptOutTime(_ optOutTime: Int?) {
- UserDefaults.standard.optOutTime = optOutTime
- }
-
- static func saveSessionId(_ sessionId: Int) {
- UserDefaults.standard.sessionId = sessionId
- UserDefaults.standard.synchronize()
- }
-
- static func getSessionId() -> Int? {
- return UserDefaults.standard.sessionId
- }
-
- static func saveLastEventTimeStamp(_ lastEventTimeStamp: Int?) {
- UserDefaults.standard.lastEventTimeStamp = lastEventTimeStamp
- UserDefaults.standard.synchronize()
- }
-
- static func getLastEventTimeStamp() -> Int? {
- if let lastEventTimeStamp = UserDefaults.standard.lastEventTimeStamp, lastEventTimeStamp != 0 {
- return lastEventTimeStamp
- }
- return nil
- }
-
- static func saveAutomaticSessionTrackingStatus(_ autoTrackingStatus: Bool) {
- UserDefaults.standard.automaticTrackingStatus = autoTrackingStatus
- UserDefaults.standard.synchronize()
- }
-
- static func getAutomaticSessionTrackingStatus() -> Bool? {
- return UserDefaults.standard.automaticTrackingStatus
- }
-
- static func saveManualSessionTrackingStatus(_ manualTrackingStatus: Bool) {
- UserDefaults.standard.manualTrackingStatus = manualTrackingStatus
- UserDefaults.standard.synchronize()
- }
-
- static func getManualSessionTrackingStatus() -> Bool? {
- return UserDefaults.standard.manualTrackingStatus
- }
-
- static func saveSessionStoppedStatus(_ sessionStoppedStatus: Bool) {
- UserDefaults.standard.sessionStoppedStatus = sessionStoppedStatus
- UserDefaults.standard.synchronize()
- }
-
- static func getSessionStoppedStatus() -> Bool? {
- return UserDefaults.standard.sessionStoppedStatus
- }
-
- static func saveTraits(_ traits: Data?) {
- UserDefaults.standard.traits = traits
- UserDefaults.standard.synchronize()
- }
-
- static func getTraits() -> Data? {
- return UserDefaults.standard.traits
- }
-
- static func saveUserId(_ userId: String?) {
- UserDefaults.standard.userId = userId
- UserDefaults.standard.synchronize()
- }
-
- static func getUserId() -> String? {
- return UserDefaults.standard.userId
- }
-}
diff --git a/Sources/Classes/Common/Extensions/Data+Ext.swift b/Sources/Classes/Common/Extensions/Data+Ext.swift
new file mode 100644
index 00000000..fc59b20b
--- /dev/null
+++ b/Sources/Classes/Common/Extensions/Data+Ext.swift
@@ -0,0 +1,16 @@
+//
+// Data+Ext.swift
+// Rudder
+//
+// Created by Pallab Maiti on 16/07/22.
+// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
+//
+
+import Foundation
+
+extension Data {
+ var hexString: String {
+ let hexString = map { String(format: "%02.2hhx", $0) }.joined()
+ return hexString
+ }
+}
diff --git a/Sources/Classes/Common/Extensions/UserDefaults+Ext.swift b/Sources/Classes/Common/Extensions/UserDefaults+Ext.swift
deleted file mode 100644
index 33743d8a..00000000
--- a/Sources/Classes/Common/Extensions/UserDefaults+Ext.swift
+++ /dev/null
@@ -1,108 +0,0 @@
-//
-// UserDefaults+Ext.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 13/08/21.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-extension PropertyListDecoder {
- func optionalDecode(_ type: T.Type, from object: Any?) -> T? {
- if let data = object as? Data {
- return try? PropertyListDecoder().decode(T.self, from: data)
- }
- return nil
- }
-}
-
-extension UserDefaults {
- var serverConfig: RSServerConfig? {
- get {
- return PropertyListDecoder().optionalDecode(RSServerConfig.self, from: object(forKey: RSServerConfigKey))
- }
- set {
- if let newValue = newValue {
- set(try? PropertyListEncoder().encode(newValue), forKey: RSServerConfigKey)
- } else {
- set(nil, forKey: RSServerConfigKey)
- }
- }
- }
-
- var lastUpdateTime: Int? {
- get { integer(forKey: RSServerLastUpdatedKey) }
- set { setValue(newValue, forKey: RSServerLastUpdatedKey) }
- }
-
- var applicationVersion: String? {
- get { string(forKey: RSApplicationVersionKey) }
- set { setValue(newValue, forKey: RSApplicationVersionKey) }
- }
-
- var applicationBuild: String? {
- get { string(forKey: RSApplicationBuildKey) }
- set { setValue(newValue, forKey: RSApplicationBuildKey) }
- }
-
- var externalIds: String? {
- get { string(forKey: RSExternalIdKey) }
- set { setValue(newValue, forKey: RSExternalIdKey) }
- }
-
- var anonymousId: String? {
- get { string(forKey: RSAnonymousIdKey) }
- set { setValue(newValue, forKey: RSAnonymousIdKey) }
- }
-
- var optStatus: Bool? {
- get { bool(forKey: RSOptStatusKey) }
- set { setValue(newValue, forKey: RSOptStatusKey) }
- }
-
- var optInTime: Int? {
- get { integer(forKey: RSOptInTimeKey) }
- set { setValue(newValue, forKey: RSOptInTimeKey) }
- }
-
- var optOutTime: Int? {
- get { integer(forKey: RSOptOutTimeKey) }
- set { setValue(newValue, forKey: RSOptOutTimeKey) }
- }
-
- var sessionId: Int? {
- get { integer(forKey: RSSessionIdKey) }
- set { setValue(newValue, forKey: RSSessionIdKey) }
- }
-
- var lastEventTimeStamp: Int? {
- get { integer(forKey: RSLastEventTimeStamp) }
- set { setValue(newValue, forKey: RSLastEventTimeStamp) }
- }
-
- var automaticTrackingStatus: Bool? {
- get { bool(forKey: RSSessionAutoTrackStatus) }
- set { setValue(newValue, forKey: RSSessionAutoTrackStatus) }
- }
-
- var manualTrackingStatus: Bool? {
- get { bool(forKey: RSSessionManualTrackStatus) }
- set { setValue(newValue, forKey: RSSessionManualTrackStatus) }
- }
-
- var sessionStoppedStatus: Bool? {
- get { bool(forKey: RSSessionStoppedStatus) }
- set { setValue(newValue, forKey: RSSessionStoppedStatus) }
- }
-
- var traits: Data? {
- get { data(forKey: RSTraitsKey) }
- set { setValue(newValue, forKey: RSTraitsKey) }
- }
-
- var userId: String? {
- get { string(forKey: RSUserIdKey) }
- set { setValue(newValue, forKey: RSUserIdKey) }
- }
-}
diff --git a/Sources/Classes/Domain/Enums/JSON.swift b/Sources/Classes/Domain/Enums/JSON.swift
index 96fd2e05..f177ccda 100644
--- a/Sources/Classes/Domain/Enums/JSON.swift
+++ b/Sources/Classes/Domain/Enums/JSON.swift
@@ -35,7 +35,8 @@ public enum JSON: Equatable {
}
// For primitives??
- public init(_ value: Any) throws {
+ // swiftlint:disable cyclomatic_complexity
+ public init(_ value: Any) throws {
switch value {
// handle NS values
case _ as NSNull:
@@ -61,11 +62,22 @@ public enum JSON: Equatable {
self = .object(try object.mapValues(JSON.init))
case let json as JSON:
self = json
+ case let date as Date:
+ self = .string(Self.dateString(from: date))
// we don't work with whatever is being supplied
default:
throw JSONError.nonJSONType(type: "\(value.self)")
}
}
+
+ static func dateString(from date: Date) -> String {
+ let dateFormatter = DateFormatter()
+ dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
+ dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
+ dateFormatter.locale = Locale(identifier: "en_US_POSIX")
+ dateFormatter.calendar = Calendar(identifier: Calendar.Identifier.gregorian)
+ return dateFormatter.string(from: date)
+ }
}
// MARK: - Codable conformance
diff --git a/Sources/Classes/Domain/Enums/RSErrorCode.swift b/Sources/Classes/Domain/Enums/RSErrorCode.swift
index c3ebeee1..772eef2c 100644
--- a/Sources/Classes/Domain/Enums/RSErrorCode.swift
+++ b/Sources/Classes/Domain/Enums/RSErrorCode.swift
@@ -12,5 +12,7 @@ enum RSErrorCode: Int {
case UNKNOWN = -1
case WRONG_WRITE_KEY = 0
case DECODING_FAILED = 1
+ case RESOURCE_NOT_FOUND = 2
+ case BAD_REQUEST = 3
case SERVER_ERROR = 500
}
diff --git a/Sources/Classes/Domain/Enums/RSLogLevel.swift b/Sources/Classes/Domain/Enums/RSLogLevel.swift
deleted file mode 100644
index 0ad9d3d9..00000000
--- a/Sources/Classes/Domain/Enums/RSLogLevel.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// RSLogLevel.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 10/08/21.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-@frozen @objc public enum RSLogLevel: Int {
- case verbose = 5
- case debug = 4
- case info = 3
- case warning = 2
- case error = 1
- case `none` = 0
-
- public func toString() -> String {
- switch self {
- case .verbose:
- return "Verbose"
- case .debug:
- return "Debug"
- case .info:
- return "Info"
- case .warning:
- return "Warning"
- case .error:
- return "Error"
- case .none:
- return ""
- }
- }
-}
diff --git a/Sources/Classes/Domain/Models/RSConfig.swift b/Sources/Classes/Domain/Models/RSConfig.swift
index 3ff3b212..d4173392 100644
--- a/Sources/Classes/Domain/Models/RSConfig.swift
+++ b/Sources/Classes/Domain/Models/RSConfig.swift
@@ -15,52 +15,52 @@ open class RSConfig: NSObject {
return _writeKey
}
- private var _dataPlaneUrl: String = RSDataPlaneUrl
+ private var _dataPlaneUrl: String = DEFAULT_DATA_PLANE_URL
public var dataPlaneUrl: String {
return _dataPlaneUrl
}
- private var _flushQueueSize: Int = RSFlushQueueSize
+ private var _flushQueueSize: Int = DEFAULT_FLUSH_QUEUE_SIZE
public var flushQueueSize: Int {
return _flushQueueSize
}
- private var _dbCountThreshold: Int = RSDBCountThreshold
+ private var _dbCountThreshold: Int = DEFAULT_DB_COUNT_THRESHOLD
public var dbCountThreshold: Int {
return _dbCountThreshold
}
- private var _sleepTimeOut: Int = RSSleepTimeout
+ private var _sleepTimeOut: Int = DEFAULT_SLEEP_TIMEOUT
public var sleepTimeOut: Int {
return _sleepTimeOut
}
- private var _logLevel: RSLogLevel = RSLogLevel.none
+ private var _logLevel: RSLogLevel = .error
public var logLevel: RSLogLevel {
return _logLevel
}
- private var _trackLifecycleEvents: Bool = RSTrackLifeCycleEvents
+ private var _trackLifecycleEvents: Bool = DEFAULT_TRACK_LIFE_CYCLE_EVENTS_STATUS
public var trackLifecycleEvents: Bool {
return _trackLifecycleEvents
}
- private var _recordScreenViews: Bool = RSRecordScreenViews
+ private var _recordScreenViews: Bool = DEFAULT_RECORD_SCREEN_VIEWS_STATUS
public var recordScreenViews: Bool {
return _recordScreenViews
}
- private var _controlPlaneUrl: String = RSControlPlaneUrl
+ private var _controlPlaneUrl: String = DEFAULT_CONTROL_PLANE_URL
public var controlPlaneUrl: String {
return _controlPlaneUrl
}
- private var _autoSessionTracking: Bool = RSAutoSessionTracking
+ private var _autoSessionTracking: Bool = DEFAULT_AUTO_SESSION_TRACKING_STATUS
public var automaticSessionTracking: Bool {
return _autoSessionTracking
}
- private var _sessionTimeout: Int = RSSessionTimeout
+ private var _sessionTimeout: Int = DEFAULT_SESSION_TIMEOUT
public var sessionTimeout: Int {
return _sessionTimeout
}
@@ -72,20 +72,24 @@ open class RSConfig: NSObject {
@discardableResult @objc
public func dataPlaneURL(_ dataPlaneUrl: String) -> RSConfig {
- if let url = URL(string: dataPlaneUrl) {
- if let scheme = url.scheme, let host = url.host {
- if let port = url.port {
- _dataPlaneUrl = "\(scheme)://\(host):\(port)"
- } else {
- _dataPlaneUrl = "\(scheme)://\(host)"
- }
- }
+ guard let url = URL(string: dataPlaneUrl), let scheme = url.scheme, let host = url.host else {
+ Logger.logError("dataPlaneUrl is invalid")
+ return self
+ }
+ if let port = url.port {
+ _dataPlaneUrl = "\(scheme)://\(host):\(port)"
+ } else {
+ _dataPlaneUrl = "\(scheme)://\(host)"
}
return self
}
@discardableResult @objc
public func flushQueueSize(_ flushQueueSize: Int) -> RSConfig {
+ guard flushQueueSize >= MIN_FLUSH_QUEUE_SIZE && flushQueueSize <= MAX_FLUSH_QUEUE_SIZE else {
+ Logger.logError("flushQueueSize is out of range. Min: 1, Max: 100. Set to default")
+ return self
+ }
_flushQueueSize = flushQueueSize
return self
}
@@ -98,14 +102,18 @@ open class RSConfig: NSObject {
@discardableResult @objc
public func dbCountThreshold(_ dbCountThreshold: Int) -> RSConfig {
+ guard dbCountThreshold >= MIN_DB_COUNT_THRESHOLD else {
+ Logger.logError("dbCountThreshold is invalid. Min: 1. Set to default")
+ return self
+ }
_dbCountThreshold = dbCountThreshold
return self
}
@discardableResult @objc
public func sleepTimeOut(_ sleepTimeOut: Int) -> RSConfig {
- guard sleepTimeOut > 0 else {
- RSClient.rsLog(message: "sleepTimeOut can not be less than 1 second", logLevel: .warning)
+ guard sleepTimeOut >= MIN_SLEEP_TIMEOUT else {
+ Logger.logError("sleepTimeOut is invalid. Min: 10. Set to default")
return self
}
_sleepTimeOut = sleepTimeOut
@@ -126,14 +134,14 @@ open class RSConfig: NSObject {
@discardableResult @objc
public func controlPlaneURL(_ controlPlaneUrl: String) -> RSConfig {
- if let url = URL(string: controlPlaneUrl) {
- if let scheme = url.scheme, let host = url.host {
- if let port = url.port {
- _controlPlaneUrl = "\(scheme)://\(host):\(port)"
- } else {
- _controlPlaneUrl = "\(scheme)://\(host)"
- }
- }
+ guard let url = URL(string: controlPlaneUrl), let scheme = url.scheme, let host = url.host else {
+ Logger.logError("controlPlaneUrl is invalid")
+ return self
+ }
+ if #available(macOS 13.0, iOS 16.0, tvOS 16.0, watchOS 9.0, *) {
+ _controlPlaneUrl = "\(scheme)://\(host)\(url.path())"
+ } else {
+ _controlPlaneUrl = "\(scheme)://\(host)\(url.path)"
}
return self
}
@@ -146,8 +154,8 @@ open class RSConfig: NSObject {
@discardableResult @objc
public func sessionTimeout(_ sessionTimeout: Int) -> RSConfig {
- guard sessionTimeout >= RSSessionInActivityMinimumTimeOut else {
- RSClient.rsLog(message: "sessionTimeout can not be less than 0 second", logLevel: .warning)
+ guard sessionTimeout >= MIN_SESSION_TIMEOUT else {
+ Logger.logError("sessionTimeout is invalid. Min: 0. Set to default")
return self
}
_sessionTimeout = sessionTimeout
diff --git a/Sources/Classes/Domain/Models/RSContext.swift b/Sources/Classes/Domain/Models/RSContext.swift
new file mode 100644
index 00000000..a166b0b7
--- /dev/null
+++ b/Sources/Classes/Domain/Models/RSContext.swift
@@ -0,0 +1,216 @@
+//
+// RSContext.swift
+// Rudder
+//
+// Created by Pallab Maiti on 07/12/23.
+// Copyright © 2023 Rudder Labs India Pvt Ltd. All rights reserved.
+//
+
+import Foundation
+
+@objc
+open class RSContext: NSObject, Codable {
+ @objc
+ open class AppInfo: NSObject, Codable {
+ public var name: String
+ public var namespace: String
+ public var build: String
+ public var version: String
+
+ internal override init() {
+ let info = Bundle.main.infoDictionary
+ name = (info?["CFBundleDisplayName"] as? String ?? (info?["CFBundleName"] as? String)) ?? ""
+ version = (info?["CFBundleShortVersionString"] as? String) ?? ""
+ build = (info?["CFBundleVersion"] as? String) ?? ""
+ namespace = (Bundle.main.bundleIdentifier) ?? ""
+ }
+ }
+
+ @objc
+ open class DeviceInfo: NSObject, Codable {
+ public var id: String?
+ public var manufacturer: String?
+ public var model: String?
+ public var name: String?
+ public var type: String?
+
+ internal override init() {
+ manufacturer = Vendor.current.manufacturer
+ type = Vendor.current.type
+ model = Vendor.current.model
+ name = Vendor.current.name
+ id = Vendor.current.identifierForVendor
+ }
+ }
+
+ @objc
+ open class LibraryInfo: NSObject, Codable {
+ public var name: String
+ public var version: String
+
+ internal override init() {
+ name = "rudder-ios-library"
+ version = RSVersion
+ }
+ }
+
+ @objc
+ open class OSInfo: NSObject, Codable {
+ public var name: String?
+ public var version: String?
+
+ internal override init() {
+ name = Vendor.current.systemName
+ version = Vendor.current.systemVersion
+ }
+ }
+
+ @objc
+ open class ScreenInfo: NSObject, Codable {
+ public var density: Double?
+ public var width: Double?
+ public var height: Double?
+
+ internal override init() {
+ width = Vendor.current.screenSize.width
+ height = Vendor.current.screenSize.height
+ density = Vendor.current.screenSize.density
+ }
+ }
+
+ @objc
+ open class NetworkInfo: NSObject, Codable {
+ public var carrier: String?
+ public var bluetooth: Bool = false
+ public var cellular: Bool = false
+ public var wifi: Bool = false
+
+ internal override init() {
+ switch Vendor.current.connection {
+ case .online(.cellular):
+ cellular = true
+ case .online(.wifi):
+ wifi = true
+ case .online(.bluetooth):
+ bluetooth = true
+ default:
+ break
+ }
+ carrier = Vendor.current.carrier
+ }
+ }
+
+ private let _app: AppInfo?
+ public var app: AppInfo? {
+ _app
+ }
+
+ private let _device: DeviceInfo?
+ public var device: DeviceInfo? {
+ _device
+ }
+
+ private let _library: LibraryInfo?
+ public var library: LibraryInfo? {
+ _library
+ }
+
+ private let _os: OSInfo?
+ public var os: OSInfo? {
+ _os
+ }
+
+ private let _screen: ScreenInfo?
+ public var screen: ScreenInfo? {
+ _screen
+ }
+
+ private let _locale: String?
+ public var locale: String? {
+ _locale
+ }
+
+ private let _network: NetworkInfo?
+ public var network: NetworkInfo? {
+ _network
+ }
+
+ private let _timezone: String?
+ public var timezone: String? {
+ _timezone
+ }
+
+ private let _traits: JSON?
+ public var traits: IdentifyTraits? {
+ _traits?.dictionaryValue
+ }
+
+ private let _externalIds: [[String: String]]?
+ public var externalIds: [[String: String]]? {
+ _externalIds
+ }
+
+ public var dictionaryValue: [String: Any]? {
+ return self.dictionary
+ }
+
+ enum CodingKeys: String, CodingKey {
+ case _app = "app"
+ case _device = "device"
+ case _library = "library"
+ case _os = "os"
+ case _screen = "screen"
+ case _locale = "locale"
+ case _network = "network"
+ case _timezone = "timezone"
+ case _traits = "traits"
+ case _externalIds = "externalId"
+ }
+
+ static func locale() -> String {
+ if #available(macOS 13, iOS 16, tvOS 16, watchOS 9, *) {
+ return "\(Locale.current.language.languageCode?.identifier ?? "")-\(Locale.current.region?.identifier ?? "")"
+ } else {
+ return "\(Locale.current.languageCode ?? "")-\(Locale.current.regionCode ?? "")"
+ }
+ }
+
+ static func timezone() -> String {
+ return TimeZone.current.identifier
+ }
+
+ static func traits(userDefaults: RSUserDefaults) -> JSON? {
+ let traitsJSON: JSON? = userDefaults.read(.traits)
+ var traitsDict = traitsJSON?.dictionaryValue
+ if let userId: String = userDefaults.read(.userId) {
+ traitsDict?["userId"] = userId
+ }
+ if let anonymousId: String = userDefaults.read(.anonymousId) {
+ traitsDict?["anonymousId"] = anonymousId
+ }
+ if let traits = traitsDict {
+ return try? JSON(traits)
+ }
+ return nil
+ }
+
+ internal init(userDefaults: RSUserDefaults) {
+ _app = AppInfo()
+ _device = DeviceInfo()
+ _library = LibraryInfo()
+ _os = OSInfo()
+ _screen = ScreenInfo()
+ _locale = Self.locale()
+ _network = NetworkInfo()
+ _timezone = Self.timezone()
+ _traits = Self.traits(userDefaults: userDefaults)
+ _externalIds = userDefaults.read(.externalId)
+ }
+}
+
+public extension Encodable {
+ var dictionary: [String: Any]? {
+ guard let data = try? JSONEncoder().encode(self) else { return nil }
+ return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] }
+ }
+}
diff --git a/Sources/Classes/Domain/Models/RSOption.swift b/Sources/Classes/Domain/Models/RSOption.swift
index 3efb97fc..46dc6de3 100644
--- a/Sources/Classes/Domain/Models/RSOption.swift
+++ b/Sources/Classes/Domain/Models/RSOption.swift
@@ -23,11 +23,11 @@ open class RSOption: NSObject {
@objc
public func putExternalId(_ type: String, withId id: String) {
guard type.isNotEmpty else {
- RSClient.rsLog(message: "ExternalId type can not be empty", logLevel: .warning)
+ Logger.log(message: "ExternalId type can not be empty", logLevel: .warning)
return
}
guard id.isNotEmpty else {
- RSClient.rsLog(message: "External id can not be empty", logLevel: .warning)
+ Logger.log(message: "External id can not be empty", logLevel: .warning)
return
}
if externalIds == nil {
@@ -46,7 +46,7 @@ open class RSOption: NSObject {
@objc
public func putIntegration(_ type: String, isEnabled enabled: Bool) {
guard type.isNotEmpty else {
- RSClient.rsLog(message: "Integration type can not be empty", logLevel: .warning)
+ Logger.log(message: "Integration type can not be empty", logLevel: .warning)
return
}
integrations?[type] = enabled
@@ -55,7 +55,7 @@ open class RSOption: NSObject {
@objc
public func putCustomContext(_ context: [String: Any], withKey key: String) {
guard key.isNotEmpty else {
- RSClient.rsLog(message: "CustomContext key can not be empty", logLevel: .warning)
+ Logger.log(message: "CustomContext key can not be empty", logLevel: .warning)
return
}
if customContexts == nil {
diff --git a/Sources/Classes/Domain/Models/RSUserInfo.swift b/Sources/Classes/Domain/Models/RSUserInfo.swift
new file mode 100644
index 00000000..9c93741a
--- /dev/null
+++ b/Sources/Classes/Domain/Models/RSUserInfo.swift
@@ -0,0 +1,15 @@
+//
+// RSUserInfo.swift
+// Rudder
+//
+// Created by Pallab Maiti on 15/07/22.
+// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
+//
+
+import Foundation
+
+struct RSUserInfo {
+ var anonymousId: String?
+ var userId: String?
+ var traits: JSON?
+}
diff --git a/Sources/Classes/Domain/Protocols/RSConsoleLogger.swift b/Sources/Classes/Domain/Protocols/RSConsoleLogger.swift
deleted file mode 100644
index deb87872..00000000
--- a/Sources/Classes/Domain/Protocols/RSConsoleLogger.swift
+++ /dev/null
@@ -1,19 +0,0 @@
-//
-// RSConsoleLogger.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 24/02/22.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-class RSConsoleLogger: RSLogger {
- func parseLog(_ log: RSLogMessage) {
- var metadata = ""
- if let function = log.function, let line = log.line {
- metadata = " - \(function):\(line)"
- }
- print("\(TAG):\(log.logLevel.toString()):\(metadata):\(log.message)")
- }
-}
diff --git a/Sources/Classes/Domain/Protocols/RSLogger.swift b/Sources/Classes/Domain/Protocols/RSLogger.swift
deleted file mode 100644
index 2e8d3010..00000000
--- a/Sources/Classes/Domain/Protocols/RSLogger.swift
+++ /dev/null
@@ -1,136 +0,0 @@
-//
-// RSLogger.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 24/02/22.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-public protocol RSLogger {
- func parseLog(_ log: RSLogMessage)
-}
-
-public struct RSLoggingType: Hashable {
-
- public enum LogDestination {
- case log
- case metric
- }
-
- public static let log = RSLoggingType(types: [.log])
- public static let metric = RSLoggingType(types: [.metric])
-
- init(types: [LogDestination]) {
- self.allTypes = types
- }
-
- private let allTypes: [LogDestination]
- func contains(_ destination: LogDestination) -> Bool {
- return allTypes.contains(destination)
- }
-}
-
-public protocol RSLogMessage {
- var logLevel: RSLogLevel { get }
- var title: String? { get }
- var message: String { get }
- var event: RSMessage? { get }
- var function: String? { get }
- var line: Int? { get }
- var logType: RSLoggingType.LogDestination { get }
- var dateTime: Date { get }
-}
-
-public enum RSMetricType: Int {
- case counter = 0 // Not Verbose
- case gauge // Semi-verbose
-
- func toString() -> String {
- var typeString = "Gauge"
- if self == .counter {
- typeString = "Counter"
- }
- return typeString
- }
-
- static func fromString(_ string: String) -> Self {
- var returnType = Self.counter
- if string == "Gauge" {
- returnType = .gauge
- }
-
- return returnType
- }
-}
-
-// MARK: - Logging API
-
-extension RSClient {
-
- /// The logging method for capturing all general types of log messages related to RudderStack.
- /// - Parameters:
- /// - message: The main message of the log to be captured.
- /// - logLevel: Usually .error, .warning or .debug, in order of serverity. This helps filter logs based on this added metadata.
- /// - function: The name of the function the log came from. This will be captured automatically.
- /// - line: The line number in the function the log came from. This will be captured automatically.
- public func log(message: String, logLevel: RSLogLevel? = nil, function: String = #function, line: Int = #line) {
- apply { plugin in
- // Check if we should send off the event
- if RSLoggerPlugin.loggingEnabled == false {
- return
- }
- if let loggerPlugin = plugin as? RSLoggerPlugin {
- var filterKind = loggerPlugin.logLevel
- if let logKind = logLevel {
- filterKind = logKind
- }
-
- let log = LogFactory.buildLog(destination: .log, title: "", message: message, logLevel: filterKind, function: function, line: line)
- loggerPlugin.log(log, destination: .log)
- }
- }
- }
-
- /// The logging method for capturing metrics related to RudderStack or other libraries.
- /// - Parameters:
- /// - type: Metric type, usually .counter or .gauge. Select the one that makes sense for the metric.
- /// - name: The title of the metric to track.
- /// - value: The value associated with the metric. This would be an incrementing counter or time or pressure gauge.
- /// - tags: Any tags that should be associated with the metric. Any extra metadata that may help.
- public func metric(_ type: RSMetricType, name: String, value: Double, tags: [String]? = nil) {
- apply { plugin in
- // Check if we should send off the event
- if RSLoggerPlugin.loggingEnabled == false {
- return
- }
-
- if let loggerPlugin = plugin as? RSLoggerPlugin {
-
- let log = LogFactory.buildLog(destination: .metric, title: type.toString(), message: name, value: value, tags: tags)
- loggerPlugin.log(log, destination: .metric)
- }
- }
- }
-}
-
-extension RSClient {
- /// Add a logging target to the system. These `targets` can handle logs in various ways. Consider
- /// sending logs to the console, the OS and a web service. Three targets can handle these scenarios.
- /// - Parameters:
- /// - target: A `LogTarget` that has logic to parse and handle log messages.
- /// - type: The type consists of `log`, `metric` or `history`. These correspond to the
- /// public API on Analytics.
- public func add(target: RSLogger, type: RSLoggingType) {
- apply { (potentialLogger) in
- if let logger = potentialLogger as? RSLoggerPlugin {
- do {
- try logger.add(target: target, for: type)
- } catch {
- Self.rsLog(message: "Could not add target: \(error.localizedDescription)", logLevel: .error)
- }
- }
- }
- }
-}
diff --git a/Sources/Classes/Domain/Protocols/RSMessage.swift b/Sources/Classes/Domain/Protocols/RSMessage.swift
index 23d215b2..2b12be98 100644
--- a/Sources/Classes/Domain/Protocols/RSMessage.swift
+++ b/Sources/Classes/Domain/Protocols/RSMessage.swift
@@ -19,6 +19,8 @@ public protocol RSMessage {
var option: RSOption? { get set }
var channel: String? { get set }
var dictionaryValue: [String: Any] { get }
+ var sessionId: Int? { get set }
+ var sessionStart: Bool? { get set }
}
public struct TrackMessage: RSMessage {
@@ -31,6 +33,8 @@ public struct TrackMessage: RSMessage {
public var integrations: MessageIntegrations?
public var option: RSOption?
public var channel: String?
+ public var sessionId: Int?
+ public var sessionStart: Bool?
public let event: String
public let properties: TrackProperties?
@@ -63,6 +67,8 @@ public struct IdentifyMessage: RSMessage {
public var integrations: MessageIntegrations?
public var option: RSOption?
public var channel: String?
+ public var sessionId: Int?
+ public var sessionStart: Bool?
public var traits: IdentifyTraits?
@@ -93,7 +99,9 @@ public struct ScreenMessage: RSMessage {
public var integrations: MessageIntegrations?
public var option: RSOption?
public var channel: String?
-
+ public var sessionId: Int?
+ public var sessionStart: Bool?
+
public let name: String
public let category: String?
public let properties: ScreenProperties?
@@ -128,7 +136,9 @@ public struct GroupMessage: RSMessage {
public var integrations: MessageIntegrations?
public var option: RSOption?
public var channel: String?
-
+ public var sessionId: Int?
+ public var sessionStart: Bool?
+
public let groupId: String
public let traits: GroupTraits?
@@ -160,7 +170,9 @@ public struct AliasMessage: RSMessage {
public var integrations: MessageIntegrations?
public var option: RSOption?
public var channel: String?
-
+ public var sessionId: Int?
+ public var sessionStart: Bool?
+
public var previousId: String?
public var dictionaryValue: [String: Any] {
@@ -174,8 +186,9 @@ public struct AliasMessage: RSMessage {
dictionary["previousId"] = previousId
}
- init(newId: String, option: RSOption? = nil) {
+ init(newId: String, previousId: String?, option: RSOption? = nil) {
self.userId = newId
+ self.previousId = previousId
self.option = option
}
}
@@ -183,9 +196,34 @@ public struct AliasMessage: RSMessage {
// MARK: - RawEvent data helpers
extension RSMessage {
- internal func applyRawEventData() -> Self {
+ internal func applyRawEventData(userInfo: RSUserInfo?) -> Self {
var result: Self = self
- result.messageId = String(format: "%ld-%@", RSUtils.getTimeStamp(), RSUtils.getUniqueId())
+ result.context = MessageContext()
+ if let traits = userInfo?.traits?.dictionaryValue {
+ result.context?[keyPath: "traits"] = traits
+ }
+ if let userId = userInfo?.userId {
+ result.context?[keyPath: "traits.userId"] = userId
+ }
+ if let anonymousId = userInfo?.anonymousId {
+ result.context?[keyPath: "traits.anonymousId"] = anonymousId
+ }
+ /*var device = [String: Any]()
+ if let deviceToken: String = RSSessionStorage.shared.read(.deviceToken) {
+ device["token"] = deviceToken
+ }
+ if let advertisingId: String = RSSessionStorage.shared.read(.advertisingId), advertisingId.isNotEmpty {
+ device["advertisingId"] = advertisingId
+ device["adTrackingEnabled"] = true
+ let appTrackingConsent: RSAppTrackingConsent = RSSessionStorage.shared.read(.appTrackingConsent) ?? .notDetermined
+ device["attTrackingStatus"] = appTrackingConsent.rawValue
+ }
+ if !device.isEmpty {
+ result.context?["device"] = device
+ }*/
+ result.userId = userInfo?.userId
+ result.anonymousId = userInfo?.anonymousId
+ result.messageId = RSUtils.getUniqueId()
result.timestamp = RSUtils.getTimestampString()
result.channel = "mobile"
return result
diff --git a/Sources/Classes/Helpers/Logger.swift b/Sources/Classes/Helpers/Logger.swift
new file mode 100644
index 00000000..4e5c1053
--- /dev/null
+++ b/Sources/Classes/Helpers/Logger.swift
@@ -0,0 +1,68 @@
+//
+// Logger.swift
+// Rudder
+//
+// Created by Pallab Maiti on 27/11/23.
+// Copyright © 2023 Rudder Labs India Pvt Ltd. All rights reserved.
+//
+
+import Foundation
+
+@frozen @objc public enum RSLogLevel: Int {
+ case verbose = 5
+ case debug = 4
+ case info = 3
+ case warning = 2
+ case error = 1
+ case none = 0
+
+ public func toString() -> String {
+ switch self {
+ case .verbose:
+ return "Verbose"
+ case .debug:
+ return "Debug"
+ case .info:
+ return "Info"
+ case .warning:
+ return "Warning"
+ case .error:
+ return "Error"
+ case .none:
+ return ""
+ }
+ }
+}
+
+class Logger {
+ static var logLevel: RSLogLevel = .error
+
+ static func logDebug(_ message: String, function: String = #function, line: Int = #line) {
+ log(message: message, logLevel: .debug, function: function, line: line)
+ }
+
+ static func logInfo(_ message: String, function: String = #function, line: Int = #line) {
+ log(message: message, logLevel: .info, function: function, line: line)
+ }
+
+ static func logWarning(_ message: String, function: String = #function, line: Int = #line) {
+ log(message: message, logLevel: .warning, function: function, line: line)
+ }
+
+ static func logError(_ message: String, function: String = #function, line: Int = #line) {
+ log(message: message, logLevel: .error, function: function, line: line)
+ }
+
+ static func log(message: String, logLevel: RSLogLevel, function: String = #function, line: Int = #line) {
+ if self.logLevel == .verbose || self.logLevel == logLevel {
+ let metadata = " - \(function):\(line):"
+ print("RudderStack:\(logLevel.toString()):\(metadata)\(message)")
+ }
+ }
+}
+
+extension RSClient {
+ public func log(message: String, logLevel: RSLogLevel) {
+ Logger.log(message: message, logLevel: logLevel)
+ }
+}
diff --git a/Sources/Classes/Helpers/Platforms/Mac/RSmacOSLifecycleEvents.swift b/Sources/Classes/Helpers/Platforms/Mac/RSmacOSLifecycleEvents.swift
index 4fd727a9..d12d5270 100644
--- a/Sources/Classes/Helpers/Platforms/Mac/RSmacOSLifecycleEvents.swift
+++ b/Sources/Classes/Helpers/Platforms/Mac/RSmacOSLifecycleEvents.swift
@@ -11,13 +11,62 @@ import Foundation
class RSmacOSLifecycleEvents: RSPlatformPlugin, RSmacOSLifecycle {
let type = PluginType.before
- var client: RSClient?
+ var client: RSClient? {
+ didSet {
+ initialSetup()
+ }
+ }
@RSAtomic private var didFinishLaunching = false
@RSAtomic private var fromBackground = false
-
+ private var userDefaults: RSUserDefaults?
+ private var config: RSConfig?
+
+ internal func initialSetup() {
+ guard let client = self.client else { return }
+ userDefaults = client.userDefaults
+ config = client.config
+ }
+
+ func application(didFinishLaunchingWithOptions launchOptions: [String: Any]?) {
+ didFinishLaunching = true
+
+ if config?.trackLifecycleEvents == false {
+ return
+ }
+
+ let previousVersion: String? = userDefaults?.read(application: .version)
+ let previousBuild: String? = userDefaults?.read(application: .build)
+
+ let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
+ let currentBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
+
+ if previousVersion == nil {
+ client?.track("Application Installed", properties: RSUtils.getLifeCycleProperties(
+ currentVersion: currentVersion,
+ currentBuild: currentBuild
+ ))
+ } else if currentVersion != previousVersion {
+ client?.track("Application Updated", properties: RSUtils.getLifeCycleProperties(
+ previousVersion: previousVersion,
+ previousBuild: previousBuild,
+ currentVersion: currentVersion,
+ currentBuild: currentBuild
+ ))
+ }
+
+ client?.track("Application Opened", properties: RSUtils.getLifeCycleProperties(
+ currentVersion: currentVersion,
+ currentBuild: currentBuild,
+ fromBackground: false
+ ))
+
+ userDefaults?.write(application: .version, value: currentVersion)
+ userDefaults?.write(application: .build, value: currentBuild)
+ }
+
func applicationDidBecomeActive() {
- if client?.config?.trackLifecycleEvents == false {
+ if config?.trackLifecycleEvents == false {
return
}
@@ -27,8 +76,8 @@ class RSmacOSLifecycleEvents: RSPlatformPlugin, RSmacOSLifecycle {
if didFinishLaunching == false {
didFinishLaunching = true
- let previousVersion = RSUserDefaults.getApplicationVersion()
- let previousBuild = RSUserDefaults.getApplicationBuild()
+ let previousVersion: String? = userDefaults?.read(application: .version)
+ let previousBuild: String? = userDefaults?.read(application: .build)
if previousVersion == nil {
client?.track("Application Installed", properties: RSUtils.getLifeCycleProperties(
@@ -44,8 +93,8 @@ class RSmacOSLifecycleEvents: RSPlatformPlugin, RSmacOSLifecycle {
))
}
- RSUserDefaults.saveApplicationVersion(currentVersion)
- RSUserDefaults.saveApplicationBuild(currentBuild)
+ userDefaults?.write(application: .version, value: currentVersion)
+ userDefaults?.write(application: .build, value: currentBuild)
}
if fromBackground {
@@ -71,7 +120,7 @@ class RSmacOSLifecycleEvents: RSPlatformPlugin, RSmacOSLifecycle {
}
func applicationWillTerminate() {
- if client?.config?.trackLifecycleEvents == false {
+ if config?.trackLifecycleEvents == false {
return
}
diff --git a/Sources/Classes/Helpers/Platforms/Mac/RSmacOSScreenViewEvents.swift b/Sources/Classes/Helpers/Platforms/Mac/RSmacOSScreenViewEvents.swift
index eb327e06..ed139821 100644
--- a/Sources/Classes/Helpers/Platforms/Mac/RSmacOSScreenViewEvents.swift
+++ b/Sources/Classes/Helpers/Platforms/Mac/RSmacOSScreenViewEvents.swift
@@ -27,6 +27,8 @@ class RSmacOSScreenViewEvents: RSPlatformPlugin {
}
extension NSViewController {
+ static var client: RSClient?
+
static func rudderSwizzleView() {
let originalSelector = #selector(self.viewDidAppear)
let swizzledSelector = #selector(self.rsViewDidAppear)
@@ -45,27 +47,10 @@ extension NSViewController {
func rsViewDidAppear() {
var name = NSStringFromClass(type(of: self))
name = name.replacingOccurrences(of: "ViewController", with: "")
- let screenMessage = ScreenMessage(title: name, properties: ["automatic": true, "name": name])
+ let screenMessage = ScreenMessage(title: name, properties: ["automatic": true, "name": name]).applyRawEventData(userInfo: NSViewController.client?.userInfo)
NSViewController.client?.process(message: screenMessage)
rsViewDidAppear()
}
}
-extension NSViewController {
- private struct AssociatedKey {
- static var client: RSClient?
- }
-
- static var client: RSClient? {
- get {
- return objc_getAssociatedObject(self, &AssociatedKey.client) as? RSClient
- }
- set {
- if let value = newValue {
- objc_setAssociatedObject(self, &AssociatedKey.client, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- }
- }
- }
-}
-
#endif
diff --git a/Sources/Classes/Helpers/Platforms/Vendors/AppleUtils.swift b/Sources/Classes/Helpers/Platforms/Vendors/AppleUtils.swift
index ae15a9e9..74c39ac3 100644
--- a/Sources/Classes/Helpers/Platforms/Vendors/AppleUtils.swift
+++ b/Sources/Classes/Helpers/Platforms/Vendors/AppleUtils.swift
@@ -28,15 +28,19 @@ internal class PhoneVendor: Vendor {
}
override var type: String {
-#if os(iOS)
- return "ios"
-#elseif os(tvOS)
- return "tvos"
-#elseif targetEnvironment(macCatalyst)
- return "macos"
-#else
+ #if os(iOS)
+ if UIDevice.current.userInterfaceIdiom == .pad {
+ return "iPadOS"
+ } else {
+ return "iOS"
+ }
+ #elseif os(tvOS)
+ return "tvOS"
+ #elseif targetEnvironment(macCatalyst)
+ return "macOS"
+ #else
return "unknown"
-#endif
+ #endif
}
override var model: String {
@@ -46,11 +50,11 @@ internal class PhoneVendor: Vendor {
override var name: String {
// eg. "iPod Touch"
- return device.model
+ return device.name
}
override var identifierForVendor: String? {
- return device.identifierForVendor?.uuidString
+ return device.identifierForVendor?.uuidString.lowercased()
}
override var systemName: String {
@@ -71,12 +75,12 @@ internal class PhoneVendor: Vendor {
}
override var requiredPlugins: [RSPlatformPlugin] {
- return [RSiOSLifecycleMonitor(), RSDeviceTokenPlugin()]
+ return [RSiOSLifecycleMonitor()]
}
override var carrier: String {
#if os(iOS)
- return retrieveCarrierNames() ?? "unavailable";
+ return retrieveCarrierNames() ?? "unavailable"
#else
return "unavailable"
#endif
@@ -85,34 +89,23 @@ internal class PhoneVendor: Vendor {
#if os(iOS)
func retrieveCarrierNames() -> String? {
- let systemVersion = UIDevice.current.systemVersion
- let versionComponents = systemVersion.split(separator: ".").compactMap { Int($0) }
- if versionComponents.count > 0 {
- let majorVersion = versionComponents[0]
+ if #available(iOS 16, *) {
+ Logger.log(message: "Unable to retrieve carrier name as the iOS version is >= 16", logLevel: .warning)
+ return nil
+ } else {
+ let networkInfo = CTTelephonyNetworkInfo()
+ var carrierNames: [String] = []
- if majorVersion >= 16 {
- RSClient.rsLog(message: "Unable to retrieve carrier name as the iOS version is >= 16", logLevel: .warning)
- return nil
- } else if majorVersion >= 12 && majorVersion < 16 {
- let networkInfo = CTTelephonyNetworkInfo()
- var carrierNames: [String] = []
-
- if let carriers = networkInfo.serviceSubscriberCellularProviders?.values {
- for carrierObj in carriers {
- if let carrierName = carrierObj.carrierName, carrierName != "--" {
- carrierNames.append(carrierName)
- }
+ if let carriers = networkInfo.serviceSubscriberCellularProviders?.values {
+ for carrierObj in carriers {
+ if let carrierName = carrierObj.carrierName, carrierName != "--" {
+ carrierNames.append(carrierName)
}
}
- if(!carrierNames.isEmpty) {
- let formattedCarrierNames = carrierNames.joined(separator: ", ")
- return formattedCarrierNames
- }
- } else {
- let networkInfo = CTTelephonyNetworkInfo()
- if let carrier = networkInfo.subscriberCellularProvider?.carrierName, carrier != "--" {
- return carrier
- }
+ }
+ if !carrierNames.isEmpty {
+ let formattedCarrierNames = carrierNames.joined(separator: ", ")
+ return formattedCarrierNames
}
}
return nil
@@ -147,7 +140,7 @@ internal class WatchVendor: Vendor {
}
override var type: String {
- return "watchos"
+ return "watchOS"
}
override var model: String {
@@ -155,11 +148,11 @@ internal class WatchVendor: Vendor {
}
override var name: String {
- return device.model
+ return device.name
}
override var identifierForVendor: String? {
- return device.identifierForVendor?.uuidString
+ return device.identifierForVendor?.uuidString.lowercased()
}
override var systemName: String {
@@ -229,7 +222,7 @@ internal class MacVendor: Vendor {
}
override var type: String {
- return "macos"
+ return "macOS"
}
override var model: String {
@@ -241,9 +234,7 @@ internal class MacVendor: Vendor {
}
override var identifierForVendor: String? {
- // apple suggested to use this for receipt validation
- // in MAS, works for this too.
- return macAddress(bsd: "en0")
+ return macAddress(bsd: "en0")?.lowercased()
}
override var systemName: String {
@@ -267,7 +258,7 @@ internal class MacVendor: Vendor {
}
override var requiredPlugins: [RSPlatformPlugin] {
- return [RSmacOSLifecycleMonitor(), RSDeviceTokenPlugin()]
+ return [RSmacOSLifecycleMonitor()]
}
private func deviceModel() -> String {
diff --git a/Sources/Classes/Helpers/Platforms/iOS/RSiOSLifecycleEvents.swift b/Sources/Classes/Helpers/Platforms/iOS/RSiOSLifecycleEvents.swift
index ffa664aa..5a74e1ae 100644
--- a/Sources/Classes/Helpers/Platforms/iOS/RSiOSLifecycleEvents.swift
+++ b/Sources/Classes/Helpers/Platforms/iOS/RSiOSLifecycleEvents.swift
@@ -14,20 +14,32 @@ import UIKit
class RSiOSLifecycleEvents: RSPlatformPlugin, RSiOSLifecycle {
let type = PluginType.before
- var client: RSClient?
- var isFirstTimeLaunch: Bool = true
+ var client: RSClient? {
+ didSet {
+ initialSetup()
+ }
+ }
+ var isFirstTimeLaunch: Bool = true
@RSAtomic private var didFinishLaunching = false
+ private var userDefaults: RSUserDefaults?
+ private var config: RSConfig?
+
+ internal func initialSetup() {
+ guard let client = self.client else { return }
+ userDefaults = client.userDefaults
+ config = client.config
+ }
func application(_ application: UIApplication?, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
didFinishLaunching = true
- if client?.config?.trackLifecycleEvents == false {
+ if config?.trackLifecycleEvents == false {
return
}
- let previousVersion = RSUserDefaults.getApplicationVersion()
- let previousBuild = RSUserDefaults.getApplicationBuild()
+ let previousVersion: String? = userDefaults?.read(application: .version)
+ let previousBuild: String? = userDefaults?.read(application: .build)
let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
let currentBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
@@ -54,12 +66,12 @@ class RSiOSLifecycleEvents: RSPlatformPlugin, RSiOSLifecycle {
url: launchOptions?[UIApplication.LaunchOptionsKey.url]
))
- RSUserDefaults.saveApplicationVersion(currentVersion)
- RSUserDefaults.saveApplicationBuild(currentBuild)
+ userDefaults?.write(application: .version, value: currentVersion)
+ userDefaults?.write(application: .build, value: currentBuild)
}
func applicationWillEnterForeground(application: UIApplication?) {
- if client?.config?.trackLifecycleEvents == false {
+ if config?.trackLifecycleEvents == false {
return
}
#if !os(tvOS)
@@ -83,7 +95,7 @@ class RSiOSLifecycleEvents: RSPlatformPlugin, RSiOSLifecycle {
}
func applicationDidEnterBackground(application: UIApplication?) {
- if client?.config?.trackLifecycleEvents == false {
+ if config?.trackLifecycleEvents == false {
return
}
@@ -91,7 +103,7 @@ class RSiOSLifecycleEvents: RSPlatformPlugin, RSiOSLifecycle {
}
func applicationDidBecomeActive(application: UIApplication?) {
- if client?.config?.trackLifecycleEvents == false {
+ if config?.trackLifecycleEvents == false {
return
}
diff --git a/Sources/Classes/Helpers/Platforms/iOS/RSiOSLifecycleMonitor.swift b/Sources/Classes/Helpers/Platforms/iOS/RSiOSLifecycleMonitor.swift
index 3a5c6d83..b5b71463 100644
--- a/Sources/Classes/Helpers/Platforms/iOS/RSiOSLifecycleMonitor.swift
+++ b/Sources/Classes/Helpers/Platforms/iOS/RSiOSLifecycleMonitor.swift
@@ -13,7 +13,7 @@ import UIKit
class RSiOSLifecycleMonitor: RSPlatformPlugin {
let type = PluginType.utility
- var client: RSClient?
+ weak var client: RSClient?
private var application: UIApplication = UIApplication.shared
private var appNotifications: [NSNotification.Name] = [UIApplication.didEnterBackgroundNotification,
@@ -35,23 +35,23 @@ class RSiOSLifecycleMonitor: RSPlatformPlugin {
func notificationResponse(notification: NSNotification) {
switch notification.name {
case UIApplication.didEnterBackgroundNotification:
- self.didEnterBackground(notification: notification)
+ didEnterBackground(notification: notification)
case UIApplication.willEnterForegroundNotification:
- self.applicationWillEnterForeground(notification: notification)
+ applicationWillEnterForeground(notification: notification)
case UIApplication.didFinishLaunchingNotification:
- self.didFinishLaunching(notification: notification)
+ didFinishLaunching(notification: notification)
case UIApplication.didBecomeActiveNotification:
- self.didBecomeActive(notification: notification)
+ didBecomeActive(notification: notification)
case UIApplication.willResignActiveNotification:
- self.willResignActive(notification: notification)
+ willResignActive(notification: notification)
case UIApplication.didReceiveMemoryWarningNotification:
- self.didReceiveMemoryWarning(notification: notification)
+ didReceiveMemoryWarning(notification: notification)
case UIApplication.significantTimeChangeNotification:
- self.significantTimeChange(notification: notification)
+ significantTimeChange(notification: notification)
case UIApplication.backgroundRefreshStatusDidChangeNotification:
- self.backgroundRefreshDidChange(notification: notification)
+ backgroundRefreshDidChange(notification: notification)
case UIApplication.willTerminateNotification:
- self.willTerminate(notification: notification)
+ willTerminate(notification: notification)
default:
break
diff --git a/Sources/Classes/Helpers/Platforms/iOS/RSiOSScreenViewEvents.swift b/Sources/Classes/Helpers/Platforms/iOS/RSiOSScreenViewEvents.swift
index 4877c729..762c6cfe 100644
--- a/Sources/Classes/Helpers/Platforms/iOS/RSiOSScreenViewEvents.swift
+++ b/Sources/Classes/Helpers/Platforms/iOS/RSiOSScreenViewEvents.swift
@@ -26,6 +26,8 @@ class RSiOSScreenViewEvents: RSPlatformPlugin {
}
extension UIViewController {
+ static var client: RSClient?
+
static func rudderSwizzleView() {
let originalSelector = #selector(viewDidAppear(_:))
let swizzledSelector = #selector(rsViewDidAppear(_:))
@@ -44,27 +46,10 @@ extension UIViewController {
func rsViewDidAppear(_ animated: Bool) {
var name = NSStringFromClass(type(of: self))
name = name.replacingOccurrences(of: "ViewController", with: "")
- let screenMessage = ScreenMessage(title: name, properties: ["automatic": true, "name": name])
+ let screenMessage = ScreenMessage(title: name, properties: ["automatic": true, "name": name]).applyRawEventData(userInfo: UIViewController.client?.userInfo)
UIViewController.client?.process(message: screenMessage)
rsViewDidAppear(animated)
}
}
-extension UIViewController {
- private struct AssociatedKey {
- static var client: RSClient?
- }
-
- static var client: RSClient? {
- get {
- return objc_getAssociatedObject(self, &AssociatedKey.client) as? RSClient
- }
- set {
- if let value = newValue {
- objc_setAssociatedObject(self, &AssociatedKey.client, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- }
- }
- }
-}
-
#endif
diff --git a/Sources/Classes/Helpers/Platforms/watchOS/RSwatchOSLifecycleEvents.swift b/Sources/Classes/Helpers/Platforms/watchOS/RSwatchOSLifecycleEvents.swift
index 56e6fc8f..95d2f7fe 100644
--- a/Sources/Classes/Helpers/Platforms/watchOS/RSwatchOSLifecycleEvents.swift
+++ b/Sources/Classes/Helpers/Platforms/watchOS/RSwatchOSLifecycleEvents.swift
@@ -13,15 +13,28 @@ import WatchKit
class RSwatchOSLifecycleEvents: RSPlatformPlugin, RSwatchOSLifecycle {
let type = PluginType.before
- var client: RSClient?
+ var client: RSClient? {
+ didSet {
+ initialSetup()
+ }
+ }
+
+ private var userDefaults: RSUserDefaults?
+ private var config: RSConfig?
+
+ internal func initialSetup() {
+ guard let client = self.client else { return }
+ userDefaults = client.userDefaults
+ config = client.config
+ }
func applicationDidFinishLaunching(watchExtension: WKExtension?) {
- if client?.config?.trackLifecycleEvents == false {
+ if config?.trackLifecycleEvents == false {
return
}
- let previousVersion = RSUserDefaults.getApplicationVersion()
- let previousBuild = RSUserDefaults.getApplicationBuild()
+ let previousVersion: String? = userDefaults?.read(application: .version)
+ let previousBuild: String? = userDefaults?.read(application: .build)
let currentVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
let currentBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String
@@ -46,12 +59,12 @@ class RSwatchOSLifecycleEvents: RSPlatformPlugin, RSwatchOSLifecycle {
fromBackground: false
))
- RSUserDefaults.saveApplicationVersion(currentVersion)
- RSUserDefaults.saveApplicationBuild(currentBuild)
+ userDefaults?.write(application: .version, value: currentVersion)
+ userDefaults?.write(application: .build, value: currentBuild)
}
func applicationWillEnterForeground(watchExtension: WKExtension?) {
- if client?.config?.trackLifecycleEvents == false {
+ if config?.trackLifecycleEvents == false {
return
}
diff --git a/Sources/Classes/Helpers/Platforms/watchOS/RSwatchOSScreenViewEvents.swift b/Sources/Classes/Helpers/Platforms/watchOS/RSwatchOSScreenViewEvents.swift
index 88f1ccee..19897d4d 100644
--- a/Sources/Classes/Helpers/Platforms/watchOS/RSwatchOSScreenViewEvents.swift
+++ b/Sources/Classes/Helpers/Platforms/watchOS/RSwatchOSScreenViewEvents.swift
@@ -25,6 +25,8 @@ class RSwatchOSScreenViewEvents: RSPlatformPlugin {
}
}
extension WKInterfaceController {
+ static var client: RSClient?
+
static func rudderSwizzleView() {
let originalSelector = #selector(didAppear)
let swizzledSelector = #selector(rsDidAppear)
@@ -43,27 +45,10 @@ extension WKInterfaceController {
func rsDidAppear() {
var name = NSStringFromClass(Swift.type(of: self))
name = name.replacingOccurrences(of: "InterfaceController", with: "")
- let screenMessage = ScreenMessage(title: name, properties: ["automatic": true, "name": name])
+ let screenMessage = ScreenMessage(title: name, properties: ["automatic": true, "name": name]).applyRawEventData(userInfo: WKInterfaceController.client?.userInfo)
WKInterfaceController.client?.process(message: screenMessage)
rsDidAppear()
}
}
-extension WKInterfaceController {
- private struct AssociatedKey {
- static var client: RSClient?
- }
-
- static var client: RSClient? {
- get {
- return objc_getAssociatedObject(self, &AssociatedKey.client) as? RSClient
- }
- set {
- if let value = newValue {
- objc_setAssociatedObject(self, &AssociatedKey.client, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
- }
- }
- }
-}
-
#endif
diff --git a/Sources/Classes/Helpers/RSAnyCodable.swift b/Sources/Classes/Helpers/RSAnyCodable.swift
deleted file mode 100644
index 04e269fc..00000000
--- a/Sources/Classes/Helpers/RSAnyCodable.swift
+++ /dev/null
@@ -1,137 +0,0 @@
-//
-// RSAnyCodable.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 16/11/21.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import Foundation
-
-// swiftlint:disable cyclomatic_complexity
-
-@frozen public struct RSAnyCodable: Codable {
- public let value: Any
-
- public init(_ value: T?) {
- self.value = value ?? ()
- }
-}
-
-extension RSAnyCodable: _RSAnyEncodable, _RSAnyDecodable {}
-
-extension RSAnyCodable: Equatable {
- public static func == (lhs: RSAnyCodable, rhs: RSAnyCodable) -> Bool {
- switch (lhs.value, rhs.value) {
- case is (Void, Void):
- return true
- case let (lhs as Bool, rhs as Bool):
- return lhs == rhs
- case let (lhs as Int, rhs as Int):
- return lhs == rhs
- case let (lhs as Int8, rhs as Int8):
- return lhs == rhs
- case let (lhs as Int16, rhs as Int16):
- return lhs == rhs
- case let (lhs as Int32, rhs as Int32):
- return lhs == rhs
- case let (lhs as Int64, rhs as Int64):
- return lhs == rhs
- case let (lhs as UInt, rhs as UInt):
- return lhs == rhs
- case let (lhs as UInt8, rhs as UInt8):
- return lhs == rhs
- case let (lhs as UInt16, rhs as UInt16):
- return lhs == rhs
- case let (lhs as UInt32, rhs as UInt32):
- return lhs == rhs
- case let (lhs as UInt64, rhs as UInt64):
- return lhs == rhs
- case let (lhs as Float, rhs as Float):
- return lhs == rhs
- case let (lhs as Double, rhs as Double):
- return lhs == rhs
- case let (lhs as String, rhs as String):
- return lhs == rhs
- case let (lhs as [String: RSAnyCodable], rhs as [String: RSAnyCodable]):
- return lhs == rhs
- case let (lhs as [RSAnyCodable], rhs as [RSAnyCodable]):
- return lhs == rhs
- default:
- return false
- }
- }
-}
-
-extension RSAnyCodable: CustomStringConvertible {
- public var description: String {
- switch value {
- case is Void:
- return String(describing: nil as Any?)
- case let value as CustomStringConvertible:
- return value.description
- default:
- return String(describing: value)
- }
- }
-}
-
-extension RSAnyCodable: CustomDebugStringConvertible {
- public var debugDescription: String {
- switch value {
- case let value as CustomDebugStringConvertible:
- return "AnyCodable(\(value.debugDescription))"
- default:
- return "AnyCodable(\(description))"
- }
- }
-}
-
-extension RSAnyCodable: ExpressibleByNilLiteral {}
-extension RSAnyCodable: ExpressibleByBooleanLiteral {}
-extension RSAnyCodable: ExpressibleByIntegerLiteral {}
-extension RSAnyCodable: ExpressibleByFloatLiteral {}
-extension RSAnyCodable: ExpressibleByStringLiteral {}
-extension RSAnyCodable: ExpressibleByArrayLiteral {}
-extension RSAnyCodable: ExpressibleByDictionaryLiteral {}
-
-extension RSAnyCodable: Hashable {
- public func hash(into hasher: inout Hasher) {
- switch value {
- case let value as Bool:
- hasher.combine(value)
- case let value as Int:
- hasher.combine(value)
- case let value as Int8:
- hasher.combine(value)
- case let value as Int16:
- hasher.combine(value)
- case let value as Int32:
- hasher.combine(value)
- case let value as Int64:
- hasher.combine(value)
- case let value as UInt:
- hasher.combine(value)
- case let value as UInt8:
- hasher.combine(value)
- case let value as UInt16:
- hasher.combine(value)
- case let value as UInt32:
- hasher.combine(value)
- case let value as UInt64:
- hasher.combine(value)
- case let value as Float:
- hasher.combine(value)
- case let value as Double:
- hasher.combine(value)
- case let value as String:
- hasher.combine(value)
- case let value as [String: RSAnyCodable]:
- hasher.combine(value)
- case let value as [RSAnyCodable]:
- hasher.combine(value)
- default:
- break
- }
- }
-}
diff --git a/Sources/Classes/Helpers/RSAnyDecodable.swift b/Sources/Classes/Helpers/RSAnyDecodable.swift
deleted file mode 100644
index 31ff5d09..00000000
--- a/Sources/Classes/Helpers/RSAnyDecodable.swift
+++ /dev/null
@@ -1,170 +0,0 @@
-//
-// RSAnyDecodable.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 17/11/21.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-#if canImport(Foundation)
-import Foundation
-#endif
-
-// swiftlint:disable cyclomatic_complexity
-// swiftlint:disable type_name
-
-@frozen public struct RSAnyDecodable: Decodable {
- public let value: Any
-
- public init(_ value: T?) {
- self.value = value ?? ()
- }
-}
-
-@usableFromInline
-protocol _RSAnyDecodable {
- var value: Any { get }
- init(_ value: T?)
-}
-
-extension RSAnyDecodable: _RSAnyDecodable {}
-
-extension _RSAnyDecodable {
- public init(from decoder: Decoder) throws {
- let container = try decoder.singleValueContainer()
-
- if container.decodeNil() {
- #if canImport(Foundation)
- self.init(NSNull())
- #else
- self.init(self?)
- #endif
- } else if let bool = try? container.decode(Bool.self) {
- self.init(bool)
- } else if let int = try? container.decode(Int.self) {
- self.init(int)
- } else if let uint = try? container.decode(UInt.self) {
- self.init(uint)
- } else if let double = try? container.decode(Double.self) {
- self.init(double)
- } else if let string = try? container.decode(String.self) {
- self.init(string)
- } else if let array = try? container.decode([RSAnyDecodable].self) {
- self.init(array.map { $0.value })
- } else if let dictionary = try? container.decode([String: RSAnyDecodable].self) {
- self.init(dictionary.mapValues { $0.value })
- } else {
- throw DecodingError.dataCorruptedError(in: container, debugDescription: "AnyDecodable value cannot be decoded")
- }
- }
-}
-
-extension RSAnyDecodable: Equatable {
- public static func == (lhs: RSAnyDecodable, rhs: RSAnyDecodable) -> Bool {
- switch (lhs.value, rhs.value) {
-#if canImport(Foundation)
- case is (NSNull, NSNull), is (Void, Void):
- return true
-#endif
- case let (lhs as Bool, rhs as Bool):
- return lhs == rhs
- case let (lhs as Int, rhs as Int):
- return lhs == rhs
- case let (lhs as Int8, rhs as Int8):
- return lhs == rhs
- case let (lhs as Int16, rhs as Int16):
- return lhs == rhs
- case let (lhs as Int32, rhs as Int32):
- return lhs == rhs
- case let (lhs as Int64, rhs as Int64):
- return lhs == rhs
- case let (lhs as UInt, rhs as UInt):
- return lhs == rhs
- case let (lhs as UInt8, rhs as UInt8):
- return lhs == rhs
- case let (lhs as UInt16, rhs as UInt16):
- return lhs == rhs
- case let (lhs as UInt32, rhs as UInt32):
- return lhs == rhs
- case let (lhs as UInt64, rhs as UInt64):
- return lhs == rhs
- case let (lhs as Float, rhs as Float):
- return lhs == rhs
- case let (lhs as Double, rhs as Double):
- return lhs == rhs
- case let (lhs as String, rhs as String):
- return lhs == rhs
- case let (lhs as [String: RSAnyDecodable], rhs as [String: RSAnyDecodable]):
- return lhs == rhs
- case let (lhs as [RSAnyDecodable], rhs as [RSAnyDecodable]):
- return lhs == rhs
- default:
- return false
- }
- }
-}
-
-extension RSAnyDecodable: CustomStringConvertible {
- public var description: String {
- switch value {
- case is Void:
- return String(describing: nil as Any?)
- case let value as CustomStringConvertible:
- return value.description
- default:
- return String(describing: value)
- }
- }
-}
-
-extension RSAnyDecodable: CustomDebugStringConvertible {
- public var debugDescription: String {
- switch value {
- case let value as CustomDebugStringConvertible:
- return "AnyDecodable(\(value.debugDescription))"
- default:
- return "AnyDecodable(\(description))"
- }
- }
-}
-
-extension RSAnyDecodable: Hashable {
- public func hash(into hasher: inout Hasher) {
- switch value {
- case let value as Bool:
- hasher.combine(value)
- case let value as Int:
- hasher.combine(value)
- case let value as Int8:
- hasher.combine(value)
- case let value as Int16:
- hasher.combine(value)
- case let value as Int32:
- hasher.combine(value)
- case let value as Int64:
- hasher.combine(value)
- case let value as UInt:
- hasher.combine(value)
- case let value as UInt8:
- hasher.combine(value)
- case let value as UInt16:
- hasher.combine(value)
- case let value as UInt32:
- hasher.combine(value)
- case let value as UInt64:
- hasher.combine(value)
- case let value as Float:
- hasher.combine(value)
- case let value as Double:
- hasher.combine(value)
- case let value as String:
- hasher.combine(value)
- case let value as [String: RSAnyDecodable]:
- hasher.combine(value)
- case let value as [RSAnyDecodable]:
- hasher.combine(value)
- default:
- break
- }
- }
-}
diff --git a/Sources/Classes/Helpers/RSAnyEncodable.swift b/Sources/Classes/Helpers/RSAnyEncodable.swift
deleted file mode 100644
index 2fc41790..00000000
--- a/Sources/Classes/Helpers/RSAnyEncodable.swift
+++ /dev/null
@@ -1,275 +0,0 @@
-//
-// RSAnyEncodable.swift
-// RudderStack
-//
-// Created by Pallab Maiti on 17/11/21.
-// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-#if canImport(Foundation)
-import Foundation
-#endif
-
-// swiftlint:disable cyclomatic_complexity
-// swiftlint:disable function_body_length
-// swiftlint:disable type_name
-
-@frozen public struct RSAnyEncodable: Encodable {
- public let value: Any
-
- public init(_ value: T?) {
- self.value = value ?? ()
- }
-}
-
-@usableFromInline
-protocol _RSAnyEncodable {
- var value: Any { get }
- init(_ value: T?)
-}
-
-extension RSAnyEncodable: _RSAnyEncodable {}
-
-// MARK: - Encodable
-extension _RSAnyEncodable {
- public func encode(to encoder: Encoder) throws {
- var container = encoder.singleValueContainer()
-
- switch value {
- #if canImport(Foundation)
- case let number as NSNumber:
- try encode(nsnumber: number, into: &container)
- case is NSNull:
- try container.encodeNil()
- #endif
- case is Void:
- try container.encodeNil()
- case let bool as Bool:
- try container.encode(bool)
- case let int as Int:
- try container.encode(int)
- case let int8 as Int8:
- try container.encode(int8)
- case let int16 as Int16:
- try container.encode(int16)
- case let int32 as Int32:
- try container.encode(int32)
- case let int64 as Int64:
- try container.encode(int64)
- case let uint as UInt:
- try container.encode(uint)
- case let uint8 as UInt8:
- try container.encode(uint8)
- case let uint16 as UInt16:
- try container.encode(uint16)
- case let uint32 as UInt32:
- try container.encode(uint32)
- case let uint64 as UInt64:
- try container.encode(uint64)
- case let float as Float:
- try container.encode(float)
- case let double as Double:
- try container.encode(double)
- case let string as String:
- try container.encode(string)
- #if canImport(Foundation)
- case let date as Date:
- try container.encode(date)
- case let url as URL:
- try container.encode(url)
- #endif
- case let array as [Any?]:
- try container.encode(array.map { RSAnyEncodable($0) })
- case let dictionary as [String: Any?]:
- try container.encode(dictionary.mapValues { RSAnyEncodable($0) })
- case let encodable as Encodable:
- try encodable.encode(to: encoder)
- default:
- let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "AnyEncodable value cannot be encoded")
- throw EncodingError.invalidValue(value, context)
- }
- }
-
- #if canImport(Foundation)
- private func encode(nsnumber: NSNumber, into container: inout SingleValueEncodingContainer) throws {
- switch Character(Unicode.Scalar(UInt8(nsnumber.objCType.pointee))) {
- case "c", "C":
- try container.encode(nsnumber.boolValue)
- case "s":
- try container.encode(nsnumber.int8Value)
- case "i":
- try container.encode(nsnumber.int16Value)
- case "l":
- try container.encode(nsnumber.int32Value)
- case "q":
- try container.encode(nsnumber.int64Value)
- case "S":
- try container.encode(nsnumber.uint8Value)
- case "I":
- try container.encode(nsnumber.uint16Value)
- case "L":
- try container.encode(nsnumber.uint32Value)
- case "Q":
- try container.encode(nsnumber.uint64Value)
- case "f":
- try container.encode(nsnumber.floatValue)
- case "d":
- try container.encode(nsnumber.doubleValue)
- default:
- let context = EncodingError.Context(codingPath: container.codingPath, debugDescription: "NSNumber cannot be encoded because its type is not handled")
- throw EncodingError.invalidValue(nsnumber, context)
- }
- }
- #endif
-}
-
-extension RSAnyEncodable: Equatable {
- public static func == (lhs: RSAnyEncodable, rhs: RSAnyEncodable) -> Bool {
- switch (lhs.value, rhs.value) {
- case is (Void, Void):
- return true
- case let (lhs as Bool, rhs as Bool):
- return lhs == rhs
- case let (lhs as Int, rhs as Int):
- return lhs == rhs
- case let (lhs as Int8, rhs as Int8):
- return lhs == rhs
- case let (lhs as Int16, rhs as Int16):
- return lhs == rhs
- case let (lhs as Int32, rhs as Int32):
- return lhs == rhs
- case let (lhs as Int64, rhs as Int64):
- return lhs == rhs
- case let (lhs as UInt, rhs as UInt):
- return lhs == rhs
- case let (lhs as UInt8, rhs as UInt8):
- return lhs == rhs
- case let (lhs as UInt16, rhs as UInt16):
- return lhs == rhs
- case let (lhs as UInt32, rhs as UInt32):
- return lhs == rhs
- case let (lhs as UInt64, rhs as UInt64):
- return lhs == rhs
- case let (lhs as Float, rhs as Float):
- return lhs == rhs
- case let (lhs as Double, rhs as Double):
- return lhs == rhs
- case let (lhs as String, rhs as String):
- return lhs == rhs
- case let (lhs as [String: RSAnyEncodable], rhs as [String: RSAnyEncodable]):
- return lhs == rhs
- case let (lhs as [RSAnyEncodable], rhs as [RSAnyEncodable]):
- return lhs == rhs
- default:
- return false
- }
- }
-}
-
-extension RSAnyEncodable: CustomStringConvertible {
- public var description: String {
- switch value {
- case is Void:
- return String(describing: nil as Any?)
- case let value as CustomStringConvertible:
- return value.description
- default:
- return String(describing: value)
- }
- }
-}
-
-extension RSAnyEncodable: CustomDebugStringConvertible {
- public var debugDescription: String {
- switch value {
- case let value as CustomDebugStringConvertible:
- return "AnyEncodable(\(value.debugDescription))"
- default:
- return "AnyEncodable(\(description))"
- }
- }
-}
-
-extension RSAnyEncodable: ExpressibleByNilLiteral {}
-extension RSAnyEncodable: ExpressibleByBooleanLiteral {}
-extension RSAnyEncodable: ExpressibleByIntegerLiteral {}
-extension RSAnyEncodable: ExpressibleByFloatLiteral {}
-extension RSAnyEncodable: ExpressibleByStringLiteral {}
-extension RSAnyEncodable: ExpressibleByStringInterpolation {}
-extension RSAnyEncodable: ExpressibleByArrayLiteral {}
-extension RSAnyEncodable: ExpressibleByDictionaryLiteral {}
-
-extension _RSAnyEncodable {
- public init(nilLiteral _: ()) {
- self.init(nil as Any?)
- }
-
- public init(booleanLiteral value: Bool) {
- self.init(value)
- }
-
- public init(integerLiteral value: Int) {
- self.init(value)
- }
-
- public init(floatLiteral value: Double) {
- self.init(value)
- }
-
- public init(extendedGraphemeClusterLiteral value: String) {
- self.init(value)
- }
-
- public init(stringLiteral value: String) {
- self.init(value)
- }
-
- public init(arrayLiteral elements: Any...) {
- self.init(elements)
- }
-
- public init(dictionaryLiteral elements: (AnyHashable, Any)...) {
- self.init([AnyHashable: Any](elements, uniquingKeysWith: { first, _ in first }))
- }
-}
-
-extension RSAnyEncodable: Hashable {
- public func hash(into hasher: inout Hasher) {
- switch value {
- case let value as Bool:
- hasher.combine(value)
- case let value as Int:
- hasher.combine(value)
- case let value as Int8:
- hasher.combine(value)
- case let value as Int16:
- hasher.combine(value)
- case let value as Int32:
- hasher.combine(value)
- case let value as Int64:
- hasher.combine(value)
- case let value as UInt:
- hasher.combine(value)
- case let value as UInt8:
- hasher.combine(value)
- case let value as UInt16:
- hasher.combine(value)
- case let value as UInt32:
- hasher.combine(value)
- case let value as UInt64:
- hasher.combine(value)
- case let value as Float:
- hasher.combine(value)
- case let value as Double:
- hasher.combine(value)
- case let value as String:
- hasher.combine(value)
- case let value as [String: RSAnyEncodable]:
- hasher.combine(value)
- case let value as [RSAnyEncodable]:
- hasher.combine(value)
- default:
- break
- }
- }
-}
diff --git a/Sources/Classes/Helpers/RSSessionStorage.swift b/Sources/Classes/Helpers/RSSessionStorage.swift
new file mode 100644
index 00000000..6110bc18
--- /dev/null
+++ b/Sources/Classes/Helpers/RSSessionStorage.swift
@@ -0,0 +1,73 @@
+//
+// RSSessionStorage.swift
+// Rudder
+//
+// Created by Pallab Maiti on 16/07/22.
+// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
+//
+
+import Foundation
+
+class RSSessionStorage {
+ enum Keys: String {
+ case deviceToken
+ case advertisingId
+ case appTrackingConsent
+ case option
+ case context
+ }
+
+ static let shared = RSSessionStorage()
+ private let syncQueue = DispatchQueue(label: "sessionStorage.rudder.com")
+ private var deviceToken: String?
+ private var advertisingId: String?
+ private var appTrackingConsent: RSAppTrackingConsent?
+ private var option: RSOption?
+ private var context: RSContext?
+
+ func write(_ key: RSSessionStorage.Keys, value: T?) {
+ syncQueue.sync {
+ switch key {
+ case .deviceToken:
+ deviceToken = value as? String
+ case .advertisingId:
+ advertisingId = value as? String
+ case .appTrackingConsent:
+ appTrackingConsent = value as? RSAppTrackingConsent
+ case .option:
+ option = value as? RSOption
+ case .context:
+ if let value = value as? MessageContext {
+ if let data = try? JSONSerialization.data(withJSONObject: value) {
+ context = try? JSONDecoder().decode(RSContext.self, from: data)
+ }
+ }
+ }
+ }
+ }
+
+ func read(_ key: RSSessionStorage.Keys) -> T? {
+ var result: T?
+ syncQueue.sync {
+ switch key {
+ case .deviceToken:
+ result = deviceToken as? T
+ case .advertisingId:
+ result = advertisingId as? T
+ case .appTrackingConsent:
+ result = appTrackingConsent as? T
+ case .option:
+ result = option as? T
+ case .context:
+ result = context as? T
+ }
+ }
+ return result
+ }
+
+ func reset() {
+ syncQueue.sync {
+
+ }
+ }
+}
diff --git a/Sources/Classes/Helpers/RSUserDefaults.swift b/Sources/Classes/Helpers/RSUserDefaults.swift
new file mode 100644
index 00000000..74fe5129
--- /dev/null
+++ b/Sources/Classes/Helpers/RSUserDefaults.swift
@@ -0,0 +1,119 @@
+//
+// RSUserDefaults.swift
+// RudderStack
+//
+// Created by Pallab Maiti on 17/08/21.
+// Copyright © 2021 Rudder Labs India Pvt Ltd. All rights reserved.
+//
+
+import Foundation
+
+class RSUserDefaults {
+ enum Keys: String, CaseIterable {
+ case userId
+ case traits
+ case anonymousId
+ case serverConfig
+ case optStatus
+ case optInTime
+ case optOutTime
+ case externalId
+ case sessionId
+ case lastEventTimeStamp
+ case automaticSessionTrackingStatus
+ case manualSessionTrackingStatus
+ case sessionStoppedStatus
+ }
+
+ enum ApplicationKeys: String {
+ case version
+ case build
+ }
+
+ let syncQueue = DispatchQueue(label: "userDefaults.rudder.com")
+ let userDefaults: UserDefaults
+
+ init(userDefaults: UserDefaults = UserDefaults.standard) {
+ self.userDefaults = userDefaults
+ }
+
+ func write(_ key: RSUserDefaults.Keys, value: T?) {
+ syncQueue.sync {
+ if isBasicType(value: value) {
+ userDefaults.set(value, forKey: key.rawValue)
+ } else {
+ userDefaults.set(try? PropertyListEncoder().encode(value), forKey: key.rawValue)
+ }
+ userDefaults.synchronize()
+ }
+ }
+
+ func read(_ key: RSUserDefaults.Keys) -> T? {
+ var result: T?
+ syncQueue.sync {
+ let raw = userDefaults.object(forKey: key.rawValue)
+ if let r = raw as? Data {
+ result = PropertyListDecoder().optionalDecode(T.self, from: r)
+ } else {
+ result = userDefaults.object(forKey: key.rawValue) as? T
+ }
+ }
+ return result
+ }
+
+ func remove(_ key: RSUserDefaults.Keys) {
+ syncQueue.sync {
+ userDefaults.removeObject(forKey: key.rawValue)
+ userDefaults.synchronize()
+ }
+ }
+
+ func write(application key: RSUserDefaults.ApplicationKeys, value: String?) {
+ syncQueue.sync {
+ userDefaults.set(value, forKey: key.rawValue)
+ userDefaults.synchronize()
+ }
+ }
+
+ func read(application key: RSUserDefaults.ApplicationKeys) -> String? {
+ var result: String?
+ syncQueue.sync {
+ result = userDefaults.string(forKey: key.rawValue)
+ }
+ return result
+ }
+
+ func reset() {
+ syncQueue.sync {
+ userDefaults.removeObject(forKey: RSUserDefaults.Keys.traits.rawValue)
+ userDefaults.removeObject(forKey: RSUserDefaults.Keys.externalId.rawValue)
+ userDefaults.removeObject(forKey: RSUserDefaults.Keys.userId.rawValue)
+ }
+ }
+}
+
+extension RSUserDefaults {
+ func isBasicType(value: T?) -> Bool {
+ var result = false
+ if value == nil {
+ result = true
+ } else {
+ switch value {
+ case is NSNull, is Decimal, is NSNumber, is Bool, is String:
+ result = true
+ default:
+ break
+ }
+ }
+ return result
+ }
+}
+
+extension PropertyListDecoder {
+ func optionalDecode(_ type: T.Type, from object: Any?) -> T? {
+ if let data = object as? Data {
+ return try? PropertyListDecoder().decode(T.self, from: data)
+ }
+ return nil
+ }
+}
diff --git a/Sources/Classes/Networking/APIClient/RSServiceManager.swift b/Sources/Classes/Networking/APIClient/RSServiceManager.swift
index 50c746ea..197a089c 100644
--- a/Sources/Classes/Networking/APIClient/RSServiceManager.swift
+++ b/Sources/Classes/Networking/APIClient/RSServiceManager.swift
@@ -24,13 +24,15 @@ struct RSServiceManager: RSServiceType {
return URLSession(configuration: configuration)
}()
+ let urlSession: URLSession
let client: RSClient
var version: String {
return "v1"
}
- init(client: RSClient) {
+ init(urlSession: URLSession = RSServiceManager.sharedSession, client: RSClient) {
+ self.urlSession = urlSession
self.client = client
}
@@ -46,18 +48,18 @@ struct RSServiceManager: RSServiceType {
extension RSServiceManager {
func request(_ API: API, _ completion: @escaping Handler) {
let urlString = [baseURL(API), path(API)].joined().addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
- client.log(message: "URL: \(urlString ?? "")", logLevel: .debug)
+ Logger.log(message: "URL: \(urlString ?? "")", logLevel: .debug)
var request = URLRequest(url: URL(string: urlString ?? "")!)
request.httpMethod = method(API).value
if let headers = headers(API) {
request.allHTTPHeaderFields = headers
- client.log(message: "HTTPHeaderFields: \(headers)", logLevel: .debug)
+ Logger.log(message: "HTTPHeaderFields: \(headers)", logLevel: .debug)
}
if let httpBody = httpBody(API) {
request.httpBody = httpBody
- client.log(message: "HTTPBody: \(httpBody)", logLevel: .debug)
+ Logger.log(message: "HTTPBody: \(httpBody)", logLevel: .debug)
}
- let dataTask = RSServiceManager.sharedSession.dataTask(with: request, completionHandler: { (data, response, error) in
+ let dataTask = urlSession.dataTask(with: request, completionHandler: { (data, response, error) in
if error != nil {
completion(.failure(NSError(code: .SERVER_ERROR)))
return
@@ -73,7 +75,7 @@ extension RSServiceManager {
default:
do {
if let data = data, let jsonString = String(data: data, encoding: .utf8) {
- client.log(message: jsonString, logLevel: .debug)
+ Logger.log(message: jsonString, logLevel: .debug)
}
let object = try JSONDecoder().decode(T.self, from: data ?? Data())
completion(.success(object))
@@ -82,7 +84,7 @@ extension RSServiceManager {
}
}
default:
- let errorCode = handleCustomError(data: data ?? Data())
+ let errorCode = handleCustomError(data: data ?? Data(), statusCode: statusCode)
completion(.failure(NSError(code: errorCode)))
}
} else {
@@ -92,17 +94,24 @@ extension RSServiceManager {
dataTask.resume()
}
- func handleCustomError(data: Data) -> RSErrorCode {
- do {
- guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: String] else {
+ func handleCustomError(data: Data, statusCode: Int) -> RSErrorCode {
+ switch statusCode {
+ case 404:
+ return .RESOURCE_NOT_FOUND
+ case 400:
+ return .BAD_REQUEST
+ default:
+ do {
+ guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: String] else {
+ return .SERVER_ERROR
+ }
+ if let message = json["message"], message.lowercased() == "invalid write key" {
+ return .WRONG_WRITE_KEY
+ }
+ return .SERVER_ERROR
+ } catch {
return .SERVER_ERROR
}
- if let message = json["message"], message == "Invalid write key" {
- return .WRONG_WRITE_KEY
- }
- return .SERVER_ERROR
- } catch {
- return .SERVER_ERROR
}
}
}
@@ -113,9 +122,7 @@ extension RSServiceManager {
"Authorization": "Basic \(client.config?.writeKey.computeAuthToken() ?? "")"]
switch API {
case .flushEvents:
- if let anonymousIdPlugin = client.find(pluginType: RSAnonymousIdPlugin.self) {
- headers["AnonymousId"] = anonymousIdPlugin.anonymousId?.computeAnonymousIdToken() ?? ""
- }
+ headers["AnonymousId"] = client.anonymousId ?? ""
default:
break
}
@@ -125,12 +132,12 @@ extension RSServiceManager {
func baseURL(_ API: API) -> String {
switch API {
case .flushEvents:
- return "\(client.config?.dataPlaneUrl ?? RSDataPlaneUrl)/\(version)/"
+ return "\(client.config?.dataPlaneUrl ?? DEFAULT_DATA_PLANE_URL)/\(version)/"
case .downloadConfig:
if client.config?.controlPlaneUrl.hasSuffix("/") == true {
- return "\(client.config?.controlPlaneUrl ?? RSControlPlaneUrl)"
+ return "\(client.config?.controlPlaneUrl ?? DEFAULT_CONTROL_PLANE_URL)"
} else {
- return "\(client.config?.controlPlaneUrl ?? RSControlPlaneUrl)/"
+ return "\(client.config?.controlPlaneUrl ?? DEFAULT_CONTROL_PLANE_URL)/"
}
}
}
diff --git a/Sources/Classes/Utility/Fixtures/ServerConfig.json b/Sources/Classes/Utility/Fixtures/ServerConfig.json
new file mode 100644
index 00000000..9e2f3173
--- /dev/null
+++ b/Sources/Classes/Utility/Fixtures/ServerConfig.json
@@ -0,0 +1 @@
+{"source":{"id":"2PuQRyVWk5fmstevuIYS9tTlQos","name":"iOS Dev","writeKey":"2PuQRzr0QTU3cXSE880zk8pyv9I","config":{"statsCollection":{"errors":{"enabled":true},"metrics":{"enabled":true}}},"enabled":true,"workspaceId":"2CYviwoPKBATiXGmWYNpK5p2lPL","sourceDefinitionId":"1Q8kZmXcQ89PWXmdBlN3CSgkaO0","destinations":[{"id":"2Ku8x3PujDxvraFCvXeidOwNl4K","name":"Firebase Dev","enabled":true,"config":{"blacklistedEvents":[],"whitelistedEvents":[],"eventFilteringOption":"disable","oneTrustCookieCategories":[{"oneTrustCookieCategory":"Functional Cookies"}]},"liveEventsConfig":{},"destinationDefinitionId":"1YL4ZafH4z7LQkGDp0ThEwF7N1l","destinationDefinition":{"id":"1YL4ZafH4z7LQkGDp0ThEwF7N1l","name":"FIREBASE","displayName":"Firebase","createdAt":"2020-02-26T09:16:36.149Z","updatedAt":"2023-03-27T11:40:32.471Z","config":{"destConfig":{"ios":["useNativeSDK"],"unity":["useNativeSDK"],"android":["useNativeSDK"],"flutter":["useNativeSDK"],"reactnative":["useNativeSDK"],"defaultConfig":["blacklistedEvents","whitelistedEvents","eventFilteringOption","oneTrustCookieCategories"]},"secretKeys":[],"excludeKeys":[],"includeKeys":["blacklistedEvents","whitelistedEvents","eventFilteringOption","oneTrustCookieCategories"],"transformAt":"processor","transformAtV1":"processor","supportedSourceTypes":["android","ios","unity","reactnative","flutter"],"saveDestinationResponse":false},"responseRules":null,"category":null,"options":null},"deleted":false,"createdAt":"2023-01-27T09:55:50.082Z","updatedAt":"2023-08-04T07:42:33.295Z","workspaceId":"2CYviwoPKBATiXGmWYNpK5p2lPL","revisionId":"2TVj4nh4nIHumFe0txQf3z9MJWV","secretConfig":{},"secretVersion":10,"shouldApplyDeviceModeTransformation":false,"propagateEventsUntransformedOnError":false},{"id":"2LDaS7hJDi31TFg8ct5tIB9Lmfo","name":"Amp Dev","enabled":true,"config":{"apiKey":"1b0a913109d21ccaa5e315d9ef925dc2","groupTypeTrait":"","groupValueTrait":"","trackAllPages":false,"trackCategorizedPages":true,"trackNamedPages":true,"traitsToIncrement":[{"traits":""}],"traitsToSetOnce":[{"traits":""}],"traitsToAppend":[{"traits":""}],"traitsToPrepend":[{"traits":""}],"trackProductsOnce":false,"trackRevenuePerProduct":false,"versionName":"","trackSessionEvents":false,"useIdfaAsDeviceId":false,"blacklistedEvents":[{"eventName":""}],"whitelistedEvents":[{"eventName":""}],"oneTrustCookieCategories":[{"oneTrustCookieCategory":""}],"eventFilteringOption":"disable","mapDeviceBrand":false,"residencyServer":"standard","userProvidedPageEventString":"","useUserDefinedPageEventName":false,"eventUploadThreshold":"30","eventUploadPeriodMillis":"30000"},"liveEventsConfig":{"eventDelivery":false,"eventDeliveryTS":1681887360138},"destinationDefinitionId":"1Q8kZdhlglB9q8gsD4xryMyWg1i","destinationDefinition":{"id":"1Q8kZdhlglB9q8gsD4xryMyWg1i","name":"AM","displayName":"Amplitude","createdAt":"2019-08-30T10:07:47.170Z","updatedAt":"2023-11-23T06:21:22.977Z","config":{"destConfig":{"ios":["eventUploadPeriodMillis","eventUploadThreshold","useNativeSDK","connectionMode","trackSessionEvents","useIdfaAsDeviceId"],"web":["useNativeSDK","connectionMode","preferAnonymousIdForDeviceId","attribution","eventUploadThreshold","eventUploadPeriodMillis","trackNewCampaigns"],"android":["eventUploadPeriodMillis","eventUploadThreshold","useNativeSDK","connectionMode","enableLocationListening","trackSessionEvents","useAdvertisingIdForDeviceId"],"flutter":["eventUploadPeriodMillis","eventUploadThreshold","useNativeSDK","connectionMode","enableLocationListening","trackSessionEvents","useAdvertisingIdForDeviceId","useIdfaAsDeviceId"],"reactnative":["eventUploadPeriodMillis","eventUploadThreshold","useNativeSDK","connectionMode","enableLocationListening","trackSessionEvents","useAdvertisingIdForDeviceId","useIdfaAsDeviceId"],"defaultConfig":["apiKey","groupTypeTrait","groupValueTrait","trackAllPages","trackCategorizedPages","trackNamedPages","traitsToIncrement","traitsToSetOnce","traitsToAppend","traitsToPrepend","trackProductsOnce","trackRevenuePerProduct","versionName","apiSecret","residencyServer","blacklistedEvents","whitelistedEvents","eventFilteringOption","mapDeviceBrand","oneTrustCookieCategories","userProvidedPageEventString","useUserDefinedPageEventName","userProvidedScreenEventString","useUserDefinedScreenEventName"]},"secretKeys":["apiKey","apiSecret"],"excludeKeys":[],"includeKeys":["apiKey","groupTypeTrait","groupValueTrait","trackAllPages","trackCategorizedPages","trackNamedPages","traitsToIncrement","traitsToSetOnce","traitsToAppend","traitsToPrepend","trackProductsOnce","trackRevenuePerProduct","preferAnonymousIdForDeviceId","versionName","enableLocationListening","useAdvertisingIdForDeviceId","trackSessionEvents","useIdfaAsDeviceId","blacklistedEvents","whitelistedEvents","oneTrustCookieCategories","eventFilteringOption","mapDeviceBrand","residencyServer","userProvidedPageEventString","useUserDefinedPageEventName","attribution","eventUploadThreshold","eventUploadPeriodMillis","trackNewCampaigns","userProvidedScreenEventString","useUserDefinedScreenEventName"],"transformAt":"processor","transformAtV1":"processor","isAudienceSupported":false,"supportedSourceTypes":["android","ios","web","unity","amp","cloud","warehouse","reactnative","flutter","cordova","shopify"],"supportsVisualMapper":true,"supportedMessageTypes":["alias","group","identify","page","screen","track"],"saveDestinationResponse":true,"supportedConnectionModes":{"ios":["cloud","device"],"web":["cloud","device"],"android":["cloud","device"],"flutter":["cloud","device"],"reactnative":["cloud","device"]}},"responseRules":null,"category":null,"options":null},"deleted":false,"createdAt":"2023-02-03T07:08:23.373Z","updatedAt":"2023-10-03T12:10:02.379Z","workspaceId":"2CYviwoPKBATiXGmWYNpK5p2lPL","revisionId":"2WFj0vIHszakUtSWUc154AhTHAU","secretConfig":{},"secretVersion":11,"shouldApplyDeviceModeTransformation":false,"propagateEventsUntransformedOnError":false}],"updatedAt":"2023-11-20T06:53:35.875Z","createdAt":"2023-05-17T06:21:22.377Z","liveEventsConfig":{"eventUpload":false,"eventUploadTS":1700463215874},"sourceDefinition":{"options":null,"config":null,"configSchema":null,"uiConfig":null,"id":"1Q8kZmXcQ89PWXmdBlN3CSgkaO0","name":"iOS","displayName":"iOS","category":null,"type":"ios","createdAt":"2019-08-30T10:07:48.397Z","updatedAt":"2023-04-26T11:00:01.643Z"},"createdBy":"2CYvj0Lk1AEiT6gm920O3NemhUZ","secretVersion":null,"connections":[{"id":"2TQyKWhIJEu2BD6J8O1hYMlpi5o","sourceId":"2PuQRyVWk5fmstevuIYS9tTlQos","destinationId":"2Ku8x3PujDxvraFCvXeidOwNl4K","enabled":true,"config":null,"deleted":false,"createdAt":"2023-08-02T15:18:55.314Z","updatedAt":"2023-08-02T15:18:55.314Z"},{"id":"2W1pX0qcKJsuKYg5MrVvAP5QSY4","sourceId":"2PuQRyVWk5fmstevuIYS9tTlQos","destinationId":"2LDaS7hJDi31TFg8ct5tIB9Lmfo","enabled":true,"config":null,"deleted":false,"createdAt":"2023-09-28T14:06:15.880Z","updatedAt":"2023-09-28T14:06:15.880Z"}],"deleted":false,"transient":false},"updatedAt":"2023-11-24T09:28:55.672Z","consentManagementMetadata":{"providers":[{"provider":"oneTrust","resolutionStrategy":"and"},{"provider":"ketch","resolutionStrategy":"or"}]}}
\ No newline at end of file
diff --git a/Sources/Classes/Utility/MockURLProtocol.swift b/Sources/Classes/Utility/MockURLProtocol.swift
new file mode 100644
index 00000000..c4bd625a
--- /dev/null
+++ b/Sources/Classes/Utility/MockURLProtocol.swift
@@ -0,0 +1,40 @@
+//
+// MockURLProtocol.swift
+// MetricsReporterTests
+//
+// Created by Pallab Maiti on 27/06/23.
+//
+
+class MockURLProtocol: URLProtocol {
+
+ static var requestHandler: ((URLRequest) throws -> (HTTPURLResponse, Data?))?
+
+ override class func canInit(with request: URLRequest) -> Bool {
+ return true
+ }
+
+ override class func canonicalRequest(for request: URLRequest) -> URLRequest {
+ return request
+ }
+
+ override func startLoading() {
+ guard let handler = MockURLProtocol.requestHandler else {
+ fatalError("Handler is unavailable.")
+ }
+
+ do {
+ let (response, data) = try handler(request)
+ client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
+ if let data = data {
+ client?.urlProtocol(self, didLoad: data)
+ }
+ client?.urlProtocolDidFinishLoading(self)
+ } catch {
+ client?.urlProtocol(self, didFailWithError: error)
+ }
+ }
+
+ override func stopLoading() {
+
+ }
+}
diff --git a/Sources/Classes/Utility/RSUtils.swift b/Sources/Classes/Utility/RSUtils.swift
index 59526737..bff63084 100644
--- a/Sources/Classes/Utility/RSUtils.swift
+++ b/Sources/Classes/Utility/RSUtils.swift
@@ -9,7 +9,25 @@
import Foundation
import SQLite3
+internal var isUnitTesting: Bool = {
+ // this will work on apple platforms, but fail on linux.
+ if NSClassFromString("XCTestCase") != nil {
+ return true
+ }
+ // this will work on linux and apple platforms, but not in anything with a UI
+ // because XCTest doesn't come into the call stack till much later.
+ let matches = Thread.callStackSymbols.filter { line in
+ return line.contains("XCTest") || line.contains("xctest")
+ }
+ if !matches.isEmpty {
+ return true
+ }
+ // couldn't see anything that indicated we were testing.
+ return false
+}()
+
struct RSUtils {
+
static func getDateString(date: Date) -> String {
let dateFormatter = DateFormatter()
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")
diff --git a/Sources/Classes/Utility/TestUtils.swift b/Sources/Classes/Utility/TestUtils.swift
new file mode 100644
index 00000000..d5f222d7
--- /dev/null
+++ b/Sources/Classes/Utility/TestUtils.swift
@@ -0,0 +1,61 @@
+//
+// TestUtils.swift
+// RudderTests
+//
+// Created by Pallab Maiti on 10/02/23.
+//
+
+import Foundation
+
+internal final class TestUtils {
+
+ static let shared = TestUtils()
+
+ func getPath(forResource: String, ofType: String) -> String {
+ let bundle = Bundle(for: type(of: self))
+ if let path = bundle.path(forResource: forResource, ofType: ofType) {
+ return path
+ } else {
+ fatalError("\(forResource).\(ofType) not present in test bundle.")
+ }
+ }
+
+ func getJSONString(forResource: String, ofType: String) -> String {
+ let path = getPath(forResource: forResource, ofType: ofType)
+ do {
+ let data = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
+ let jsonResult = try JSONSerialization.jsonObject(with: data, options: .mutableLeaves)
+ let data1 = try JSONSerialization.data(withJSONObject: jsonResult, options: .prettyPrinted)
+ if let convertedString = String(data: data1, encoding: .utf8) {
+ return convertedString
+ } else {
+ fatalError("Can not parse or invalid JSON.")
+ }
+ } catch {
+ fatalError("Can not parse or invalid JSON.")
+ }
+ }
+
+ func convertToDictionary(text: String) -> [String: String]? {
+ if let data = text.data(using: .utf8) {
+ do {
+ return try JSONSerialization.jsonObject(with: data, options: []) as? [String: String]
+ } catch {
+ print(error.localizedDescription)
+ }
+ }
+ return nil
+ }
+
+ func convertToJSONString(arrayObject: NSMutableArray) -> String? {
+ do {
+ let jsonData: Data = try JSONSerialization.data(withJSONObject: arrayObject, options: [])
+ if let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue) {
+ return jsonString as String
+ }
+ } catch {
+ print(error.localizedDescription)
+ }
+ return nil
+ }
+}
diff --git a/Sources/Rudder.h b/Sources/Rudder.h
new file mode 100644
index 00000000..e33391b1
--- /dev/null
+++ b/Sources/Rudder.h
@@ -0,0 +1,18 @@
+//
+// Rudder.h
+// Rudder
+//
+// Created by Pallab Maiti on 09/03/22.
+//
+
+#import
+
+//! Project version number for Rudder.
+FOUNDATION_EXPORT double RSVersionNumber;
+
+//! Project version string for Rudder.
+FOUNDATION_EXPORT const unsigned char RSVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import
+
+
diff --git a/Sources/SDKInfo/Info.plist b/Sources/SDKInfo/Info.plist
deleted file mode 100644
index c0701c6d..00000000
--- a/Sources/SDKInfo/Info.plist
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- $(PRODUCT_BUNDLE_PACKAGE_TYPE)
- CFBundleShortVersionString
- $(MARKETING_VERSION)
- CFBundleVersion
- $(CURRENT_PROJECT_VERSION)
-
-
diff --git a/Sources/SDKInfo/Rudder.h b/Sources/SDKInfo/Rudder.h
deleted file mode 100644
index 54b38bed..00000000
--- a/Sources/SDKInfo/Rudder.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// RS.h
-//
-// Created by Arnab Pal on 17/10/19.
-// Copyright © 2019 RSlabs. All rights reserved.
-//
-
-/*#import "RSClient.h"
-
-#import "RSConfig.h"
-#import "RSConfigBuilder.h"
-
-#import "RSMessage.h"
-#import "RSMessageBuilder.h"
-
-#import "RSLogger.h"
-
-// Ecommerce Section
-#import "RSECommerceProductBuilder.h"
-#import "RSECommerceFilterBuilder.h"
-#import "RSECommerceSortBuilder.h"
-#import "RSECommercePromotionBuilder.h"
-#import "RSECommerceOrderBuilder.h"
-#import "RSECommerceCheckoutBuilder.h"
-#import "RSECommerceCouponBuilder.h"
-#import "RSECommerceWishListBuilder.h"
-
-#import "RSProductSearchedEvent.h"
-#import "RSProductListViewedEvent.h"
-#import "RSProductListFilteredEvent.h"
-#import "RSPromotionViewedEvent.h"
-#import "RSPromotionClickedEvent.h"
-#import "RSProductClickedEvent.h"
-#import "RSProductViewedEvent.h"
-#import "RSProductAddedToCartEvent.h"
-#import "RSProductRemovedEvent.h"
-#import "RSCartViewedEvent.h"
-#import "RSCheckoutStartedEvent.h"
-#import "RSCheckoutStepViewedEvent.h"
-#import "RSCheckoutStepCompletedEvent.h"
-#import "RSPaymentInfoEnteredEvent.h"
-#import "RSOrderUpdatedEvent.h"
-#import "RSOrderCompletedEvent.h"
-#import "RSOrderRefundedEvent.h"
-#import "RSOrderCancelledEvent.h"
-#import "RSCouponEnteredEvent.h"
-#import "RSCouponAppliedEvent.h"
-#import "RSCouponDeniedEvent.h"
-#import "RSCouponRemovedEvent.h"
-#import "RSProductAddedToWishListEvent.h"
-#import "RSProductRemovedFromWishListEvent.h"
-#import "RSWishListProductAddedToCartEvent.h"
-#import "RSProductSharedEvent.h"
-#import "RSCartSharedEvent.h"
-#import "RSProductReviewedEvent.h"*/
-
-#import
-
-//! Project version number for Rudder.
-FOUNDATION_EXPORT double RSVersionNumber;
-
-//! Project version string for Rudder.
-FOUNDATION_EXPORT const unsigned char RSVersionString[];
-
-// In this header, you should import all the public headers of your framework using statements like #import
-
-
diff --git a/Tests/RudderTests/RSAliasTests.swift b/Tests/RudderTests/RSAliasTests.swift
deleted file mode 100644
index 07d705fe..00000000
--- a/Tests/RudderTests/RSAliasTests.swift
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// RSAliasTests.swift
-// RudderStackTests
-//
-// Created by Pallab Maiti on 09/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import XCTest
-@testable import Rudder
-
-class RSAliasTests: XCTestCase {
-
- var client: RSClient!
-
- override func setUpWithError() throws {
- client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
- }
-
- override func tearDownWithError() throws {
- client = nil
- }
-
- func testAlias() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.alias("user_id")
-
- let aliasEvent1 = resultPlugin.lastMessage as? AliasMessage
-
- XCTAssertTrue(aliasEvent1?.userId == "user_id")
- XCTAssertTrue(aliasEvent1?.type == .alias)
- XCTAssertNil(aliasEvent1?.option)
- XCTAssertNil(aliasEvent1?.previousId)
-
- client.alias("new_user_id")
-
- let aliasEvent2 = resultPlugin.lastMessage as? AliasMessage
-
- XCTAssertTrue(aliasEvent2?.userId == "new_user_id")
- XCTAssertTrue(aliasEvent2?.previousId == "user_id")
- XCTAssertTrue(aliasEvent2?.type == .alias)
- XCTAssertNil(aliasEvent2?.option)
- }
-}
diff --git a/Tests/RudderTests/RSClientTests.swift b/Tests/RudderTests/RSClientTests.swift
deleted file mode 100644
index 93ddc1e8..00000000
--- a/Tests/RudderTests/RSClientTests.swift
+++ /dev/null
@@ -1,235 +0,0 @@
-//
-// RSClientTests.swift
-// RudderStackTests
-//
-// Created by Pallab Maiti on 07/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import XCTest
-@testable import Rudder
-
-let WRITE_KEY = "1wvsoF3Kx2SczQNlx1dvcqW9ODW"
-let DATA_PLANE_URL = "https://rudderstacz.dataplane.rudderstack.com"
-
-class RSClientTests: XCTestCase {
-
- var client: RSClient!
-
- override func setUpWithError() throws {
- client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
- }
-
- override func tearDownWithError() throws {
- client = nil
- }
-
- func testBaseEventCreation() {
- client.track("Track 1")
- }
-
- // make sure you have Firebase added & enabled to the source in your RudderStack A/C
- func testDestinationEnabled() {
- let expectation = XCTestExpectation(description: "Firebase Expectation")
- let myDestination = FirebaseDestination {
- expectation.fulfill()
- return true
- }
-
- client.addDestination(myDestination)
- waitUntilServerConfigDownloaded(client: client)
- waitUntilStarted(client: client)
- client.track("testDestinationEnabled")
-
- wait(for: [expectation], timeout: 2.0)
- }
-
- func testDestinationNotEnabled() {
- let expectation = XCTestExpectation(description: "MyDestination Expectation")
- let myDestination = MyDestination {
- expectation.fulfill()
- return true
- }
-
- client.addDestination(myDestination)
- waitUntilServerConfigDownloaded(client: client)
- waitUntilStarted(client: client)
- client.track("testDestinationEnabled")
-
- XCTExpectFailure {
- wait(for: [expectation], timeout: 2.0)
- }
- }
-
- func testAnonymousId() {
- client.setAnonymousId("anonymous_id")
-
- let anonId = client.anonymousId
-
- XCTAssertTrue(anonId != "")
- XCTAssertTrue(anonId == "anonymous_id")
- }
-
- func testContext() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.track("context check")
-
- let context = resultPlugin.lastMessage?.context
- XCTAssertNotNil(context)
- XCTAssertNotNil(context?["screen"], "screen missing!")
- XCTAssertNotNil(context?["network"], "network missing!")
- XCTAssertNotNil(context?["os"], "os missing!")
- XCTAssertNotNil(context?["timezone"], "timezone missing!")
- XCTAssertNotNil(context?["library"], "library missing!")
- XCTAssertNotNil(context?["device"], "device missing!")
- XCTAssertNotNil(context?["app"], "app missing!")
- XCTAssertNotNil(context?["locale"], "locale missing!")
- }
-
- func testDeviceToken() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.setDeviceToken("device_token")
- client.track("device token check")
-
- let context = resultPlugin.lastMessage?.context
- let token = context?[keyPath: "device.token"] as? String
-
- XCTAssertTrue(token != "")
- XCTAssertTrue(token == "device_token")
- }
-
- func testContextTraits() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.identify("user_id", traits: ["email": "abc@def.com"])
-
- let identifyEvent = resultPlugin.lastMessage as? IdentifyMessage
- XCTAssertTrue(identifyEvent?.userId == "user_id")
- let identifyTraits = identifyEvent?.traits
- XCTAssertTrue(identifyTraits?["email"] as? String == "abc@def.com")
-
- client.track("test context")
-
- let trackEvent = resultPlugin.lastMessage as? TrackMessage
- XCTAssertTrue(trackEvent?.userId == "user_id")
- let trackTraits = trackEvent?.context?["traits"] as? [String: Any]
- XCTAssertNotNil(trackTraits)
- XCTAssertTrue(trackTraits?["email"] as? String == "abc@def.com")
- XCTAssertTrue(trackTraits?["userId"] as? String == "user_id")
-
- let clientTraits = client.traits
- XCTAssertNotNil(clientTraits)
- XCTAssertTrue(clientTraits?["email"] == "abc@def.com")
- XCTAssertTrue(clientTraits?["userId"] == "user_id")
- }
-}
-
-func waitUntilStarted(client: RSClient?) {
- guard let client = client else { return }
- if let replayQueue = client.find(pluginType: RSReplayQueuePlugin.self) {
- while replayQueue.running == true {
- RunLoop.main.run(until: Date.distantPast)
- }
- }
-}
-
-func waitUntilServerConfigDownloaded(client: RSClient?) {
- guard let client = client else { return }
- while client.serverConfig == nil {
- RunLoop.main.run(until: Date.distantPast)
- }
-}
-
-class FirebaseDestinationPlugin: RSDestinationPlugin {
- var controller: RSController = RSController()
- var client: RSClient?
- var type: PluginType = .destination
- var key: String = "Firebase"
-
- let trackCompletion: (() -> Bool)?
-
- init(trackCompletion: (() -> Bool)? = nil) {
- self.trackCompletion = trackCompletion
- }
-
- func track(message: TrackMessage) -> TrackMessage? {
- var returnEvent: TrackMessage? = message
- if let completion = trackCompletion {
- if !completion() {
- returnEvent = nil
- }
- }
- return returnEvent
- }
-}
-
-class MyDestinationPlugin: RSDestinationPlugin {
- var controller: RSController = RSController()
- var client: RSClient?
- var type: PluginType = .destination
- var key: String = "MyDestination"
-
- let trackCompletion: (() -> Bool)?
-
- init(trackCompletion: (() -> Bool)? = nil) {
- self.trackCompletion = trackCompletion
- }
-
- func track(message: TrackMessage) -> TrackMessage? {
- var returnEvent: TrackMessage? = message
- if let completion = trackCompletion {
- if !completion() {
- returnEvent = nil
- }
- }
- return returnEvent
- }
-}
-
-class FirebaseDestination: RudderDestination {
- init(trackCompletion: (() -> Bool)?) {
- super.init()
- plugin = FirebaseDestinationPlugin(trackCompletion: trackCompletion)
- }
-}
-
-class MyDestination: RudderDestination {
- init(trackCompletion: (() -> Bool)?) {
- super.init()
- plugin = MyDestinationPlugin(trackCompletion: trackCompletion)
- }
-}
-
-class ResultPlugin: RSPlugin {
- let type: PluginType = .after
- var client: RSClient?
- var lastMessage: RSMessage?
- var trackList = [TrackMessage]()
- var identifyList = [IdentifyMessage]()
-
- func execute(message: T?) -> T? where T: RSMessage {
- lastMessage = message
- if let message = message as? TrackMessage {
- trackList.append(message)
- }
- if let message = message as? IdentifyMessage {
- identifyList.append(message)
- }
- return message
- }
-}
diff --git a/Tests/RudderTests/RSGroupTests.swift b/Tests/RudderTests/RSGroupTests.swift
deleted file mode 100644
index 3cf09dc3..00000000
--- a/Tests/RudderTests/RSGroupTests.swift
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// RSGroupTests.swift
-// RudderStackTests
-//
-// Created by Pallab Maiti on 09/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import XCTest
-@testable import Rudder
-
-class RSGroupTests: XCTestCase {
-
- var client: RSClient!
-
- override func setUpWithError() throws {
- client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
- }
-
- override func tearDownWithError() throws {
- client = nil
- }
-
- func testGroup() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.group("sample_group_id")
-
- let groupEvent = resultPlugin.lastMessage as? GroupMessage
-
- XCTAssertTrue(groupEvent?.groupId == "sample_group_id")
- XCTAssertTrue(groupEvent?.type == .group)
- XCTAssertNil(groupEvent?.traits)
- XCTAssertNil(groupEvent?.option)
- }
-
- func testGroupWithTraits() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.group("sample_group_id", traits: ["key_1": "value_1", "key_2": "value_2"])
-
- let groupEvent = resultPlugin.lastMessage as? GroupMessage
-
- XCTAssertTrue(groupEvent?.groupId == "sample_group_id")
- XCTAssertTrue(groupEvent?.type == .group)
- XCTAssertNotNil(groupEvent?.traits)
- XCTAssertNil(groupEvent?.option)
-
- let traits = groupEvent?.traits
-
- XCTAssertTrue(traits?["key_1"] == "value_1")
- XCTAssertTrue(traits?["key_2"] == "value_2")
- }
-}
diff --git a/Tests/RudderTests/RSIdentifyTests.swift b/Tests/RudderTests/RSIdentifyTests.swift
deleted file mode 100644
index 15bec4e8..00000000
--- a/Tests/RudderTests/RSIdentifyTests.swift
+++ /dev/null
@@ -1,87 +0,0 @@
-//
-// RSIdentifyTests.swift
-// RudderStackTests
-//
-// Created by Pallab Maiti on 09/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import XCTest
-@testable import Rudder
-
-class RSIdentifyTests: XCTestCase {
-
- var client: RSClient!
-
- override func setUpWithError() throws {
- client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
- }
-
- override func tearDownWithError() throws {
- client = nil
- }
-
- func testIdentify() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.identify("user_id")
-
- let identifyEvent = resultPlugin.lastMessage as? IdentifyMessage
-
- XCTAssertTrue(identifyEvent?.userId == "user_id")
- XCTAssertTrue(identifyEvent?.type == .identify)
- }
-
- func testIdentifyWithTraits() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.identify("user_id", traits: ["email": "abc@def.com"])
-
- let identifyEvent = resultPlugin.lastMessage as? IdentifyMessage
-
- XCTAssertTrue(identifyEvent?.userId == "user_id")
- XCTAssertTrue(identifyEvent?.type == .identify)
-
- let traits = identifyEvent?.traits
-
- XCTAssertTrue(traits?["email"] as? String == "abc@def.com")
- XCTAssertFalse(traits?["name"] as? String == "name")
- }
-
- func testUserIdAndTraitsPersistCorrectly() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.identify("user_id", traits: ["email": "abc@def.com"])
-
- let identifyEvent = resultPlugin.lastMessage as? IdentifyMessage
-
- XCTAssertTrue(identifyEvent?.userId == "user_id")
- XCTAssertTrue(identifyEvent?.type == .identify)
-
- let traits = identifyEvent?.traits
-
- XCTAssertTrue(traits?["email"] as? String == "abc@def.com")
- XCTAssertFalse(traits?["name"] as? String == "name")
-
- client.track("simple_track")
-
- let trackEvent = resultPlugin.lastMessage as? TrackMessage
-
- XCTAssertTrue(trackEvent?.userId == "user_id")
- let trackTraits = trackEvent?.context?["traits"] as? [String: Any]
- XCTAssertNil(trackTraits)
- }
-}
diff --git a/Tests/RudderTests/RSScreenTests.swift b/Tests/RudderTests/RSScreenTests.swift
deleted file mode 100644
index 880c6818..00000000
--- a/Tests/RudderTests/RSScreenTests.swift
+++ /dev/null
@@ -1,60 +0,0 @@
-//
-// RSScreenTests.swift
-// RudderStackTests
-//
-// Created by Pallab Maiti on 09/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import XCTest
-@testable import Rudder
-
-class RSScreenTests: XCTestCase {
-
- var client: RSClient!
-
- override func setUpWithError() throws {
- client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
- }
-
- override func tearDownWithError() throws {
- client = nil
- }
-
- func testScreen() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.screen("ViewController")
-
- let screenEvent = resultPlugin.lastMessage as? ScreenMessage
- XCTAssertTrue(screenEvent?.name == "ViewController")
- XCTAssertTrue(screenEvent?.type == .screen)
- }
-
- func testScreenWithProperties() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.screen("ViewController", properties: ["key_1": "value_1", "key_2": "value_2"])
-
- let screenEvent = resultPlugin.lastMessage as? ScreenMessage
-
- XCTAssertTrue(screenEvent?.name == "ViewController")
- XCTAssertTrue(screenEvent?.type == .screen)
- XCTAssertNotNil(screenEvent?.properties)
- XCTAssertNil(screenEvent?.option)
-
- let properties = screenEvent?.properties
-
- XCTAssertTrue(properties?["key_1"] as? String == "value_1")
- XCTAssertTrue(properties?["key_2"] as? String == "value_2")
- }
-}
diff --git a/Tests/RudderTests/RSTrackTests.swift b/Tests/RudderTests/RSTrackTests.swift
deleted file mode 100644
index 17cb9ec1..00000000
--- a/Tests/RudderTests/RSTrackTests.swift
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// RSTrackTests.swift
-// RudderStackTests
-//
-// Created by Pallab Maiti on 09/03/22.
-// Copyright © 2022 Rudder Labs India Pvt Ltd. All rights reserved.
-//
-
-import XCTest
-@testable import Rudder
-
-class RSTrackTests: XCTestCase {
- var client: RSClient!
-
- override func setUpWithError() throws {
- client = RSClient.sharedInstance()
- client.configure(with: RSConfig(writeKey: WRITE_KEY).dataPlaneURL(DATA_PLANE_URL))
- }
-
- override func tearDownWithError() throws {
- client = nil
- }
-
- func testTrack() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.track("simple_track")
-
- let trackEvent = resultPlugin.lastMessage as? TrackMessage
-
- XCTAssertTrue(trackEvent?.event == "simple_track")
- XCTAssertTrue(trackEvent?.type == .track)
- XCTAssertNil(trackEvent?.properties)
- XCTAssertNil(trackEvent?.option)
- }
-
- func testTrackWithProperties() {
- let resultPlugin = ResultPlugin()
- client.add(plugin: resultPlugin)
-
- waitUntilStarted(client: client)
- waitUntilServerConfigDownloaded(client: client)
-
- client.track("simple_track_with_props", properties: ["key_1": "value_1", "key_2": "value_2"])
-
- let trackEvent = resultPlugin.lastMessage as? TrackMessage
-
- XCTAssertTrue(trackEvent?.event == "simple_track_with_props")
- XCTAssertTrue(trackEvent?.type == .track)
- XCTAssertNotNil(trackEvent?.properties)
- XCTAssertNil(trackEvent?.option)
-
- let properties = trackEvent?.properties
-
- XCTAssertTrue(properties?["key_1"] as? String == "value_1")
- XCTAssertTrue(properties?["key_2"] as? String == "value_2")
- }
-
-}
diff --git a/sonar-project.properties b/sonar-project.properties
index 7c12c935..9355cecd 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -13,14 +13,14 @@ sonar.links.scm=https://github.com/rudderlabs/rudder-sdk-ios
sonar.links.issue=https://github.com/rudderlabs/rudder-sdk-ios/issues
# Path to reports
-# sonar.javascript.lcov.reportPaths=reports/Test_report.json
-# sonar.testExecutionReportPaths=reports/sonar/results-report.xml
-# sonar.swift.swiftLint.reportPaths=reports/Lint_report.json
+sonar.coverageReportPaths=generic-coverage.xml
+sonar.c.file.suffixes=-
+sonar.cpp.file.suffixes=-
+sonar.objc.file.suffixes=-
# Path to sources
-sonar.sources=Sources/Classes
-# sonar.inclusions=**/*.swift
-# sonar.exclusions=**/*.json,**/*.html,**/*.png,**/*.jpg,**/*.gif,**/*.svg
+sonar.sources=Sources
+sonar.exclusions=**/*.json,**/*.html,**/*.png,**/*.jpg,**/*.gif,**/*.svg
# Path to tests
# sonar.tests=Tests
diff --git a/xccov-to-generic.sh b/xccov-to-generic.sh
new file mode 100644
index 00000000..0574a996
--- /dev/null
+++ b/xccov-to-generic.sh
@@ -0,0 +1,95 @@
+#!/usr/bin/env bash
+
+# xccov-to-generic.sh
+#
+# Created by Pallab Maiti.
+#
+
+set -euo pipefail
+
+function convert_file {
+ local xccovarchive_file="$1"
+ local file_name="$2"
+ local xccov_options="$3"
+ echo " "
+ xcrun xccov view $xccov_options --file "$file_name" "$xccovarchive_file" | \
+ sed -n '
+ s/^ *\([0-9][0-9]*\): 0.*$/ /p;
+ s/^ *\([0-9][0-9]*\): [1-9].*$/ /p
+ '
+ echo ' '
+}
+
+function xccov_to_generic {
+ echo ''
+ for xccovarchive_file in "$@"; do
+ if [[ ! -d $xccovarchive_file ]]
+ then
+ echo "Coverage FILE NOT FOUND AT PATH: $xccovarchive_file" 1>&2;
+ exit 1
+ fi
+
+ if [ $sdk_version -gt 10 ]; then # Apply optimization
+ xccovarchive_file=$(optimize_format)
+ fi
+
+ local xccov_options=""
+ if [[ $xccovarchive_file == *".xcresult"* ]]; then
+ xccov_options="--archive"
+ fi
+ xcrun xccov view $xccov_options --file-list "$xccovarchive_file" | while read -r file_name; do
+ convert_file "$xccovarchive_file" "$file_name" "$xccov_options"
+ done
+ done
+ echo ''
+}
+
+function check_sdk_version {
+ sdk_major_version=`xcrun --show-sdk-version | cut -d . -f 1`
+
+ if [ $? -ne 0 ]; then
+ echo 'Failed to execute xcrun show-sdk-version' 1>&2
+ exit -1
+ fi
+ echo $sdk_major_version
+}
+
+function cleanup_tmp_files {
+ rm -rf tmp.json
+ rm -rf tmp.xccovarchive
+}
+
+# Optimize coverage files conversion time by exporting to a clean xcodearchive directory
+# Credits to silverhammermba on issue #68 for the suggestion
+function optimize_format {
+ cleanup_tmp_files
+ xcrun xcresulttool get --format json --path "$xccovarchive_file" > tmp.json
+ if [ $? -ne 0 ]; then
+ echo 'Failed to execute xcrun xcresulttool get' 1>&2
+ exit -1
+ fi
+
+ # local reference=$(jq -r '.actions._values[2].actionResult.coverage.archiveRef.id._value' tmp.json)
+ local reference=$(jq -r '.actions._values[]|[.actionResult.coverage.archiveRef.id],._values' tmp.json | grep value | cut -d : -f 2 | cut -d \" -f 2)
+ if [ $? -ne 0 ]; then
+ echo 'Failed to execute jq (https://stedolan.github.io/jq/)' 1>&2
+ exit -1
+ fi
+ # $reference can be a list of IDs (from a merged .xcresult bundle of multiple test plans)
+ for test_ref in $reference; do
+ xcrun xcresulttool export --type directory --path "$xccovarchive_file" --id "$test_ref" --output-path tmp.xccovarchive
+ if [ $? -ne 0 ]; then
+ echo "Failed to execute xcrun xcresulttool export for reference ${test_ref}" 1>&2
+ exit -1
+ fi
+ done
+ echo "tmp.xccovarchive"
+}
+
+sdk_version=$(check_sdk_version)
+if [ $? -ne 0 ]; then
+ exit -1
+fi
+
+xccov_to_generic "$@"
+cleanup_tmp_files