Skip to content
This repository was archived by the owner on Oct 29, 2024. It is now read-only.

Commit c93ff06

Browse files
authored
[sc-190014] Merge 7.0 for u2c release (#143)
* Update swift and android sdk dependencies * Initial commit * TODO: comment out private attributes config and figure out later * Remove erroneous type annotation * TODO: fix deprecated config settings * Added todos to map deprecated android config * Initial refactor to move deprecated android config items * Start implementing deprecated config options * Implement android sdk major changes * Removed deprecated config options * Remove pollUri to use streaming and default endpoints * Implemented typescript changes * Renamed xxxUri to xxxUrl * Implemented swift config option changes * Fixed Reference creation for private context attributes * Update modd.conf * Removed jcenter * Reinstate user.privateAttributeNames because that should stay frozen * PR feedback * Update test-types.ts * Remove unnecessary stream: true config default * [sc-188224] Adios old rn versions * Set example app min ios target to 12.4 as mandated by rn 0.70. Improve local dev modd experience. * Added yarn-all scripts * Fixed broken tests by adding babel config and removing redundant transform.js * Remove old rn versions from CI * Force npm i to get around rn 6.3.0 still supporting old rn versions * Increase circleci macos resource to large * [sc-188335] Add u2c support (#140) * Added js common sdk context helper files. First attempt to implement glue code from js to android sdk. * Validate context in js before initializing ldclient * Added multi context support. Dry'd context manipulation logic. * Copy src folder to node_modules so its part of the npm package * Added arbitrary attributes mapping logic * Replaced src/common sdk files with actual js common sdk package * Refactored init code to be more robust with errors. Dry'd init logic. * Implemented identify logic for context. Changed example app to use multi context. * Autogenerate keys for anonymous context * Removed console logs and dry'd logic * Added contextUtils. Refactored isContext to js. * Initial attempt at ios context implementation * First cut ios implementation * Refactored helper functions to its own utils class. Added android unit tests. * Added multicontext tests * Added ios Podfile and fix dev build. Added swift unit tests. * Added swift unit test scaffold * Update Tests.swift * Improve ios unit tests * Speed up hot reload by replacing cp with rsync. Dry'd dir paths eliminating repetitions. * Update Tests.swift * Update .gitignore * Added more context and config tests * Add unit test for config build * Update modd-android.conf * Added contextUtils tests * Added typescript support for example app to test types. Replaced cp with rsync to speed up local dev. Improved tsconfig to use out of the box rn config. * Use common types for LDUser, LDContext and LDMultiKindContext * Update LaunchdarklyReactNativeClient.xcscheme * Update App.tsx * Prettified changelog * Updated common sdk version * Replaced user references with context * Use trySetValue for key, name and anonymous * Update config.yml * Added files property to specify only necessary files for npm publish * Exclude android test files from npm publish * Replace print with NSLog * Revert prettier changes. Ignore changelog from prettier. * Corrected misspelling of filename. * Added newline at eof * [sc-189696] Fix auto generation of anonymous keys (#141) * Initial commit * Rollback swift changes * Swift changes. * Updated js tests * Don't generate keys in js and defer context validation to native sdks * Update Tests.swift * Add java anonymous key test * Add github actions for tests * Update main.yml * Remove js tests from cicleci to github action. Prettified circleci config. * Update config.yml * Update config.yml * Update config.yml * Update config.yml * Add ios test job * Update main.yml * Update main.yml * Update main.yml * Update main.yml * Update main.yml * Update main.yml * Update main.yml * Update main.yml * Cache pods and quiet xcodebuild * Update main.yml * Update main.yml * Update main.yml * Update main.yml * Restore other tests --------- Co-authored-by: Yusinto Ngadiman <[email protected]> * Fixed formatting of ga yml --------- Co-authored-by: Yusinto Ngadiman <[email protected]> * [sc-169352] Add ldClient nil guards (#142) Update LaunchdarklyReactNativeClient.swift * Attempt to fix broken ios tests * Bust Pod cache * Update config.yml --------- Co-authored-by: Yusinto Ngadiman <[email protected]>
1 parent f007a43 commit c93ff06

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+9375
-7391
lines changed

.circleci/config.yml

Lines changed: 23 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ jobs:
1414

1515
macos:
1616
xcode: <<parameters.xcode-version>>
17-
resource_class: macos.x86.medium.gen2
17+
resource_class: large
1818

1919
environment:
20-
ANDROID_SDK_ROOT: "/tmp/Android"
20+
ANDROID_SDK_ROOT: '/tmp/Android'
2121

2222
steps:
2323
- checkout
@@ -49,16 +49,6 @@ jobs:
4949
mkdir -p test
5050
cd test
5151
[ -d "CITest" ] || npx react-native@<<parameters.rn-version>> init CITest --version <<parameters.rn-version>> --skip-install
52-
53-
# HACK: rn 0.64.x init the test project targeting ios 10, which is incompatible with the ios SDK which requires
54-
# a minimum of ios 11
55-
sed -i.bak "s/platform :ios, '10.0'/platform :ios, '11.0'/" CITest/ios/Podfile
56-
sed -i.bak "s/IPHONEOS_DEPLOYMENT_TARGET = 10.0;/IPHONEOS_DEPLOYMENT_TARGET = 11.0;/" CITest/ios/CITest.xcodeproj/project.pbxproj
57-
58-
#HACK: force rn android 0.64.x init to use minSdkVersion 30 to pass the build
59-
sed -i.bak 's/buildToolsVersion = "29.0.3"/buildToolsVersion = "30.0.2"/' CITest/android/build.gradle
60-
sed -i.bak "s/compileSdkVersion = 29/compileSdkVersion = 31/" CITest/android/build.gradle
61-
sed -i.bak "s/targetSdkVersion = 29/targetSdkVersion = 31/" CITest/android/build.gradle
6252
6353
- save_cache:
6454
name: Save RN project template to cache
@@ -75,7 +65,15 @@ jobs:
7565
7666
- run:
7767
name: Add LaunchDarkly dependency
78-
command: cd ../test/CITest && npx yarn add file:../../project
68+
command: |
69+
cd ../test/CITest && npx yarn add file:../../project
70+
cd node_modules/launchdarkly-react-native-client-sdk/ios
71+
rm -rf LaunchdarklyReactNativeClient.xcworkspace
72+
rm -rf build
73+
rm -rf Pods
74+
rm -rf Tests
75+
rm -rf Podfile
76+
rm -rf Podfile.lock
7977
8078
- restore_cache:
8179
name: Restore gem cache
@@ -110,7 +108,7 @@ jobs:
110108
- when:
111109
# We only care to build Android application and debug iOS Build for a single XCode version
112110
condition:
113-
equal: [ 13.2.1, << parameters.xcode-version >> ]
111+
equal: [13.2.1, << parameters.xcode-version >>]
114112
steps:
115113
- run:
116114
name: Build application for iOS (Debug)
@@ -124,43 +122,22 @@ jobs:
124122
- store_artifacts:
125123
path: artifacts
126124

127-
test-javascript:
128-
docker:
129-
- image: cimg/node:current
130-
steps:
131-
- checkout
132-
133-
- run: npm install
134-
- run: mkdir -p reports/jest
135-
- run:
136-
command: npm run test:junit
137-
environment:
138-
JEST_JUNIT_OUTPUT_DIR: "./reports/jest"
139-
140-
- run: npm run check-typescript
141-
142-
- store_test_results:
143-
path: reports
144-
145125
workflows:
146126
version: 2
147-
all-tests:
127+
install-sdk-build-app:
148128
jobs:
149-
- test-javascript
150129
- build-applications-using-template:
151130
name: rn<<matrix.rn-version>>-xc<<matrix.xcode-version>>-build-apps-using-template
152131
matrix:
153132
parameters:
154-
rn-version: [ "0.64.4", "0.65.2", "0.66.4", "0.67.3", "0.68.0","0.69.4", "0.70.1" ]
155-
xcode-version: [ "12.5.1", "13.2.1", "13.4.1", "14.0.1" ]
133+
rn-version: ['0.69.4', '0.70.1']
134+
xcode-version: ['12.5.1', '13.2.1', '13.4.1', '14.0.1']
156135
exclude:
157-
- rn-version: "0.64.4"
158-
xcode-version: "13.4.1"
159-
- rn-version: "0.64.4"
160-
xcode-version: "14.0.1"
161-
- rn-version: "0.65.2"
162-
xcode-version: "13.4.1"
163-
- rn-version: "0.65.2"
164-
xcode-version: "14.0.1"
165-
requires:
166-
- test-javascript
136+
- rn-version: '0.69.4'
137+
xcode-version: '13.4.1'
138+
- rn-version: '0.69.4'
139+
xcode-version: '14.0.1'
140+
- rn-version: '0.70.1'
141+
xcode-version: '13.4.1'
142+
- rn-version: '0.70.1'
143+
xcode-version: '14.0.1'

.github/workflows/main.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: Tests
2+
on: [push]
3+
4+
jobs:
5+
tsc:
6+
runs-on: ubuntu-latest
7+
name: Typescript
8+
steps:
9+
- uses: actions/checkout@v3
10+
- uses: actions/setup-node@v3
11+
with:
12+
node-version: '16.x'
13+
cache: 'yarn'
14+
- run: yarn && yarn tsc
15+
16+
js-tests:
17+
runs-on: ubuntu-latest
18+
name: JS tests
19+
steps:
20+
- uses: actions/checkout@v3
21+
- uses: actions/setup-node@v3
22+
with:
23+
node-version: '16.x'
24+
cache: 'yarn'
25+
- run: yarn && yarn test
26+
27+
android-tests:
28+
runs-on: ubuntu-latest
29+
name: Android tests
30+
steps:
31+
- uses: actions/checkout@v3
32+
- uses: actions/setup-node@v3
33+
with:
34+
node-version: '16.x'
35+
cache: 'yarn'
36+
- run: yarn && cd android && ./gradlew test
37+
38+
# ripped from these two places:
39+
# https://vmois.dev/xcode-github-actions/
40+
# https://gist.github.com/ricardopereira/10198e68f27c14601d77ebc7a8352da1
41+
ios-tests:
42+
runs-on: macOS-latest
43+
strategy:
44+
matrix:
45+
destination: ['platform=iOS Simulator,name=iPhone 13,OS=16.2']
46+
name: iOS tests
47+
steps:
48+
- uses: actions/checkout@v3
49+
- uses: actions/setup-node@v3
50+
with:
51+
node-version: '16.x'
52+
cache: 'yarn'
53+
- uses: actions/cache@v3
54+
id: cocoapods-cache
55+
with:
56+
path: ios/Pods
57+
key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
58+
restore-keys: |
59+
${{ runner.os }}-pods-
60+
- name: CocoaPods
61+
if: steps.cocoapods-cache.outputs.cache-hit != 'true'
62+
run: cd ios && yarn && pod install
63+
- name: Select Xcode
64+
run: sudo xcode-select -switch /Applications/Xcode_14.2.app && /usr/bin/xcodebuild -version
65+
- name: Run tests
66+
run: cd ios && xcodebuild -quiet -workspace LaunchdarklyReactNativeClient.xcworkspace -scheme LaunchdarklyReactNativeClient -sdk iphonesimulator -destination "${destination}" test | xcpretty && exit ${PIPESTATUS[0]}
67+
env:
68+
destination: ${{ matrix.destination }}

.ldrelease/config.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ repo:
44
public: react-native-client-sdk
55
private: react-native-client-sdk-private
66

7+
branches:
8+
- name: main
9+
description: 7.x
10+
- name: 6.x
11+
712
publications:
813
- url: https://www.npmjs.com/package/launchdarkly-react-native-client-sdk
914
description: npm

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CHANGELOG.md

ManualTestApp/App.js renamed to ManualTestApp/App.tsx

Lines changed: 61 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import React, { useState, useEffect } from 'react';
1+
import { useState, useEffect, ReactNode } from 'react';
22
import { SafeAreaView, ScrollView, StyleSheet, Text, View, Button, TextInput, Alert, Switch } from 'react-native';
33
import { Picker } from '@react-native-picker/picker';
4-
import LDClient from 'launchdarkly-react-native-client-sdk';
5-
import MessageQueue from 'react-native/Libraries/BatchedBridge/MessageQueue.js';
4+
import LDClient, { LDMultiKindContext } from 'launchdarkly-react-native-client-sdk';
5+
import MessageQueue from 'react-native/Libraries/BatchedBridge/MessageQueue';
66

7-
const Wrapper = ({ children }): Node => {
7+
const Wrapper = ({ children }: { children: ReactNode }) => {
88
const styles = {
99
scroll: { backgroundColor: '#fff', padding: 10 },
1010
area: { backgroundColor: '#fff', flex: 1 },
@@ -17,11 +17,11 @@ const Wrapper = ({ children }): Node => {
1717
};
1818

1919
const Body = () => {
20-
const [client, setClient] = useState(null);
20+
const [client, setClient] = useState<LDClient | null>(null);
2121
const [flagKey, setFlagKey] = useState('dev-test-flag');
2222
const [flagType, setFlagType] = useState('bool');
2323
const [isOffline, setIsOffline] = useState(false);
24-
const [userKey, setUserKey] = useState('user key');
24+
const [contextKey, setContextKey] = useState('context-key');
2525
const [listenerKey, setListenerKey] = useState('');
2626
const [listeners, setListeners] = useState({});
2727

@@ -36,69 +36,96 @@ const Body = () => {
3636
version: '0.0.1',
3737
},
3838
};
39-
let user = { key: userKey };
39+
const anonymousUserContext = {
40+
kind: 'user',
41+
key: 'user-key-1',
42+
anonymous: true,
43+
};
44+
45+
// A multi-context can contain both anonymous and non-anonymous contexts.
46+
// Here, organization is not anonymous.
47+
const multiContext: LDMultiKindContext = {
48+
kind: 'multi',
49+
user: anonymousUserContext,
50+
org: {
51+
key: 'org-key',
52+
name: 'Example organization name',
53+
_meta: {
54+
privateAttributes: ['address', 'phone'],
55+
},
56+
address: {
57+
street: 'sunset blvd',
58+
postcode: 94105,
59+
},
60+
phone: 5551234,
61+
},
62+
};
63+
4064
try {
41-
await ldClient.configure(config, user);
65+
await ldClient.configure(config, multiContext);
4266
} catch (err) {
4367
console.error(err);
4468
}
4569
setClient(ldClient);
4670
}
4771

4872
if (client == null) {
49-
initializeClient();
73+
initializeClient().then(() => console.log('ld client initialized successfully'));
5074
}
5175
});
5276

5377
const evalFlag = async () => {
5478
let res;
5579
if (flagType === 'bool') {
56-
res = await client.boolVariation(flagKey, false);
80+
res = await client?.boolVariation(flagKey, false);
5781
} else if (flagType === 'string') {
58-
res = await client.stringVariation(flagKey, '');
82+
res = await client?.stringVariation(flagKey, '');
5983
} else if (flagType === 'number') {
60-
res = await client.numberVariation(flagKey, 0.0);
84+
res = await client?.numberVariation(flagKey, 0.0);
6185
} else if (flagType === 'json') {
62-
res = await client.jsonVariation(flagKey, null);
86+
res = await client?.jsonVariation(flagKey, null);
6387
}
6488

6589
Alert.alert('LD Server Response', JSON.stringify(res));
6690
};
6791

6892
const track = () => {
69-
client.track(flagKey, false);
93+
client?.track(flagKey, false);
7094
};
7195

7296
const identify = () => {
73-
client.identify({ key: userKey });
97+
client?.identify({ kind: 'user', key: contextKey });
7498
};
7599

76100
const listen = () => {
77101
if (listeners.hasOwnProperty(listenerKey)) {
78102
return;
79103
}
80-
let listener = (value) => Alert.alert('Listener Callback', value);
81-
client.registerFeatureFlagListener(listenerKey, listener);
104+
let listener = (value: string | undefined) => Alert.alert('Listener Callback', value);
105+
client?.registerFeatureFlagListener(listenerKey, listener);
82106
setListeners({ ...listeners, ...{ [listenerKey]: listener } });
83107
};
84108

85109
const removeListener = () => {
86-
client.unregisterFeatureFlagListener(listenerKey, listeners[listenerKey]);
110+
// @ts-ignore
111+
client?.unregisterFeatureFlagListener(listenerKey, listeners[listenerKey]);
112+
// @ts-ignore
87113
let { [listenerKey]: omit, ...newListeners } = listeners;
88114
setListeners(newListeners);
89115
};
90116

91117
const flush = () => {
92-
client.flush();
118+
client?.flush();
93119
};
94120

95-
const setOffline = (newIsOffline) => {
96-
if (newIsOffline) {
97-
client.setOffline();
121+
const setOffline = (offline: boolean) => {
122+
if (offline) {
123+
client?.setOffline();
98124
} else {
99-
client.setOnline();
125+
client?.setOnline();
100126
}
101-
setIsOffline(newIsOffline);
127+
128+
setIsOffline(offline);
102129
};
103130

104131
return (
@@ -116,8 +143,8 @@ const Body = () => {
116143
<Text>Offline</Text>
117144
<Switch value={isOffline} onValueChange={setOffline} />
118145
</View>
119-
<Text>User Key:</Text>
120-
<TextInput style={styles.input} onChangeText={setUserKey} value={userKey} autoCapitalize="none" />
146+
<Text>Context key:</Text>
147+
<TextInput style={styles.input} onChangeText={setContextKey} value={contextKey} autoCapitalize="none" />
121148
<View style={styles.row}>
122149
<Button title="Identify" onPress={identify} />
123150
<Button title="Track" onPress={track} />
@@ -155,11 +182,17 @@ const App = () => {
155182
};
156183

157184
MessageQueue.spy((msg) => {
158-
if (msg.module != 'LaunchdarklyReactNativeClient' && !msg.method.includes('LaunchdarklyReactNativeClient')) {
185+
if (
186+
msg.module != 'LaunchdarklyReactNativeClient' &&
187+
typeof msg.method !== 'number' &&
188+
!msg.method.includes('LaunchdarklyReactNativeClient')
189+
) {
159190
return;
160191
}
161192
let logMsg = msg.type === 0 ? 'N->JS: ' : 'JS->N: ';
162-
logMsg += msg.method.replace('LaunchdarklyReactNativeClient.', '');
193+
if (typeof msg.method !== 'number') {
194+
logMsg += msg.method.replace('LaunchdarklyReactNativeClient.', '');
195+
}
163196

164197
let params = [...msg.args];
165198
if (params.length >= 2) {

0 commit comments

Comments
 (0)