@jazadev/react-native 0.1.0
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/README.md +241 -0
- package/dist/index.cjs +1988 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +271 -0
- package/dist/index.d.ts +271 -0
- package/dist/index.js +1987 -0
- package/dist/index.js.map +1 -0
- package/package.json +77 -0
package/README.md
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# `@jazadev/react-native`
|
|
2
|
+
|
|
3
|
+
Official React Native / Expo SDK for Jaza.
|
|
4
|
+
|
|
5
|
+
Use this in your **mobile app** with your publishable key (`jz_*_pk_*`) and a short-lived top-up token from **your backend**. Never put your secret key in the app.
|
|
6
|
+
|
|
7
|
+
Server-side calls (create customer, issue top-up JWT, read balance) use [`@jazadev/node`](https://www.npmjs.com/package/@jazadev/node) or any HTTP client with your secret key.
|
|
8
|
+
|
|
9
|
+
### Try the sample
|
|
10
|
+
|
|
11
|
+
A private Expo app lives in [`example/`](./example). It demos sign-in (local JSON + Jaza customer), balance, and top-up with Expo Router API routes. See [example/README.md](./example/README.md). It is **not** published with this package.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @jazadev/react-native
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Install peer dependencies (Expo):
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx expo install react react-native react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-screens @gorhom/bottom-sheet @expo/vector-icons
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 2. Expo config
|
|
30
|
+
|
|
31
|
+
Add this so the phone number field stays visible when the keyboard opens on Android (the SDK also sets `android_keyboardInputMode="adjustResize"` on the bottom sheet, but the Activity must resize too).
|
|
32
|
+
|
|
33
|
+
**`app.json`**
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"expo": {
|
|
38
|
+
"android": {
|
|
39
|
+
"softwareKeyboardLayoutMode": "resize"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**`app.config.js`**
|
|
46
|
+
|
|
47
|
+
```js
|
|
48
|
+
export default {
|
|
49
|
+
expo: {
|
|
50
|
+
android: {
|
|
51
|
+
softwareKeyboardLayoutMode: 'resize',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## 3. Provider setup (app root)
|
|
60
|
+
|
|
61
|
+
Wrap your app with these providers, outermost first:
|
|
62
|
+
|
|
63
|
+
1. `GestureHandlerRootView` — gestures for bottom sheets
|
|
64
|
+
2. `JazaProvider` — Jaza state, theme, and checkout sheet
|
|
65
|
+
|
|
66
|
+
(`BottomSheetModalProvider` is not required; the SDK uses React Native `Modal` + `@gorhom/bottom-sheet`.)
|
|
67
|
+
|
|
68
|
+
`getBalance` is defined here once; `JazaBalanceWidget` and the offer step both use it.
|
|
69
|
+
|
|
70
|
+
### Expo Router (`app/_layout.tsx`)
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { Stack } from 'expo-router';
|
|
74
|
+
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
75
|
+
import { JazaProvider } from '@jazadev/react-native';
|
|
76
|
+
|
|
77
|
+
const API_BASE = process.env.EXPO_PUBLIC_API_URL!;
|
|
78
|
+
|
|
79
|
+
export default function RootLayout() {
|
|
80
|
+
return (
|
|
81
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
82
|
+
<JazaProvider
|
|
83
|
+
publishableKey={process.env.EXPO_PUBLIC_JAZA_PUBLISHABLE_KEY!}
|
|
84
|
+
getBalance={async () => {
|
|
85
|
+
const res = await fetch(`${API_BASE}/jaza/balance`, {
|
|
86
|
+
credentials: 'include',
|
|
87
|
+
});
|
|
88
|
+
const data = await res.json();
|
|
89
|
+
return data.balanceCredits as number;
|
|
90
|
+
}}
|
|
91
|
+
onTopUpComplete={({ credits }) => {
|
|
92
|
+
console.log('Top-up completed', credits);
|
|
93
|
+
}}
|
|
94
|
+
theme="system"
|
|
95
|
+
>
|
|
96
|
+
<Stack />
|
|
97
|
+
</JazaProvider>
|
|
98
|
+
</GestureHandlerRootView>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Alternative: classic `App.tsx`
|
|
104
|
+
|
|
105
|
+
Same wrappers; replace `<Stack />` with your navigation tree or screen components.
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
109
|
+
import { JazaProvider } from '@jazadev/react-native';
|
|
110
|
+
import { HomeScreen } from './screens/HomeScreen';
|
|
111
|
+
|
|
112
|
+
export default function App() {
|
|
113
|
+
return (
|
|
114
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
115
|
+
<JazaProvider
|
|
116
|
+
publishableKey={process.env.EXPO_PUBLIC_JAZA_PUBLISHABLE_KEY!}
|
|
117
|
+
getBalance={async () => {
|
|
118
|
+
const res = await fetch(`${process.env.EXPO_PUBLIC_API_URL}/jaza/balance`);
|
|
119
|
+
return (await res.json()).balanceCredits;
|
|
120
|
+
}}
|
|
121
|
+
theme="system"
|
|
122
|
+
>
|
|
123
|
+
<HomeScreen />
|
|
124
|
+
</JazaProvider>
|
|
125
|
+
</GestureHandlerRootView>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## 4. Show balance — `JazaBalanceWidget`
|
|
133
|
+
|
|
134
|
+
Render on any screen inside `JazaProvider`. It calls `getBalance` on mount and after a successful top-up.
|
|
135
|
+
|
|
136
|
+
**`app/(tabs)/index.tsx`** (or your home screen)
|
|
137
|
+
|
|
138
|
+
```tsx
|
|
139
|
+
import { View } from 'react-native';
|
|
140
|
+
import { JazaBalanceWidget } from '@jazadev/react-native';
|
|
141
|
+
|
|
142
|
+
export default function HomeScreen() {
|
|
143
|
+
return (
|
|
144
|
+
<View style={{ padding: 20 }}>
|
|
145
|
+
<JazaBalanceWidget />
|
|
146
|
+
</View>
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Your server** (uses `@jazadev/node` with the secret key):
|
|
152
|
+
|
|
153
|
+
```ts
|
|
154
|
+
import { Jaza } from '@jazadev/node';
|
|
155
|
+
|
|
156
|
+
const jaza = new Jaza({ secretKey: process.env.JAZA_SECRET_KEY!, publicKey: process.env.JAZA_PUBLIC_KEY! });
|
|
157
|
+
|
|
158
|
+
// GET /jaza/balance — resolve customerId from your auth session
|
|
159
|
+
app.get('/jaza/balance', async (req, res) => {
|
|
160
|
+
const wallet = await jaza.getBalance({ customerId: req.user.jazaCustomerId });
|
|
161
|
+
res.json({ balanceCredits: wallet.balanceCredits });
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 5. Top up — `JazaTopUpButton`
|
|
168
|
+
|
|
169
|
+
Add the button on the same screen (or elsewhere under `JazaProvider`). It does **not** open the sheet until `onRequestToken` returns a JWT.
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
import { View } from 'react-native';
|
|
173
|
+
import { JazaBalanceWidget, JazaTopUpButton } from '@jazadev/react-native';
|
|
174
|
+
|
|
175
|
+
const API_BASE = process.env.EXPO_PUBLIC_API_URL!;
|
|
176
|
+
|
|
177
|
+
export default function HomeScreen() {
|
|
178
|
+
return (
|
|
179
|
+
<View style={{ padding: 20, gap: 16 }}>
|
|
180
|
+
<JazaBalanceWidget />
|
|
181
|
+
<JazaTopUpButton
|
|
182
|
+
label="Top up credits"
|
|
183
|
+
onRequestToken={async () => {
|
|
184
|
+
const res = await fetch(`${API_BASE}/jaza/top-up-token`, {
|
|
185
|
+
method: 'POST',
|
|
186
|
+
credentials: 'include',
|
|
187
|
+
});
|
|
188
|
+
if (!res.ok) throw new Error('Could not start top-up');
|
|
189
|
+
const data = await res.json();
|
|
190
|
+
return data.token as string;
|
|
191
|
+
}}
|
|
192
|
+
/>
|
|
193
|
+
</View>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Your server**:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
// POST /jaza/top-up-token
|
|
202
|
+
app.post('/jaza/top-up-token', async (req, res) => {
|
|
203
|
+
const session = await jaza.topUp({ customerId: req.user.jazaCustomerId });
|
|
204
|
+
res.json({ token: session.token });
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Optional props:
|
|
209
|
+
|
|
210
|
+
- `label` — button text (default: `"Top up credits"`)
|
|
211
|
+
- `style` — `ViewStyle` for the button container
|
|
212
|
+
|
|
213
|
+
`JazaProvider` also accepts `onTopUpComplete` for when a payment succeeds.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## 6. What happens after the user taps Top up
|
|
218
|
+
|
|
219
|
+
1. App calls your backend → you return a top-up JWT (`jaza.topUp`)
|
|
220
|
+
2. Bottom sheet opens → bundles and current balance
|
|
221
|
+
3. User picks a bundle → enters phone, country, currency → sees quote
|
|
222
|
+
4. User confirms → payment starts → SDK polls until success or failure
|
|
223
|
+
5. Balance refreshes via `getBalance`; sheet shows success or retry
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Exports
|
|
228
|
+
|
|
229
|
+
| Export | Description |
|
|
230
|
+
|--------|-------------|
|
|
231
|
+
| `JazaProvider` | Context, theme, sheet, API client |
|
|
232
|
+
| `JazaBalanceWidget` | Credits balance card |
|
|
233
|
+
| `JazaTopUpButton` | Opens sheet after `onRequestToken` |
|
|
234
|
+
| `useJaza` | Advanced access to sheet state |
|
|
235
|
+
| `PublicClient` | Low-level public API client |
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## License
|
|
240
|
+
|
|
241
|
+
MIT
|