@safercity/sdk-react-native 0.1.0 → 0.1.1
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 +87 -9
- package/package.json +1 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @safercity/sdk-react-native
|
|
2
2
|
|
|
3
|
-
React Native adapter for SaferCity SDK with expo-fetch streaming support.
|
|
3
|
+
React Native adapter for SaferCity SDK with expo-fetch streaming support and secure token storage.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -19,10 +19,9 @@ bun add @safercity/sdk-react-native @safercity/sdk-react @tanstack/react-query
|
|
|
19
19
|
## Quick Start
|
|
20
20
|
|
|
21
21
|
```tsx
|
|
22
|
-
import { createReactNativeClient
|
|
22
|
+
import { createReactNativeClient } from '@safercity/sdk-react-native';
|
|
23
23
|
import { SaferCityProvider } from '@safercity/sdk-react';
|
|
24
24
|
|
|
25
|
-
// Create client with React Native optimizations
|
|
26
25
|
const client = createReactNativeClient({
|
|
27
26
|
baseUrl: 'https://api.safercity.com',
|
|
28
27
|
token: userToken,
|
|
@@ -38,6 +37,76 @@ function App() {
|
|
|
38
37
|
}
|
|
39
38
|
```
|
|
40
39
|
|
|
40
|
+
## Authentication Modes
|
|
41
|
+
|
|
42
|
+
On mobile, **direct mode** is the most common pattern. Your app authenticates users with an external auth provider and passes the token to SaferCity:
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { SaferCityProvider } from '@safercity/sdk-react';
|
|
46
|
+
|
|
47
|
+
function App() {
|
|
48
|
+
return (
|
|
49
|
+
<SaferCityProvider
|
|
50
|
+
mode="direct"
|
|
51
|
+
baseUrl="https://api.safercity.com"
|
|
52
|
+
tenantId="tenant-123"
|
|
53
|
+
getAccessToken={() => getTokenFromAuthProvider()}
|
|
54
|
+
>
|
|
55
|
+
<Navigation />
|
|
56
|
+
</SaferCityProvider>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Proxy mode** also works if your mobile app communicates through a backend-for-frontend (BFF). Cookie mode is not typical for mobile apps.
|
|
62
|
+
|
|
63
|
+
## Secure Token Storage
|
|
64
|
+
|
|
65
|
+
For server-side OAuth flows on mobile (e.g., background token management), the SDK provides secure storage that auto-detects the best available option:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { createSecureTokenStorage, getStorageType } from '@safercity/sdk-react-native';
|
|
69
|
+
import { TokenManager } from '@safercity/sdk';
|
|
70
|
+
|
|
71
|
+
// Auto-detects: expo-secure-store > AsyncStorage > in-memory
|
|
72
|
+
const storage = createSecureTokenStorage();
|
|
73
|
+
|
|
74
|
+
const tokenManager = new TokenManager({
|
|
75
|
+
credentials: {
|
|
76
|
+
clientId: 'your-client-id',
|
|
77
|
+
clientSecret: 'your-client-secret',
|
|
78
|
+
},
|
|
79
|
+
storage,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Get token (auto-refreshes if expired)
|
|
83
|
+
const token = await tokenManager.getToken();
|
|
84
|
+
|
|
85
|
+
// Check what storage is being used
|
|
86
|
+
const type = getStorageType(); // 'secure-store' | 'async-storage' | 'memory'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Storage Priority
|
|
90
|
+
|
|
91
|
+
| Storage | Package | Security | Persistence |
|
|
92
|
+
|---------|---------|----------|-------------|
|
|
93
|
+
| `SecureStoreTokenStorage` | `expo-secure-store` | Encrypted (device keychain/keystore) | Yes |
|
|
94
|
+
| `AsyncStorageTokenStorage` | `@react-native-async-storage/async-storage` | Unencrypted | Yes |
|
|
95
|
+
| `InMemoryTokenStorage` | Built-in | N/A | No |
|
|
96
|
+
|
|
97
|
+
You can also use a specific storage class directly:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import {
|
|
101
|
+
SecureStoreTokenStorage,
|
|
102
|
+
AsyncStorageTokenStorage,
|
|
103
|
+
InMemoryTokenStorage,
|
|
104
|
+
} from '@safercity/sdk-react-native';
|
|
105
|
+
|
|
106
|
+
const storage = new SecureStoreTokenStorage();
|
|
107
|
+
await storage.waitForInit(); // wait for initial load from device storage
|
|
108
|
+
```
|
|
109
|
+
|
|
41
110
|
## Streaming Support
|
|
42
111
|
|
|
43
112
|
This package automatically uses `expo-fetch` for streaming when available (Expo SDK 52+).
|
|
@@ -45,7 +114,6 @@ This package automatically uses `expo-fetch` for streaming when available (Expo
|
|
|
45
114
|
```tsx
|
|
46
115
|
import { isStreamingSupported } from '@safercity/sdk-react-native';
|
|
47
116
|
|
|
48
|
-
// Check if streaming is supported
|
|
49
117
|
if (isStreamingSupported()) {
|
|
50
118
|
console.log('SSE streaming is available');
|
|
51
119
|
} else {
|
|
@@ -57,6 +125,7 @@ if (isStreamingSupported()) {
|
|
|
57
125
|
|
|
58
126
|
```tsx
|
|
59
127
|
import { usePanicStream } from '@safercity/sdk-react';
|
|
128
|
+
import { isStreamingSupported } from '@safercity/sdk-react-native';
|
|
60
129
|
|
|
61
130
|
function PanicTracker({ panicId }: { panicId: string }) {
|
|
62
131
|
const { data, isConnected, error } = usePanicStream(panicId, {
|
|
@@ -66,7 +135,6 @@ function PanicTracker({ panicId }: { panicId: string }) {
|
|
|
66
135
|
});
|
|
67
136
|
|
|
68
137
|
if (!isStreamingSupported()) {
|
|
69
|
-
// Fallback to polling
|
|
70
138
|
return <PollingPanicTracker panicId={panicId} />;
|
|
71
139
|
}
|
|
72
140
|
|
|
@@ -81,13 +149,11 @@ function PanicTracker({ panicId }: { panicId: string }) {
|
|
|
81
149
|
|
|
82
150
|
## Without Expo
|
|
83
151
|
|
|
84
|
-
For bare React Native projects without Expo, streaming will fall back to standard fetch.
|
|
85
|
-
SSE may have limited support depending on your React Native version.
|
|
152
|
+
For bare React Native projects without Expo, streaming will fall back to standard fetch. SSE may have limited support depending on your React Native version.
|
|
86
153
|
|
|
87
154
|
```tsx
|
|
88
155
|
import { createReactNativeClient } from '@safercity/sdk-react-native';
|
|
89
156
|
|
|
90
|
-
// You can provide a custom fetch implementation
|
|
91
157
|
const client = createReactNativeClient({
|
|
92
158
|
baseUrl: 'https://api.safercity.com',
|
|
93
159
|
token: userToken,
|
|
@@ -141,7 +207,19 @@ Returns `true` if expo-fetch is available and streaming is supported.
|
|
|
141
207
|
|
|
142
208
|
### getReactNativeFetch(customFetch?)
|
|
143
209
|
|
|
144
|
-
Returns the best available fetch implementation for the current environment.
|
|
210
|
+
Returns the best available fetch implementation for the current environment. Priority: expo-fetch > custom > global fetch.
|
|
211
|
+
|
|
212
|
+
### createReactNativeStreamAdapter(customFetch?)
|
|
213
|
+
|
|
214
|
+
Creates a `FetchStreamAdapter` using the best available fetch for the environment.
|
|
215
|
+
|
|
216
|
+
### createSecureTokenStorage()
|
|
217
|
+
|
|
218
|
+
Auto-detects and returns the best available token storage. Priority: expo-secure-store > AsyncStorage > in-memory.
|
|
219
|
+
|
|
220
|
+
### getStorageType()
|
|
221
|
+
|
|
222
|
+
Returns `'secure-store'` | `'async-storage'` | `'memory'` indicating what storage is available.
|
|
145
223
|
|
|
146
224
|
## Troubleshooting
|
|
147
225
|
|
package/package.json
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@safercity/sdk-react-native",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "React Native adapter for SaferCity SDK with expo-fetch streaming support",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "SaferCity"
|
|
8
8
|
},
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "https://github.com/safercity/safercity-v2.git",
|
|
12
|
-
"directory": "packages/sdk/react-native"
|
|
13
|
-
},
|
|
14
9
|
"keywords": ["safercity", "sdk", "react-native", "expo", "streaming"],
|
|
15
10
|
"sideEffects": false,
|
|
16
11
|
"type": "module",
|