react-native-nami-sdk 3.4.0-dev.202604020517 → 3.4.0-dev.202605111922
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/android/build.gradle +2 -2
- package/android/src/main/java/com/namiml/reactnative/NamiBridgeModule.kt +33 -10
- package/dist/specs/NativeNami.d.ts +1 -0
- package/dist/src/Nami.d.ts +1 -0
- package/dist/src/version.d.ts +1 -1
- package/ios/Nami.m +2 -0
- package/ios/Nami.swift +8 -0
- package/package.json +7 -1
- package/react-native-nami-sdk.podspec +1 -1
- package/specs/NativeNami.ts +1 -0
- package/src/Nami.ts +3 -0
- package/src/version.ts +1 -1
- package/ARCHITECTURE.md +0 -166
- package/CLAUDE.md +0 -97
package/android/build.gradle
CHANGED
|
@@ -85,8 +85,8 @@ dependencies {
|
|
|
85
85
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
86
86
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
|
87
87
|
|
|
88
|
-
playImplementation "com.namiml:sdk-android:3.4.0-dev.
|
|
89
|
-
amazonImplementation "com.namiml:sdk-amazon:3.4.0-dev.
|
|
88
|
+
playImplementation "com.namiml:sdk-android:3.4.0-dev.202605111922"
|
|
89
|
+
amazonImplementation "com.namiml:sdk-amazon:3.4.0-dev.202605111922"
|
|
90
90
|
|
|
91
91
|
implementation "com.facebook.react:react-native:+" // From node_modules
|
|
92
92
|
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:2.0.4"
|
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
package com.namiml.reactnative
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import android.util.Log
|
|
4
|
+
import com.facebook.react.bridge.Arguments
|
|
5
|
+
import com.facebook.react.bridge.Promise
|
|
6
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
8
|
+
import com.facebook.react.bridge.ReactMethod
|
|
9
|
+
import com.facebook.react.bridge.ReadableMap
|
|
4
10
|
import com.facebook.react.module.annotations.ReactModule
|
|
5
11
|
import com.facebook.react.turbomodule.core.interfaces.TurboModule
|
|
6
12
|
import com.namiml.Nami
|
|
7
13
|
import com.namiml.NamiConfiguration
|
|
8
14
|
import com.namiml.NamiLanguageCode
|
|
9
15
|
import com.namiml.NamiLogLevel
|
|
10
|
-
import android.util.Log
|
|
11
16
|
|
|
12
17
|
@ReactModule(name = NamiBridgeModule.NAME)
|
|
13
18
|
class NamiBridgeModule internal constructor(
|
|
14
|
-
private val context: ReactApplicationContext
|
|
15
|
-
) : ReactContextBaseJavaModule(context),
|
|
16
|
-
|
|
19
|
+
private val context: ReactApplicationContext,
|
|
20
|
+
) : ReactContextBaseJavaModule(context),
|
|
21
|
+
TurboModule {
|
|
17
22
|
companion object {
|
|
18
23
|
const val NAME = "RNNami"
|
|
19
24
|
|
|
@@ -41,7 +46,10 @@ class NamiBridgeModule internal constructor(
|
|
|
41
46
|
}
|
|
42
47
|
|
|
43
48
|
@ReactMethod
|
|
44
|
-
fun configure(
|
|
49
|
+
fun configure(
|
|
50
|
+
configDict: ReadableMap,
|
|
51
|
+
promise: Promise,
|
|
52
|
+
) {
|
|
45
53
|
logNewArchitectureStatus()
|
|
46
54
|
|
|
47
55
|
val appPlatformID = configDict.getString(CONFIG_MAP_PLATFORM_ID_KEY) ?: PLATFORM_ID_ERROR_VALUE
|
|
@@ -55,7 +63,8 @@ class NamiBridgeModule internal constructor(
|
|
|
55
63
|
}
|
|
56
64
|
|
|
57
65
|
if (configDict.hasKey(CONFIG_MAP_DEVELOPMENT_MODE_KEY) &&
|
|
58
|
-
configDict.getBoolean(CONFIG_MAP_DEVELOPMENT_MODE_KEY)
|
|
66
|
+
configDict.getBoolean(CONFIG_MAP_DEVELOPMENT_MODE_KEY)
|
|
67
|
+
) {
|
|
59
68
|
builder.developmentMode = true
|
|
60
69
|
}
|
|
61
70
|
|
|
@@ -79,9 +88,10 @@ class NamiBridgeModule internal constructor(
|
|
|
79
88
|
|
|
80
89
|
context.runOnUiQueueThread {
|
|
81
90
|
Nami.configure(builder.build()) { result ->
|
|
82
|
-
val resultMap =
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
val resultMap =
|
|
92
|
+
Arguments.createMap().apply {
|
|
93
|
+
putBoolean("success", result)
|
|
94
|
+
}
|
|
85
95
|
promise.resolve(resultMap)
|
|
86
96
|
}
|
|
87
97
|
}
|
|
@@ -92,6 +102,19 @@ class NamiBridgeModule internal constructor(
|
|
|
92
102
|
Log.d("RNNami", "New Architecture is ${if (isNewArch) "ENABLED" else "DISABLED"}")
|
|
93
103
|
}
|
|
94
104
|
|
|
105
|
+
@ReactMethod
|
|
106
|
+
fun reset(promise: Promise) {
|
|
107
|
+
context.runOnUiQueueThread {
|
|
108
|
+
try {
|
|
109
|
+
Nami.reset(context.applicationContext)
|
|
110
|
+
promise.resolve(null)
|
|
111
|
+
} catch (e: Throwable) {
|
|
112
|
+
promise.reject("reset_failed", e)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
95
117
|
@ReactMethod fun addListener(eventName: String?) {}
|
|
118
|
+
|
|
96
119
|
@ReactMethod fun removeListeners(count: Int?) {}
|
|
97
120
|
}
|
package/dist/src/Nami.d.ts
CHANGED
package/dist/src/version.d.ts
CHANGED
package/ios/Nami.m
CHANGED
|
@@ -17,6 +17,8 @@ RCT_EXTERN_METHOD(sdkConfigured:(RCTPromiseResolveBlock)resolve
|
|
|
17
17
|
|
|
18
18
|
RCT_EXTERN_METHOD(sdkVersion:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
19
19
|
|
|
20
|
+
RCT_EXTERN_METHOD(reset:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
|
|
21
|
+
|
|
20
22
|
+ (BOOL)requiresMainQueueSetup {
|
|
21
23
|
return NO;
|
|
22
24
|
}
|
package/ios/Nami.swift
CHANGED
|
@@ -92,6 +92,14 @@ class RNNami: NSObject {
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
@objc(reset:rejecter:)
|
|
96
|
+
func reset(resolve: @escaping RCTPromiseResolveBlock, reject _: @escaping RCTPromiseRejectBlock) {
|
|
97
|
+
Nami.reset()
|
|
98
|
+
DispatchQueue.main.async {
|
|
99
|
+
resolve(nil)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
95
103
|
func isNewArchitectureEnabled() -> Bool {
|
|
96
104
|
#if RCT_NEW_ARCH_ENABLED
|
|
97
105
|
return true
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-nami-sdk",
|
|
3
|
-
"version": "3.4.0-dev.
|
|
3
|
+
"version": "3.4.0-dev.202605111922",
|
|
4
4
|
"description": "React Native SDK for Nami - No-code paywall and onboarding flows with A/B testing.",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -63,9 +63,15 @@
|
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
|
+
"@namiml/expo-nami-iap": "3.4.0-dev.202605111922",
|
|
66
67
|
"react": ">=18",
|
|
67
68
|
"react-native": ">=0.73"
|
|
68
69
|
},
|
|
70
|
+
"peerDependenciesMeta": {
|
|
71
|
+
"@namiml/expo-nami-iap": {
|
|
72
|
+
"optional": true
|
|
73
|
+
}
|
|
74
|
+
},
|
|
69
75
|
"devDependencies": {
|
|
70
76
|
"@react-native/eslint-config": "^0.80.0",
|
|
71
77
|
"@types/jest": "^29.5.2",
|
|
@@ -21,7 +21,7 @@ Pod::Spec.new do |s|
|
|
|
21
21
|
s.requires_arc = true
|
|
22
22
|
s.swift_version = '5.0' # or your supported version
|
|
23
23
|
|
|
24
|
-
s.dependency 'Nami', '3.4.0-dev.
|
|
24
|
+
s.dependency 'Nami', '3.4.0-dev.202605111922'
|
|
25
25
|
|
|
26
26
|
pod_target_xcconfig = {
|
|
27
27
|
'DEFINES_MODULE' => 'YES',
|
package/specs/NativeNami.ts
CHANGED
package/src/Nami.ts
CHANGED
package/src/version.ts
CHANGED
package/ARCHITECTURE.md
DELETED
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
# React Native SDK Architecture
|
|
2
|
-
|
|
3
|
-
The Nami React Native SDK (`react-native-nami-sdk`) is a TypeScript bridge layer that exposes native Android and iOS SDK functionality to React Native applications via TurboModules.
|
|
4
|
-
|
|
5
|
-
## Build System
|
|
6
|
-
|
|
7
|
-
- **Language:** TypeScript 5 (strict mode), Kotlin (Android bridge), Swift (iOS bridge)
|
|
8
|
-
- **Package Manager:** npm
|
|
9
|
-
- **TypeScript Output:** Declaration files only (`emitDeclarationOnly`)
|
|
10
|
-
- **Native Code Generation:** React Native Codegen (TurboModule specs)
|
|
11
|
-
- **Linting:** ESLint with @react-native config, Prettier
|
|
12
|
-
|
|
13
|
-
### Native Dependencies
|
|
14
|
-
|
|
15
|
-
| Platform | SDK |
|
|
16
|
-
|----------|-----|
|
|
17
|
-
| Android (Google Play) | `com.namiml:sdk-android` |
|
|
18
|
-
| Android (Amazon) | `com.namiml:sdk-amazon` |
|
|
19
|
-
| iOS/tvOS | `Nami` CocoaPod |
|
|
20
|
-
|
|
21
|
-
## Directory Structure
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
sdk/react-native/
|
|
25
|
-
├── src/ # TypeScript bridge layer
|
|
26
|
-
│ ├── index.ts # Main exports
|
|
27
|
-
│ ├── types.ts # Type definitions
|
|
28
|
-
│ ├── transformers.ts # Data transformation utilities
|
|
29
|
-
│ ├── version.ts # Auto-generated version constant
|
|
30
|
-
│ ├── Nami.ts # Core SDK initialization
|
|
31
|
-
│ ├── NamiPaywallManager.ts # Paywall display/events
|
|
32
|
-
│ ├── NamiCampaignManager.ts # Campaign management
|
|
33
|
-
│ ├── NamiCustomerManager.ts # Customer identity
|
|
34
|
-
│ ├── NamiEntitlementManager.ts # Entitlement access
|
|
35
|
-
│ ├── NamiPurchaseManager.ts # Purchase operations
|
|
36
|
-
│ ├── NamiFlowManager.ts # Flow management
|
|
37
|
-
│ └── NamiOverlayControl.tsx # React component for overlay UI
|
|
38
|
-
├── specs/ # TurboModule native interface specs
|
|
39
|
-
├── android/ # Kotlin native bridge modules
|
|
40
|
-
│ └── src/main/java/com/namiml/reactnative/
|
|
41
|
-
├── ios/ # Swift + Objective-C native bridge
|
|
42
|
-
├── dist/ # Built .d.ts type declarations
|
|
43
|
-
├── examples/
|
|
44
|
-
│ ├── Basic/ # Full-featured sample (with Detox e2e)
|
|
45
|
-
│ └── TestNamiTV/ # tvOS sample
|
|
46
|
-
├── build-utils/ # Version management scripts
|
|
47
|
-
└── scripts/ # Version generation
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Bridge Architecture
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
JavaScript (React Native)
|
|
54
|
-
|
|
|
55
|
-
TurboModule TypeScript Specs (/specs)
|
|
56
|
-
|
|
|
57
|
-
Native Bridge Modules (Kotlin + Swift)
|
|
58
|
-
|
|
|
59
|
-
Native SDKs (com.namiml:sdk-android / Nami CocoaPod)
|
|
60
|
-
|
|
|
61
|
-
Platform APIs (Google Play Billing / StoreKit)
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
The React Native SDK is a **thin bridge** - it does NOT reimplement networking, IAP handling, paywall rendering, entitlement validation, or purchase tracking. All business logic lives in the native SDKs.
|
|
65
|
-
|
|
66
|
-
## Manager Classes
|
|
67
|
-
|
|
68
|
-
Each TypeScript manager wraps a corresponding TurboModule:
|
|
69
|
-
|
|
70
|
-
| Manager | Key Methods |
|
|
71
|
-
|---------|-------------|
|
|
72
|
-
| `Nami` | `configure()`, `sdkConfigured()`, `sdkVersion()` |
|
|
73
|
-
| `NamiPaywallManager` | `buySkuComplete()`, handler registration (buy, close, sign-in, restore, deeplink) |
|
|
74
|
-
| `NamiCampaignManager` | `launch()`, `allCampaigns()`, `isCampaignAvailable()`, `isFlow()`, `refresh()`, `getProductGroups()` |
|
|
75
|
-
| `NamiCustomerManager` | `login()`, `logout()`, `journeyState()`, `setCustomerAttribute()`, `setAnonymousMode()`, `deviceId()` |
|
|
76
|
-
| `NamiEntitlementManager` | `active()`, `isEntitlementActive()`, `refresh()`, `clearProvisionalEntitlementGrants()` |
|
|
77
|
-
| `NamiPurchaseManager` | `allPurchases()`, `skuPurchased()`, `restorePurchases()`, `presentCodeRedemptionSheet()` |
|
|
78
|
-
| `NamiFlowManager` | `pause()`, `resume()`, `finish()`, `isFlowOpen()`, `registerStepHandoff()` |
|
|
79
|
-
| `NamiOverlayControl` | `presentOverlay()`, `finishOverlay()`, React `NamiOverlayHost` component |
|
|
80
|
-
|
|
81
|
-
## Native Bridge Modules
|
|
82
|
-
|
|
83
|
-
### Android (`android/` - Kotlin)
|
|
84
|
-
|
|
85
|
-
- **NamiBridgePackage.java** - TurboReactPackage registering all modules
|
|
86
|
-
- **NamiBridgeModule.kt** - `RNNami` core configuration
|
|
87
|
-
- **NamiCampaignManagerBridgeModule.kt** - Campaign bridge
|
|
88
|
-
- **NamiPaywallManagerBridgeModule.kt** - Paywall bridge
|
|
89
|
-
- **NamiPurchaseManagerBridge.kt** - Purchase bridge
|
|
90
|
-
- **NamiEntitlementManagerBridge.kt** - Entitlement bridge
|
|
91
|
-
- **NamiCustomerManagerBridge.kt** - Customer bridge
|
|
92
|
-
- **NamiFlowManagerBridge.kt** - Flow bridge
|
|
93
|
-
- **NamiOverlayControlBridge.kt** - Overlay + ReactOverlayActivity
|
|
94
|
-
- **NamiUtil.kt** - Data transformation (WritableMap/WritableArray)
|
|
95
|
-
|
|
96
|
-
Android supports two product flavors: `play` (Google Play) and `amazon` (Amazon Appstore).
|
|
97
|
-
|
|
98
|
-
### iOS (`ios/` - Swift)
|
|
99
|
-
|
|
100
|
-
Parallel Swift implementations for each bridge module, plus Objective-C `.m` files for Codegen/legacy architecture support.
|
|
101
|
-
|
|
102
|
-
## Type System (`src/types.ts`)
|
|
103
|
-
|
|
104
|
-
Key types exported to consumers:
|
|
105
|
-
|
|
106
|
-
- **NamiConfiguration** - SDK init params (appPlatformID, logLevel, language)
|
|
107
|
-
- **NamiSKU** - Product details with platform-specific pricing (Apple, Google, Amazon)
|
|
108
|
-
- **NamiPurchase** - Purchase record with timestamps, transaction IDs, source
|
|
109
|
-
- **NamiEntitlement** - Entitlement with active purchases and related SKUs
|
|
110
|
-
- **NamiCampaign** - Campaign metadata (name, rule type, form factors, segment)
|
|
111
|
-
- **CustomerJourneyState** - Subscription lifecycle flags
|
|
112
|
-
- **NamiPaywallEvent** - Comprehensive event (30+ actions)
|
|
113
|
-
- **NamiPaywallAction** - Enum: BUY_SKU, SELECT_SKU, RESTORE_PURCHASES, VIDEO_STARTED, etc.
|
|
114
|
-
|
|
115
|
-
## Testing
|
|
116
|
-
|
|
117
|
-
### Unit Tests
|
|
118
|
-
|
|
119
|
-
TypeScript unit tests using Jest + ts-jest, covering the pure data transformation layer in `src/transformers.ts`:
|
|
120
|
-
|
|
121
|
-
- **`parsePurchaseDates`** — converts native timestamp numbers to JS Date objects
|
|
122
|
-
- **`coerceSkuType`** — validates raw strings against `NamiSKUType` union, falls back to `'unknown'`
|
|
123
|
-
- **`mapToNamiPaywallAction`** — validates raw strings against the `NamiPaywallAction` enum (28 values), falls back to `UNKNOWN`
|
|
124
|
-
- **`parseEntitlements`** — transforms raw entitlement arrays, parsing nested purchase dates and defaulting missing SKU arrays
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
# From monorepo root
|
|
128
|
-
make test-react-native
|
|
129
|
-
|
|
130
|
-
# Or directly
|
|
131
|
-
cd sdk/react-native && npm test
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
Test files live in `src/__tests__/` and are excluded from TypeScript compilation output via `tsconfig.json`.
|
|
135
|
-
|
|
136
|
-
### E2E Tests
|
|
137
|
-
|
|
138
|
-
- Detox framework in `examples/Basic/e2e/` (iOS simulator + Android emulator)
|
|
139
|
-
- CI via GitHub Actions with artifact upload on failure
|
|
140
|
-
|
|
141
|
-
#### Local Native SDK Resolution
|
|
142
|
-
|
|
143
|
-
In the monorepo, native SDKs may not yet be published when e2e tests run against a PR. The workflow resolves this by building native SDKs locally before the Detox build:
|
|
144
|
-
|
|
145
|
-
**iOS** — The `NAMI_SDK_LOCAL_PATH` environment variable points to `sdk/apple/` in the monorepo. When set, each example app's Podfile overrides the published `Nami` CocoaPod with a local `:path` reference. CI builds the XCFramework first (`make build-apple`), then sets the env var so `pod install` picks up the local artifact.
|
|
146
|
-
|
|
147
|
-
**Android** — CI publishes the SDK to `mavenLocal` via `./gradlew sdk:publishPublicGooglePublicationToMavenLocal sdk:publishPublicAmazonPublicationToMavenLocal`. The example app's `build.gradle` already includes `mavenLocal()` in its repository list, so Gradle resolves the local artifact without any code changes.
|
|
148
|
-
|
|
149
|
-
Both approaches are temporary until dev release publishing is in place, at which point the pre-build steps and env var can be removed.
|
|
150
|
-
|
|
151
|
-
### Code Quality
|
|
152
|
-
|
|
153
|
-
- ESLint + TypeScript compilation checks in CI
|
|
154
|
-
|
|
155
|
-
## Peer Dependencies
|
|
156
|
-
|
|
157
|
-
- React >= 18
|
|
158
|
-
- React Native >= 0.73
|
|
159
|
-
|
|
160
|
-
## Architectural Patterns
|
|
161
|
-
|
|
162
|
-
- **Bridge/Adapter** - TypeScript wrappers over native TurboModules
|
|
163
|
-
- **Event Emitter** - NativeEventEmitter for real-time native-to-JS events
|
|
164
|
-
- **Thin Client** - All business logic delegated to native SDKs
|
|
165
|
-
- **Codegen** - TurboModule specs for typed native module generation (New Architecture)
|
|
166
|
-
- **Transformer** - Data conversion between native types and JS objects
|
package/CLAUDE.md
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# CLAUDE.md
|
|
2
|
-
|
|
3
|
-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
-
|
|
5
|
-
## Repository Overview
|
|
6
|
-
|
|
7
|
-
This is the Nami React Native SDK (`react-native-nami-sdk`), a TypeScript bridge layer that exposes native Android and iOS SDK functionality to React Native applications via TurboModules. The SDK is a thin bridge — all business logic lives in the native Android and Apple SDKs.
|
|
8
|
-
|
|
9
|
-
## Development Setup
|
|
10
|
-
|
|
11
|
-
### Prerequisites
|
|
12
|
-
- Node.js 20+
|
|
13
|
-
- npm
|
|
14
|
-
- For iOS bridge work: Xcode + CocoaPods
|
|
15
|
-
- For Android bridge work: Android Studio with JDK 17
|
|
16
|
-
|
|
17
|
-
### Install dependencies
|
|
18
|
-
```bash
|
|
19
|
-
cd sdk/react-native && npm install
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Build Commands
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
# From monorepo root
|
|
26
|
-
make build-react-native # Install npm dependencies
|
|
27
|
-
make test-react-native # Run Jest unit tests
|
|
28
|
-
make lint-react-native # Run pre-commit + ktlint checks
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
```bash
|
|
32
|
-
# Directly
|
|
33
|
-
cd sdk/react-native
|
|
34
|
-
npm test # Run Jest unit tests
|
|
35
|
-
npm run lint # ESLint
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Project Structure
|
|
39
|
-
|
|
40
|
-
- `src/` — TypeScript bridge layer (managers, types, transformers)
|
|
41
|
-
- `specs/` — TurboModule native interface specs (Codegen)
|
|
42
|
-
- `android/` — Kotlin native bridge modules
|
|
43
|
-
- `ios/` — Swift + Objective-C native bridge
|
|
44
|
-
- `dist/` — Built `.d.ts` type declarations (`emitDeclarationOnly`)
|
|
45
|
-
- `examples/Basic/` — Full-featured sample app with Detox e2e tests
|
|
46
|
-
- `examples/TestNamiTV/` — tvOS sample app
|
|
47
|
-
- `build-utils/` — Version management scripts
|
|
48
|
-
|
|
49
|
-
## Architecture
|
|
50
|
-
|
|
51
|
-
The SDK is a **thin bridge** — no business logic lives here. TypeScript managers wrap TurboModules; TurboModules call into the native Android/Apple SDKs.
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
JavaScript (React Native)
|
|
55
|
-
↓
|
|
56
|
-
TypeScript Managers (src/)
|
|
57
|
-
↓
|
|
58
|
-
TurboModule Specs (specs/)
|
|
59
|
-
↓
|
|
60
|
-
Native Bridge Modules (android/ + ios/)
|
|
61
|
-
↓
|
|
62
|
-
Native SDKs (com.namiml:sdk-android / Nami CocoaPod)
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Adding or changing bridge methods
|
|
66
|
-
|
|
67
|
-
1. Update the TurboModule spec in `specs/` (TypeScript interface)
|
|
68
|
-
2. Update the TypeScript manager in `src/`
|
|
69
|
-
3. Update the Kotlin bridge module in `android/`
|
|
70
|
-
4. Update the Swift bridge module in `ios/`
|
|
71
|
-
5. Run `npm run lint` and `make test-react-native` before committing
|
|
72
|
-
|
|
73
|
-
## Testing
|
|
74
|
-
|
|
75
|
-
### Unit Tests (Jest + ts-jest)
|
|
76
|
-
Tests cover the pure data transformation layer in `src/transformers.ts` and live in `src/__tests__/`.
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
make test-react-native
|
|
80
|
-
# or: cd sdk/react-native && npm test
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
### E2E Tests (Detox)
|
|
84
|
-
Located in `examples/Basic/e2e/`. Run via CI. See `ARCHITECTURE.md` for local native SDK resolution setup required before running e2e locally.
|
|
85
|
-
|
|
86
|
-
## Code Quality
|
|
87
|
-
|
|
88
|
-
- **ESLint** (`@react-native` config) + **Prettier** for TypeScript
|
|
89
|
-
- **ktlint** for Kotlin bridge code — run `ktlint -F` on changed `.kt` files before committing
|
|
90
|
-
- Pre-commit hooks via `.pre-commit-config.yaml`
|
|
91
|
-
|
|
92
|
-
## Key Files
|
|
93
|
-
|
|
94
|
-
- `src/index.ts` — Main exports
|
|
95
|
-
- `src/types.ts` — All public TypeScript types
|
|
96
|
-
- `src/transformers.ts` — Data transformation between native and JS types (unit-tested)
|
|
97
|
-
- `specs/` — TurboModule specs (source of truth for the native bridge contract)
|