react-native-nami-sdk 3.0.25 → 3.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +1 -1
- package/.eslintrc.js +40 -0
- package/.github/workflows/CI.yaml +242 -5
- package/.prettierrc.js +7 -0
- package/android/src/main/java/com/nami/reactlibrary/NamiBridgeModule.kt +1 -1
- package/index.d.ts +8 -20
- package/index.ts +8 -0
- package/ios/Nami.m +1 -1
- package/ios/NamiCampaignManagerBridge.swift +1 -1
- package/package.json +6 -2
- package/src/Nami.ts +21 -0
- package/src/NamiCampaignManager.d.ts +2 -1
- package/src/NamiCampaignManager.ts +143 -0
- package/src/NamiCustomerManager.ts +89 -0
- package/src/NamiEntitlementManager.d.ts +5 -6
- package/src/NamiEntitlementManager.ts +58 -0
- package/src/NamiMLManager.ts +13 -0
- package/src/NamiPaywallManager.ts +141 -0
- package/src/NamiPurchaseManager.d.ts +27 -27
- package/src/NamiPurchaseManager.ts +100 -0
- package/src/types.ts +255 -13
- package/tsconfig.json +69 -0
- package/index.js +0 -7
- package/src/Nami.js +0 -10
- package/src/NamiCampaignManager.js +0 -76
- package/src/NamiCustomerManager.js +0 -35
- package/src/NamiEntitlementManager.js +0 -23
- package/src/NamiMLManager.js +0 -7
- package/src/NamiPaywallManager.js +0 -73
- package/src/NamiPurchaseManager.js +0 -37
package/.eslintignore
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
node_modules/
|
|
2
|
-
.eslintrc
|
|
2
|
+
.eslintrc
|
package/.eslintrc.js
CHANGED
|
@@ -3,10 +3,50 @@ module.exports = {
|
|
|
3
3
|
extends: '@react-native-community',
|
|
4
4
|
parser: '@typescript-eslint/parser',
|
|
5
5
|
plugins: ['@typescript-eslint'],
|
|
6
|
+
parserOptions: {
|
|
7
|
+
ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
|
|
8
|
+
sourceType: 'module', // Allows for the use of imports
|
|
9
|
+
ecmaFeatures: {
|
|
10
|
+
jsx: true, // Allows for the parsing of JSX
|
|
11
|
+
},
|
|
12
|
+
},
|
|
6
13
|
rules: {
|
|
7
14
|
'react/no-unstable-nested-components': [
|
|
8
15
|
'off' | 'warn' | 'error',
|
|
9
16
|
{ allowAsProps: true | false },
|
|
10
17
|
],
|
|
18
|
+
'prettier/prettier': [
|
|
19
|
+
'error',
|
|
20
|
+
{
|
|
21
|
+
bracketSpacing: true,
|
|
22
|
+
jsxBracketSameLine: true,
|
|
23
|
+
singleQuote: true,
|
|
24
|
+
trailingComma: 'all',
|
|
25
|
+
arrowParens: 'avoid',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
quotes: ['error', 'single'],
|
|
29
|
+
indent: ['error', 2, { SwitchCase: 1 }],
|
|
30
|
+
'comma-dangle': [2, 'always-multiline'],
|
|
31
|
+
'react/prop-types': 'off',
|
|
32
|
+
'@typescript-eslint/no-namespace': 'off',
|
|
33
|
+
'@typescript-eslint/no-explicit-any': 'off',
|
|
34
|
+
'@typescript-eslint/ban-ts-comment': 'off',
|
|
35
|
+
'@typescript-eslint/interface-name-prefix': 'off',
|
|
36
|
+
'@typescript-eslint/no-non-null-assertion': 'off',
|
|
37
|
+
'@typescript-eslint/no-unused-vars': [
|
|
38
|
+
2,
|
|
39
|
+
{ args: 'none', ignoreRestSiblings: true },
|
|
40
|
+
],
|
|
41
|
+
'@typescript-eslint/no-use-before-define': ['error', { variables: false }],
|
|
42
|
+
'react/jsx-first-prop-new-line': [1, 'multiline'],
|
|
43
|
+
'react/jsx-max-props-per-line': [
|
|
44
|
+
1,
|
|
45
|
+
{
|
|
46
|
+
maximum: 1,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
'no-unused-vars': 'off',
|
|
50
|
+
'object-curly-spacing': ['error', 'always'],
|
|
11
51
|
},
|
|
12
52
|
};
|
|
@@ -16,14 +16,13 @@ jobs:
|
|
|
16
16
|
node-version: "16"
|
|
17
17
|
|
|
18
18
|
- name: 'Checkout ${{ inputs.ref }}'
|
|
19
|
-
uses: actions/checkout@
|
|
19
|
+
uses: actions/checkout@v3
|
|
20
20
|
with:
|
|
21
21
|
path: source
|
|
22
22
|
ref: '${{ inputs.ref }}'
|
|
23
23
|
|
|
24
24
|
- name: Install Basic app dependencies
|
|
25
|
-
run:
|
|
26
|
-
yarn install
|
|
25
|
+
run: yarn --frozen-lockfile --prefer-offline
|
|
27
26
|
working-directory: source/examples/Basic
|
|
28
27
|
|
|
29
28
|
- name: Linter Basic
|
|
@@ -32,11 +31,249 @@ jobs:
|
|
|
32
31
|
working-directory: source/examples/Basic
|
|
33
32
|
|
|
34
33
|
- name: Install TestNamiTV app dependencies
|
|
35
|
-
run:
|
|
36
|
-
yarn install
|
|
34
|
+
run: yarn --frozen-lockfile --prefer-offline
|
|
37
35
|
working-directory: source/examples/TestNamiTV
|
|
38
36
|
|
|
39
37
|
- name: Linter TestNamiTV
|
|
40
38
|
run: |
|
|
41
39
|
npx eslint . --ext .js,.jsx,.ts,.tsx
|
|
42
40
|
working-directory: source/examples/TestNamiTV
|
|
41
|
+
e2e-ios:
|
|
42
|
+
runs-on: macos-12
|
|
43
|
+
env:
|
|
44
|
+
DETOX_CONFIGURATION: ios.sim.release
|
|
45
|
+
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/setup-node@v3
|
|
48
|
+
with:
|
|
49
|
+
node-version: 16
|
|
50
|
+
|
|
51
|
+
- name: 'Checkout ${{ inputs.ref }}'
|
|
52
|
+
uses: actions/checkout@v3
|
|
53
|
+
with:
|
|
54
|
+
path: source
|
|
55
|
+
ref: '${{ inputs.ref }}'
|
|
56
|
+
|
|
57
|
+
- name: Cache node_modules
|
|
58
|
+
uses: actions/cache@v3
|
|
59
|
+
id: cache
|
|
60
|
+
with:
|
|
61
|
+
path: source/examples/Basic/node_modules
|
|
62
|
+
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
|
63
|
+
|
|
64
|
+
- name: Install Yarn Dependencies
|
|
65
|
+
run: yarn install
|
|
66
|
+
working-directory: source/examples/Basic
|
|
67
|
+
|
|
68
|
+
- name: Install macOS dependencies
|
|
69
|
+
run: |
|
|
70
|
+
brew tap wix/brew
|
|
71
|
+
brew install applesimutils
|
|
72
|
+
sudo gem install cocoapods
|
|
73
|
+
gem install CFPropertyList
|
|
74
|
+
env:
|
|
75
|
+
# Speed up build could be updated 0/1 for full install
|
|
76
|
+
HOMEBREW_NO_AUTO_UPDATE: 1
|
|
77
|
+
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
|
78
|
+
|
|
79
|
+
- name: Update App Platform ID
|
|
80
|
+
working-directory: source/examples/Basic/config/
|
|
81
|
+
run: |
|
|
82
|
+
sed -i '' -e "s/APPLE_PROD_APP_PLATFORM_ID/$BASIC_APPLE_PROD_APP_PLATFORM_ID/" index.ts
|
|
83
|
+
env:
|
|
84
|
+
BASIC_APPLE_PROD_APP_PLATFORM_ID: '${{ secrets.APPLE_PROD_APP_PLATFORM_ID }}'
|
|
85
|
+
|
|
86
|
+
# - name: Cache Pods
|
|
87
|
+
# uses: actions/cache@v3
|
|
88
|
+
# id: podcache
|
|
89
|
+
# with:
|
|
90
|
+
# path: source/examples/Basic/ios
|
|
91
|
+
# key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
|
|
92
|
+
# restore-keys: |
|
|
93
|
+
# ${{ runner.os }}-pods-
|
|
94
|
+
|
|
95
|
+
- name: Clean node_modules tree
|
|
96
|
+
run: rm -rf node_modules/react-native-nami-sdk/examples
|
|
97
|
+
working-directory: source/examples/Basic
|
|
98
|
+
|
|
99
|
+
- name: Install iOS pods
|
|
100
|
+
run: pod install
|
|
101
|
+
working-directory: source/examples/Basic/ios
|
|
102
|
+
|
|
103
|
+
- name: Rebuild cache detox
|
|
104
|
+
run: yarn detox rebuild-framework-cache
|
|
105
|
+
working-directory: source/examples/Basic
|
|
106
|
+
|
|
107
|
+
- name: Cache Detox build
|
|
108
|
+
id: cache-detox-build
|
|
109
|
+
uses: actions/cache@v3
|
|
110
|
+
with:
|
|
111
|
+
path: source/examples/Basic/ios/Pods
|
|
112
|
+
key: ${{ runner.os }}-detox-build
|
|
113
|
+
restore-keys: |
|
|
114
|
+
${{ runner.os }}-detox-build
|
|
115
|
+
|
|
116
|
+
- name: Detox build
|
|
117
|
+
run: yarn detox build --configuration ${{ env.DETOX_CONFIGURATION }}
|
|
118
|
+
working-directory: source/examples/Basic
|
|
119
|
+
|
|
120
|
+
- name: Detox test
|
|
121
|
+
run: |
|
|
122
|
+
yarn start &
|
|
123
|
+
METRO_BUNDLER_PID=$!
|
|
124
|
+
yarn detox test --configuration ${{ env.DETOX_CONFIGURATION }} e2e/ios --cleanup --headless --record-logs all
|
|
125
|
+
DETOX_EXIT_CODE=$?
|
|
126
|
+
kill $METRO_BUNDLER_PID
|
|
127
|
+
exit $DETOX_EXIT_CODE
|
|
128
|
+
working-directory: source/examples/Basic
|
|
129
|
+
|
|
130
|
+
- name: Upload artifacts
|
|
131
|
+
if: failure()
|
|
132
|
+
uses: actions/upload-artifact@v3
|
|
133
|
+
with:
|
|
134
|
+
name: detox-artifacts
|
|
135
|
+
path: artifacts
|
|
136
|
+
e2e-android:
|
|
137
|
+
runs-on: macos-latest
|
|
138
|
+
env:
|
|
139
|
+
DETOX_CONFIGURATION: android.emu.release
|
|
140
|
+
|
|
141
|
+
steps:
|
|
142
|
+
- name: Checkout repository
|
|
143
|
+
uses: actions/checkout@v3
|
|
144
|
+
with:
|
|
145
|
+
path: source
|
|
146
|
+
ref: '${{ inputs.ref }}'
|
|
147
|
+
|
|
148
|
+
- name: Setup Node.js
|
|
149
|
+
uses: actions/setup-node@v3
|
|
150
|
+
with:
|
|
151
|
+
node-version: "16"
|
|
152
|
+
|
|
153
|
+
- name: Cache node_modules
|
|
154
|
+
uses: actions/cache@v3
|
|
155
|
+
id: cache
|
|
156
|
+
with:
|
|
157
|
+
path: source/examples/Basic/node_modules
|
|
158
|
+
key: node-modules-${{ hashFiles('**/yarn.lock') }}
|
|
159
|
+
|
|
160
|
+
- name: Install Yarn dependencies
|
|
161
|
+
run: yarn install
|
|
162
|
+
working-directory: source/examples/Basic
|
|
163
|
+
|
|
164
|
+
- name: Setup Java
|
|
165
|
+
uses: actions/setup-java@v3
|
|
166
|
+
with:
|
|
167
|
+
cache: gradle
|
|
168
|
+
distribution: temurin
|
|
169
|
+
java-version: 11
|
|
170
|
+
|
|
171
|
+
- name: Update App Platform ID
|
|
172
|
+
working-directory: source/examples/Basic/config/
|
|
173
|
+
run: |
|
|
174
|
+
sed -i '' -e "s/ANDROID_PROD_APP_PLATFORM_ID/$BASIC_ANDROID_PROD_APP_PLATFORM_ID/" index.ts
|
|
175
|
+
env:
|
|
176
|
+
BASIC_ANDROID_PROD_APP_PLATFORM_ID: '${{ secrets.ANDROID_PROD_APP_PLATFORM_ID }}'
|
|
177
|
+
|
|
178
|
+
- name: Rebuild cache detox
|
|
179
|
+
run: yarn detox rebuild-framework-cache
|
|
180
|
+
working-directory: source/examples/Basic
|
|
181
|
+
|
|
182
|
+
- name: Cache Detox build
|
|
183
|
+
id: cache-detox-build
|
|
184
|
+
uses: actions/cache@v3
|
|
185
|
+
with:
|
|
186
|
+
path: source/examples/Basic/android/app/build
|
|
187
|
+
key: ${{ runner.os }}-detox-build
|
|
188
|
+
restore-keys: |
|
|
189
|
+
${{ runner.os }}-detox-build
|
|
190
|
+
|
|
191
|
+
- name: Detox build
|
|
192
|
+
run: |
|
|
193
|
+
rm -rf node_modules/react-native-nami-sdk/examples
|
|
194
|
+
yarn detox build --configuration ${{ env.DETOX_CONFIGURATION }}
|
|
195
|
+
working-directory: source/examples/Basic
|
|
196
|
+
|
|
197
|
+
- name: Create the Keystore
|
|
198
|
+
run: |
|
|
199
|
+
# import keystore from secrets
|
|
200
|
+
echo $KEYSTORE_BASE64 | base64 -d > $RUNNER_TEMP/my_production.keystore
|
|
201
|
+
env:
|
|
202
|
+
KEYSTORE_BASE64: '${{ secrets.KEY_STORE_BASE64 }}'
|
|
203
|
+
|
|
204
|
+
- name: Encode the keystore to base64
|
|
205
|
+
id: encode_keystore
|
|
206
|
+
run: |
|
|
207
|
+
echo "SIGNINGKEYBASE64=$(openssl base64 < $RUNNER_TEMP/my_production.keystore | tr -d '\n')" >> $GITHUB_ENV
|
|
208
|
+
|
|
209
|
+
- name: Sign APK
|
|
210
|
+
id: sign_apk
|
|
211
|
+
uses: r0adkll/sign-android-release@v1
|
|
212
|
+
with:
|
|
213
|
+
releaseDirectory: source/examples/Basic/android/app/build/outputs/apk/production/release
|
|
214
|
+
signingKeyBase64: ${{ env.SIGNINGKEYBASE64 }}
|
|
215
|
+
alias: ${{ secrets.KEY_ALIAS }}
|
|
216
|
+
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
|
|
217
|
+
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
|
218
|
+
|
|
219
|
+
- name: Sign AndroidTest APK for Detox
|
|
220
|
+
id: sign_androidTest_apk
|
|
221
|
+
uses: r0adkll/sign-android-release@v1
|
|
222
|
+
with:
|
|
223
|
+
releaseDirectory: source/examples/Basic/android/app/build/outputs/apk/androidTest/production/release/
|
|
224
|
+
signingKeyBase64: ${{ env.SIGNINGKEYBASE64 }}
|
|
225
|
+
alias: ${{ secrets.KEY_ALIAS }}
|
|
226
|
+
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
|
|
227
|
+
keyPassword: ${{ secrets.KEY_PASSWORD }}
|
|
228
|
+
|
|
229
|
+
- name: Get device name
|
|
230
|
+
id: device
|
|
231
|
+
run: node -e "console.log('AVD_NAME=' + require('./.detoxrc').devices.emulator.device.avdName)" >> $GITHUB_OUTPUT
|
|
232
|
+
working-directory: source/examples/Basic
|
|
233
|
+
|
|
234
|
+
# - name: Cache AVD snapshot
|
|
235
|
+
# uses: actions/cache@v3
|
|
236
|
+
# id: avd-cache
|
|
237
|
+
# with:
|
|
238
|
+
# path: |
|
|
239
|
+
# ~/.android/avd/*
|
|
240
|
+
# ~/.android/adb*
|
|
241
|
+
# key: avd-30-aosp-atd
|
|
242
|
+
#
|
|
243
|
+
# - name: Create AVD and generate snapshot for caching
|
|
244
|
+
# if: steps.avd-cache.outputs.cache-hit != 'true'
|
|
245
|
+
# uses: reactivecircus/android-emulator-runner@v2
|
|
246
|
+
# with:
|
|
247
|
+
# target: aosp_atd
|
|
248
|
+
# api-level: 30
|
|
249
|
+
# arch: x86
|
|
250
|
+
# channel: canary
|
|
251
|
+
# profile: pixel
|
|
252
|
+
# ram-size: 2048M
|
|
253
|
+
# heapSize: 576M
|
|
254
|
+
# # avd-name: ${{ steps.device.outputs.AVD_NAME }}
|
|
255
|
+
# avd-name: Pixel_3a_API_30_AOSP
|
|
256
|
+
# force-avd-creation: false
|
|
257
|
+
# emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
|
|
258
|
+
# disable-animations: false
|
|
259
|
+
# script: echo "Generated AVD snapshot for caching"
|
|
260
|
+
# working-directory: source/examples/Basic
|
|
261
|
+
|
|
262
|
+
- name: Detox test
|
|
263
|
+
uses: reactivecircus/android-emulator-runner@v2
|
|
264
|
+
with:
|
|
265
|
+
target: aosp_atd
|
|
266
|
+
api-level: 30
|
|
267
|
+
arch: x86
|
|
268
|
+
channel: canary
|
|
269
|
+
profile: pixel
|
|
270
|
+
avd-name: Pixel_4_API_30_AOSP
|
|
271
|
+
script: yarn detox test --configuration ${{ env.DETOX_CONFIGURATION }} e2e/android --headless --record-logs all
|
|
272
|
+
working-directory: source/examples/Basic
|
|
273
|
+
|
|
274
|
+
- name: Upload artifacts
|
|
275
|
+
if: failure()
|
|
276
|
+
uses: actions/upload-artifact@v3
|
|
277
|
+
with:
|
|
278
|
+
name: detox-artifacts
|
|
279
|
+
path: artifacts
|
package/.prettierrc.js
ADDED
|
@@ -115,7 +115,7 @@ class NamiBridgeModule(reactContext: ReactApplicationContext) :
|
|
|
115
115
|
} else {
|
|
116
116
|
Arguments.createArray()
|
|
117
117
|
}
|
|
118
|
-
val settingsList = mutableListOf("extendedClientInfo:react-native:3.0.
|
|
118
|
+
val settingsList = mutableListOf("extendedClientInfo:react-native:3.0.26")
|
|
119
119
|
namiCommandsReact?.toArrayList()?.filterIsInstance<String>()?.let { commandsFromReact ->
|
|
120
120
|
settingsList.addAll(commandsFromReact)
|
|
121
121
|
}
|
package/index.d.ts
CHANGED
|
@@ -1,20 +1,8 @@
|
|
|
1
|
-
export {Nami
|
|
2
|
-
export {NamiMLManager} from './src/NamiMLManager';
|
|
3
|
-
export {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export {
|
|
10
|
-
NamiCustomerManager,
|
|
11
|
-
CustomerJourneyState,
|
|
12
|
-
AccountStateAction,
|
|
13
|
-
} from './src/NamiCustomerManager';
|
|
14
|
-
export {
|
|
15
|
-
NamiEntitlementManager,
|
|
16
|
-
NamiEntitlement,
|
|
17
|
-
} from './src/NamiEntitlementManager';
|
|
18
|
-
export {NamiPurchaseManager, NamiPurchase} from './src/NamiPurchaseManager';
|
|
19
|
-
export {NamiPaywallManager} from './src/NamiPaywallManager';
|
|
20
|
-
export {NamiSKU} from './src/types';
|
|
1
|
+
export { Nami } from './src/Nami';
|
|
2
|
+
export { NamiMLManager } from './src/NamiMLManager';
|
|
3
|
+
export { NamiCampaignManager } from './src/NamiCampaignManager';
|
|
4
|
+
export { NamiCustomerManager } from './src/NamiCustomerManager';
|
|
5
|
+
export { NamiEntitlementManager } from './src/NamiEntitlementManager';
|
|
6
|
+
export { NamiPurchaseManager } from './src/NamiPurchaseManager';
|
|
7
|
+
export { NamiPaywallManager } from './src/NamiPaywallManager';
|
|
8
|
+
export * from './src/types';
|
package/index.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { Nami } from './src/Nami';
|
|
2
|
+
export { NamiMLManager } from './src/NamiMLManager';
|
|
3
|
+
export { NamiCampaignManager } from './src/NamiCampaignManager';
|
|
4
|
+
export { NamiCustomerManager } from './src/NamiCustomerManager';
|
|
5
|
+
export { NamiEntitlementManager } from './src/NamiEntitlementManager';
|
|
6
|
+
export { NamiPurchaseManager } from './src/NamiPurchaseManager';
|
|
7
|
+
export { NamiPaywallManager } from './src/NamiPaywallManager';
|
|
8
|
+
export * from './src/types';
|
package/ios/Nami.m
CHANGED
|
@@ -52,7 +52,7 @@ RCT_EXPORT_METHOD(configure: (NSDictionary *)configDict completion: (RCTResponse
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// Start commands with header iformation for Nami to let them know this is a React client.
|
|
55
|
-
NSMutableArray *namiCommandStrings = [NSMutableArray arrayWithArray:@[@"extendedClientInfo:react-native:3.0.
|
|
55
|
+
NSMutableArray *namiCommandStrings = [NSMutableArray arrayWithArray:@[@"extendedClientInfo:react-native:3.0.26"]];
|
|
56
56
|
|
|
57
57
|
// Add additional namiCommands app may have sent in.
|
|
58
58
|
NSObject *appCommandStrings = configDict[@"namiCommands"];
|
|
@@ -97,7 +97,7 @@ class RNNamiCampaignManager: RCTEventEmitter {
|
|
|
97
97
|
"segmentId": paywallEvent.segmentId,
|
|
98
98
|
"externalSegmentId": paywallEvent.externalSegmentId,
|
|
99
99
|
"action": actionString,
|
|
100
|
-
"skuId": paywallEvent.sku?.
|
|
100
|
+
"skuId": paywallEvent.sku?.skuId,
|
|
101
101
|
"purchaseError": errorSting,
|
|
102
102
|
"purchases": dictionaries,
|
|
103
103
|
"deeplinkUrl": paywallEvent.deeplinkUrl,
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nami-sdk",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.26",
|
|
4
4
|
"description": "React Native Module for Nami - Easy subscriptions & in-app purchases, with powerful built-in paywalls and A/B testing.",
|
|
5
|
-
"main": "index.
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"types": "index.d.ts",
|
|
6
7
|
"scripts": {
|
|
7
8
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
9
|
"android": "react-native run-android",
|
|
@@ -53,8 +54,11 @@
|
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@react-native-community/eslint-config": "^3.2.0",
|
|
57
|
+
"@types/react-native": "^0.72.2",
|
|
56
58
|
"@typescript-eslint/eslint-plugin": "^5.59.7",
|
|
57
59
|
"eslint": "^8.41.0",
|
|
60
|
+
"eslint-plugin-jest": "^27.2.2",
|
|
61
|
+
"@types/jest": "^29.5.2",
|
|
58
62
|
"prettier": "^2.8.7",
|
|
59
63
|
"react": "^17.0.2",
|
|
60
64
|
"react-native": "^0.65.2",
|
package/src/Nami.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { NativeModules } from 'react-native';
|
|
2
|
+
import { NamiConfiguration } from './types';
|
|
3
|
+
|
|
4
|
+
export const { NamiBridge } = NativeModules;
|
|
5
|
+
|
|
6
|
+
export interface INami {
|
|
7
|
+
configure: (
|
|
8
|
+
config: NamiConfiguration,
|
|
9
|
+
resultCallback?: (resultObject: { success: boolean }) => void,
|
|
10
|
+
) => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const Nami: INami = {
|
|
14
|
+
...NamiBridge,
|
|
15
|
+
configure: (
|
|
16
|
+
configureObj: NamiConfiguration,
|
|
17
|
+
resultCallback?: (resultObject: { success: boolean }) => void,
|
|
18
|
+
) => {
|
|
19
|
+
NamiBridge.configure(configureObj, resultCallback ?? (() => {}));
|
|
20
|
+
},
|
|
21
|
+
};
|
|
@@ -2,6 +2,7 @@ import { EmitterSubscription } from "react-native";
|
|
|
2
2
|
import { NamiPurchase } from "./NamiPurchaseManager";
|
|
3
3
|
import { NamiPaywallAction } from "./NamiPaywallManager";
|
|
4
4
|
import { NamiSKU } from "./types";
|
|
5
|
+
import { NamiPaywallAction, NamiPurchase } from "./types";
|
|
5
6
|
|
|
6
7
|
export const NamiCampaignManager: {
|
|
7
8
|
allCampaigns: () => Promise<Array<NamiCampaign>>;
|
|
@@ -32,7 +33,7 @@ export const NamiCampaignManager: {
|
|
|
32
33
|
) => void;
|
|
33
34
|
refresh: () => void;
|
|
34
35
|
registerAvailableCampaignsHandler: (
|
|
35
|
-
|
|
36
|
+
callback: (availableCampaigns: NamiCampaign[]) => void
|
|
36
37
|
) => EmitterSubscription["remove"];
|
|
37
38
|
};
|
|
38
39
|
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NativeModules,
|
|
3
|
+
NativeEventEmitter,
|
|
4
|
+
EmitterSubscription,
|
|
5
|
+
} from 'react-native';
|
|
6
|
+
import {
|
|
7
|
+
LaunchCampaignError,
|
|
8
|
+
NamiCampaign,
|
|
9
|
+
NamiPaywallAction,
|
|
10
|
+
NamiPurchase,
|
|
11
|
+
PaywallLaunchContext,
|
|
12
|
+
} from './types';
|
|
13
|
+
|
|
14
|
+
export const { RNNamiCampaignManager } = NativeModules;
|
|
15
|
+
|
|
16
|
+
export enum NamiCampaignManagerEvents {
|
|
17
|
+
ResultCampaign = 'ResultCampaign',
|
|
18
|
+
AvailableCampaignsChanged = 'AvailableCampaignsChanged',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const searchString_Nami = 'NAMI_';
|
|
22
|
+
|
|
23
|
+
interface ICampaignManager {
|
|
24
|
+
launchSubscription: EmitterSubscription | undefined;
|
|
25
|
+
emitter: NativeEventEmitter;
|
|
26
|
+
allCampaigns: () => Promise<Array<NamiCampaign>>;
|
|
27
|
+
isCampaignAvailable(campaignSource: string | null): Promise<boolean>;
|
|
28
|
+
launch: (
|
|
29
|
+
label?: string,
|
|
30
|
+
withUrl?: string,
|
|
31
|
+
context?: PaywallLaunchContext,
|
|
32
|
+
resultCallback?: (success: boolean, error?: LaunchCampaignError) => void,
|
|
33
|
+
actionCallback?: (
|
|
34
|
+
action: NamiPaywallAction,
|
|
35
|
+
campaignId: string,
|
|
36
|
+
paywallId: string,
|
|
37
|
+
campaignName?: string,
|
|
38
|
+
campaignType?: string,
|
|
39
|
+
campaignLabel?: string,
|
|
40
|
+
campaignUrl?: string,
|
|
41
|
+
paywallName?: string,
|
|
42
|
+
segmentId?: string,
|
|
43
|
+
externalSegmentId?: string,
|
|
44
|
+
deeplinkUrl?: string,
|
|
45
|
+
skuId?: string,
|
|
46
|
+
componentChangeId?: string,
|
|
47
|
+
componentChangeName?: string,
|
|
48
|
+
purchaseError?: string,
|
|
49
|
+
purchases?: NamiPurchase[],
|
|
50
|
+
) => void,
|
|
51
|
+
) => void;
|
|
52
|
+
refresh: () => void;
|
|
53
|
+
registerAvailableCampaignsHandler: (
|
|
54
|
+
callback: (availableCampaigns: NamiCampaign[]) => void,
|
|
55
|
+
) => EmitterSubscription['remove'];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export const NamiCampaignManager: ICampaignManager = {
|
|
59
|
+
launchSubscription: undefined,
|
|
60
|
+
emitter: new NativeEventEmitter(RNNamiCampaignManager),
|
|
61
|
+
...RNNamiCampaignManager,
|
|
62
|
+
launch(label, withUrl, context, resultCallback, actionCallback) {
|
|
63
|
+
if (this.launchSubscription) {
|
|
64
|
+
this.launchSubscription.remove();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this.launchSubscription = this.emitter.addListener(
|
|
68
|
+
NamiCampaignManagerEvents.ResultCampaign,
|
|
69
|
+
body => {
|
|
70
|
+
body.action = body.action.startsWith(searchString_Nami)
|
|
71
|
+
? body.action.substring(5, body.action.length)
|
|
72
|
+
: body.action;
|
|
73
|
+
|
|
74
|
+
const {
|
|
75
|
+
action,
|
|
76
|
+
campaignId,
|
|
77
|
+
paywallId,
|
|
78
|
+
campaignName,
|
|
79
|
+
campaignType,
|
|
80
|
+
campaignLabel,
|
|
81
|
+
campaignUrl,
|
|
82
|
+
paywallName,
|
|
83
|
+
segmentId,
|
|
84
|
+
externalSegmentId,
|
|
85
|
+
deeplinkUrl,
|
|
86
|
+
skuId,
|
|
87
|
+
componentChangeId,
|
|
88
|
+
componentChangeName,
|
|
89
|
+
purchaseError,
|
|
90
|
+
purchases,
|
|
91
|
+
} = body;
|
|
92
|
+
if (actionCallback) {
|
|
93
|
+
actionCallback(
|
|
94
|
+
action,
|
|
95
|
+
campaignId,
|
|
96
|
+
paywallId,
|
|
97
|
+
campaignName,
|
|
98
|
+
campaignType,
|
|
99
|
+
campaignLabel,
|
|
100
|
+
campaignUrl,
|
|
101
|
+
paywallName,
|
|
102
|
+
segmentId,
|
|
103
|
+
externalSegmentId,
|
|
104
|
+
deeplinkUrl,
|
|
105
|
+
skuId,
|
|
106
|
+
componentChangeId,
|
|
107
|
+
componentChangeName,
|
|
108
|
+
purchaseError,
|
|
109
|
+
purchases,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
);
|
|
114
|
+
RNNamiCampaignManager.launch(
|
|
115
|
+
label ?? null,
|
|
116
|
+
withUrl ?? null,
|
|
117
|
+
context ?? null,
|
|
118
|
+
resultCallback ?? (() => {}),
|
|
119
|
+
actionCallback ?? (() => {}),
|
|
120
|
+
);
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
isCampaignAvailable: campaignSource => {
|
|
124
|
+
return RNNamiCampaignManager.isCampaignAvailable(campaignSource ?? null);
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
registerAvailableCampaignsHandler(callback) {
|
|
128
|
+
if (typeof callback !== 'function') {
|
|
129
|
+
throw new Error('Expected callback to be a function.');
|
|
130
|
+
}
|
|
131
|
+
const subscription = this.emitter.addListener(
|
|
132
|
+
NamiCampaignManagerEvents.AvailableCampaignsChanged,
|
|
133
|
+
callback,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
RNNamiCampaignManager.registerAvailableCampaignsHandler();
|
|
137
|
+
return () => {
|
|
138
|
+
if (subscription) {
|
|
139
|
+
subscription.remove();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
},
|
|
143
|
+
};
|