@safercity/sdk-react-native 0.0.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 +165 -0
- package/dist/index.cjs +65 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +85 -0
- package/dist/index.d.ts +85 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# @safercity/sdk-react-native
|
|
2
|
+
|
|
3
|
+
React Native adapter for SaferCity SDK with expo-fetch streaming support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @safercity/sdk-react-native @safercity/sdk-react @tanstack/react-query
|
|
9
|
+
# or
|
|
10
|
+
bun add @safercity/sdk-react-native @safercity/sdk-react @tanstack/react-query
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Requirements
|
|
14
|
+
|
|
15
|
+
- React Native >= 0.72.0
|
|
16
|
+
- React >= 18.0.0
|
|
17
|
+
- Expo SDK 52+ (recommended for streaming support)
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { createReactNativeClient, isStreamingSupported } from '@safercity/sdk-react-native';
|
|
23
|
+
import { SaferCityProvider } from '@safercity/sdk-react';
|
|
24
|
+
|
|
25
|
+
// Create client with React Native optimizations
|
|
26
|
+
const client = createReactNativeClient({
|
|
27
|
+
baseUrl: 'https://api.safercity.com',
|
|
28
|
+
token: userToken,
|
|
29
|
+
tenantId: 'tenant-123',
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
function App() {
|
|
33
|
+
return (
|
|
34
|
+
<SaferCityProvider {...client.getConfig()}>
|
|
35
|
+
<Navigation />
|
|
36
|
+
</SaferCityProvider>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Streaming Support
|
|
42
|
+
|
|
43
|
+
This package automatically uses `expo-fetch` for streaming when available (Expo SDK 52+).
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { isStreamingSupported } from '@safercity/sdk-react-native';
|
|
47
|
+
|
|
48
|
+
// Check if streaming is supported
|
|
49
|
+
if (isStreamingSupported()) {
|
|
50
|
+
console.log('SSE streaming is available');
|
|
51
|
+
} else {
|
|
52
|
+
console.log('Streaming not available, consider polling');
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Using Streaming
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { usePanicStream } from '@safercity/sdk-react';
|
|
60
|
+
|
|
61
|
+
function PanicTracker({ panicId }: { panicId: string }) {
|
|
62
|
+
const { data, isConnected, error } = usePanicStream(panicId, {
|
|
63
|
+
onEvent: (event) => {
|
|
64
|
+
console.log('Panic update:', event.data);
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (!isStreamingSupported()) {
|
|
69
|
+
// Fallback to polling
|
|
70
|
+
return <PollingPanicTracker panicId={panicId} />;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
<View>
|
|
75
|
+
<Text>Connected: {isConnected ? 'Yes' : 'No'}</Text>
|
|
76
|
+
<Text>Latest: {data?.data}</Text>
|
|
77
|
+
</View>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Without Expo
|
|
83
|
+
|
|
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.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import { createReactNativeClient } from '@safercity/sdk-react-native';
|
|
89
|
+
|
|
90
|
+
// You can provide a custom fetch implementation
|
|
91
|
+
const client = createReactNativeClient({
|
|
92
|
+
baseUrl: 'https://api.safercity.com',
|
|
93
|
+
token: userToken,
|
|
94
|
+
customFetch: myCustomFetch,
|
|
95
|
+
});
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Using with React Hooks
|
|
99
|
+
|
|
100
|
+
All hooks from `@safercity/sdk-react` work seamlessly:
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
import { useUsers, usePanics, useCreatePanic } from '@safercity/sdk-react';
|
|
104
|
+
|
|
105
|
+
function UserList() {
|
|
106
|
+
const { data, isLoading, error } = useUsers();
|
|
107
|
+
|
|
108
|
+
if (isLoading) return <ActivityIndicator />;
|
|
109
|
+
if (error) return <Text>Error: {error.message}</Text>;
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<FlatList
|
|
113
|
+
data={data?.data.users}
|
|
114
|
+
renderItem={({ item }) => <UserItem user={item} />}
|
|
115
|
+
keyExtractor={(item) => item.id}
|
|
116
|
+
/>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## API Reference
|
|
122
|
+
|
|
123
|
+
### createReactNativeClient(options)
|
|
124
|
+
|
|
125
|
+
Creates a SaferCity client optimized for React Native.
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface ReactNativeClientOptions {
|
|
129
|
+
baseUrl: string;
|
|
130
|
+
token?: string;
|
|
131
|
+
tenantId?: string;
|
|
132
|
+
timeout?: number;
|
|
133
|
+
headers?: Record<string, string>;
|
|
134
|
+
customFetch?: typeof fetch;
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### isStreamingSupported()
|
|
139
|
+
|
|
140
|
+
Returns `true` if expo-fetch is available and streaming is supported.
|
|
141
|
+
|
|
142
|
+
### getReactNativeFetch(customFetch?)
|
|
143
|
+
|
|
144
|
+
Returns the best available fetch implementation for the current environment.
|
|
145
|
+
|
|
146
|
+
## Troubleshooting
|
|
147
|
+
|
|
148
|
+
### Streaming not working
|
|
149
|
+
|
|
150
|
+
1. Ensure you're using Expo SDK 52 or later
|
|
151
|
+
2. Check that `expo-fetch` is properly installed
|
|
152
|
+
3. Use `isStreamingSupported()` to check availability
|
|
153
|
+
4. Fall back to polling if streaming is not supported
|
|
154
|
+
|
|
155
|
+
### Type errors
|
|
156
|
+
|
|
157
|
+
Make sure you have the correct peer dependencies:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
npm install react@^18.0.0 react-native@^0.72.0 @tanstack/react-query@^5.0.0
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## License
|
|
164
|
+
|
|
165
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var sdk = require('@safercity/sdk');
|
|
4
|
+
var sdkCore = require('@safercity/sdk-core');
|
|
5
|
+
|
|
6
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
7
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
8
|
+
}) : x)(function(x) {
|
|
9
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
10
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
11
|
+
});
|
|
12
|
+
function getExpoFetch() {
|
|
13
|
+
try {
|
|
14
|
+
const expoFetch = __require("expo/fetch");
|
|
15
|
+
return expoFetch?.fetch ?? null;
|
|
16
|
+
} catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function getReactNativeFetch(customFetch) {
|
|
21
|
+
const expoFetch = getExpoFetch();
|
|
22
|
+
if (expoFetch) {
|
|
23
|
+
return expoFetch;
|
|
24
|
+
}
|
|
25
|
+
if (customFetch) {
|
|
26
|
+
return customFetch;
|
|
27
|
+
}
|
|
28
|
+
return globalThis.fetch;
|
|
29
|
+
}
|
|
30
|
+
function supportsStreaming() {
|
|
31
|
+
const expoFetch = getExpoFetch();
|
|
32
|
+
return expoFetch !== null;
|
|
33
|
+
}
|
|
34
|
+
function createReactNativeStreamAdapter(customFetch) {
|
|
35
|
+
const fetchFn = getReactNativeFetch(customFetch);
|
|
36
|
+
return new sdkCore.FetchStreamAdapter(fetchFn);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// src/client.ts
|
|
40
|
+
function createReactNativeClient(options) {
|
|
41
|
+
const fetchFn = getReactNativeFetch(options.customFetch);
|
|
42
|
+
const streamAdapter = createReactNativeStreamAdapter(options.customFetch);
|
|
43
|
+
return sdk.createSaferCityClient({
|
|
44
|
+
...options,
|
|
45
|
+
fetch: fetchFn,
|
|
46
|
+
streamAdapter
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function isStreamingSupported() {
|
|
50
|
+
return supportsStreaming();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
exports.createReactNativeClient = createReactNativeClient;
|
|
54
|
+
exports.createReactNativeStreamAdapter = createReactNativeStreamAdapter;
|
|
55
|
+
exports.getReactNativeFetch = getReactNativeFetch;
|
|
56
|
+
exports.isStreamingSupported = isStreamingSupported;
|
|
57
|
+
exports.supportsStreaming = supportsStreaming;
|
|
58
|
+
Object.keys(sdk).forEach(function (k) {
|
|
59
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
60
|
+
enumerable: true,
|
|
61
|
+
get: function () { return sdk[k]; }
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
//# sourceMappingURL=index.cjs.map
|
|
65
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/fetch-adapter.ts","../src/client.ts"],"names":["FetchStreamAdapter","createSaferCityClient"],"mappings":";;;;;;;;;;;AAYA,SAAS,YAAA,GAAoC;AAC3C,EAAA,IAAI;AAGF,IAAA,MAAM,SAAA,GAAY,UAAQ,YAAY,CAAA;AACtC,IAAA,OAAO,WAAW,KAAA,IAAS,IAAA;AAAA,EAC7B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAUO,SAAS,oBAAoB,WAAA,EAA0C;AAC5E,EAAA,MAAM,YAAY,YAAA,EAAa;AAE/B,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,OAAO,WAAA;AAAA,EACT;AAIA,EAAA,OAAO,UAAA,CAAW,KAAA;AACpB;AAKO,SAAS,iBAAA,GAA6B;AAC3C,EAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,EAAA,OAAO,SAAA,KAAc,IAAA;AACvB;AAMO,SAAS,+BAA+B,WAAA,EAAgD;AAC7F,EAAA,MAAM,OAAA,GAAU,oBAAoB,WAAW,CAAA;AAC/C,EAAA,OAAO,IAAIA,2BAAmB,OAAO,CAAA;AACvC;;;ACrBO,SAAS,wBAAwB,OAAA,EAAoD;AAC1F,EAAA,MAAM,OAAA,GAAU,mBAAA,CAAoB,OAAA,CAAQ,WAAW,CAAA;AACvD,EAAA,MAAM,aAAA,GAAgB,8BAAA,CAA+B,OAAA,CAAQ,WAAW,CAAA;AAExE,EAAA,OAAOC,yBAAA,CAAsB;AAAA,IAC3B,GAAG,OAAA;AAAA,IACH,KAAA,EAAO,OAAA;AAAA,IACP;AAAA,GACD,CAAA;AACH;AAgBO,SAAS,oBAAA,GAAgC;AAC9C,EAAA,OAAO,iBAAA,EAAkB;AAC3B","file":"index.cjs","sourcesContent":["/**\n * React Native fetch adapter with expo-fetch support for streaming\n * \n * Expo SDK 52+ includes expo-fetch which supports ReadableStream\n * for SSE and streaming responses.\n */\n\nimport { FetchStreamAdapter } from '@safercity/sdk-core';\n\n/**\n * Detect if expo-fetch is available (Expo SDK 52+)\n */\nfunction getExpoFetch(): typeof fetch | null {\n try {\n // Dynamic import to avoid bundling issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const expoFetch = require('expo/fetch');\n return expoFetch?.fetch ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the best available fetch implementation for React Native\n * \n * Priority:\n * 1. expo-fetch (if available) - supports streaming\n * 2. Custom fetch provided by user\n * 3. Global fetch (limited streaming support)\n */\nexport function getReactNativeFetch(customFetch?: typeof fetch): typeof fetch {\n const expoFetch = getExpoFetch();\n \n if (expoFetch) {\n return expoFetch;\n }\n \n if (customFetch) {\n return customFetch;\n }\n \n // Fall back to global fetch\n // Note: Streaming may not work properly without expo-fetch\n return globalThis.fetch;\n}\n\n/**\n * Check if the current environment supports streaming\n */\nexport function supportsStreaming(): boolean {\n const expoFetch = getExpoFetch();\n return expoFetch !== null;\n}\n\n/**\n * Create a stream adapter for React Native\n * Uses expo-fetch if available, otherwise falls back to standard fetch\n */\nexport function createReactNativeStreamAdapter(customFetch?: typeof fetch): FetchStreamAdapter {\n const fetchFn = getReactNativeFetch(customFetch);\n return new FetchStreamAdapter(fetchFn);\n}\n","/**\n * React Native SaferCity client\n * \n * Pre-configured client with React Native optimizations:\n * - Uses expo-fetch for streaming support (if available)\n * - Falls back to standard fetch for non-Expo apps\n */\n\nimport { createSaferCityClient, type SaferCityClientOptions, type SaferCityClient } from '@safercity/sdk';\nimport { createReactNativeStreamAdapter, getReactNativeFetch, supportsStreaming } from './fetch-adapter';\n\nexport interface ReactNativeClientOptions extends Omit<SaferCityClientOptions, 'fetch' | 'streamAdapter'> {\n /**\n * Custom fetch implementation (optional)\n * If not provided, will use expo-fetch (if available) or global fetch\n */\n customFetch?: typeof fetch;\n}\n\n/**\n * Create a SaferCity client optimized for React Native\n * \n * @example\n * ```tsx\n * import { createReactNativeClient } from '@safercity/sdk-react-native';\n * \n * const client = createReactNativeClient({\n * baseUrl: 'https://api.safercity.com',\n * token: userToken,\n * tenantId: 'tenant-123',\n * });\n * \n * // Use just like the regular client\n * const { data } = await client.health.check();\n * \n * // Streaming works with expo-fetch\n * for await (const event of client.panics.streamUpdates('panic-123')) {\n * console.log('Update:', event.data);\n * }\n * ```\n */\nexport function createReactNativeClient(options: ReactNativeClientOptions): SaferCityClient {\n const fetchFn = getReactNativeFetch(options.customFetch);\n const streamAdapter = createReactNativeStreamAdapter(options.customFetch);\n \n return createSaferCityClient({\n ...options,\n fetch: fetchFn,\n streamAdapter,\n });\n}\n\n/**\n * Check if streaming is supported in the current React Native environment\n * \n * @example\n * ```tsx\n * import { isStreamingSupported } from '@safercity/sdk-react-native';\n * \n * if (isStreamingSupported()) {\n * // Use streaming features\n * } else {\n * // Fall back to polling\n * }\n * ```\n */\nexport function isStreamingSupported(): boolean {\n return supportsStreaming();\n}\n"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { SaferCityClientOptions, SaferCityClient } from '@safercity/sdk';
|
|
2
|
+
export * from '@safercity/sdk';
|
|
3
|
+
import { FetchStreamAdapter } from '@safercity/sdk-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* React Native SaferCity client
|
|
7
|
+
*
|
|
8
|
+
* Pre-configured client with React Native optimizations:
|
|
9
|
+
* - Uses expo-fetch for streaming support (if available)
|
|
10
|
+
* - Falls back to standard fetch for non-Expo apps
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
interface ReactNativeClientOptions extends Omit<SaferCityClientOptions, 'fetch' | 'streamAdapter'> {
|
|
14
|
+
/**
|
|
15
|
+
* Custom fetch implementation (optional)
|
|
16
|
+
* If not provided, will use expo-fetch (if available) or global fetch
|
|
17
|
+
*/
|
|
18
|
+
customFetch?: typeof fetch;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a SaferCity client optimized for React Native
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* import { createReactNativeClient } from '@safercity/sdk-react-native';
|
|
26
|
+
*
|
|
27
|
+
* const client = createReactNativeClient({
|
|
28
|
+
* baseUrl: 'https://api.safercity.com',
|
|
29
|
+
* token: userToken,
|
|
30
|
+
* tenantId: 'tenant-123',
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Use just like the regular client
|
|
34
|
+
* const { data } = await client.health.check();
|
|
35
|
+
*
|
|
36
|
+
* // Streaming works with expo-fetch
|
|
37
|
+
* for await (const event of client.panics.streamUpdates('panic-123')) {
|
|
38
|
+
* console.log('Update:', event.data);
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
declare function createReactNativeClient(options: ReactNativeClientOptions): SaferCityClient;
|
|
43
|
+
/**
|
|
44
|
+
* Check if streaming is supported in the current React Native environment
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* import { isStreamingSupported } from '@safercity/sdk-react-native';
|
|
49
|
+
*
|
|
50
|
+
* if (isStreamingSupported()) {
|
|
51
|
+
* // Use streaming features
|
|
52
|
+
* } else {
|
|
53
|
+
* // Fall back to polling
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function isStreamingSupported(): boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* React Native fetch adapter with expo-fetch support for streaming
|
|
61
|
+
*
|
|
62
|
+
* Expo SDK 52+ includes expo-fetch which supports ReadableStream
|
|
63
|
+
* for SSE and streaming responses.
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get the best available fetch implementation for React Native
|
|
68
|
+
*
|
|
69
|
+
* Priority:
|
|
70
|
+
* 1. expo-fetch (if available) - supports streaming
|
|
71
|
+
* 2. Custom fetch provided by user
|
|
72
|
+
* 3. Global fetch (limited streaming support)
|
|
73
|
+
*/
|
|
74
|
+
declare function getReactNativeFetch(customFetch?: typeof fetch): typeof fetch;
|
|
75
|
+
/**
|
|
76
|
+
* Check if the current environment supports streaming
|
|
77
|
+
*/
|
|
78
|
+
declare function supportsStreaming(): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Create a stream adapter for React Native
|
|
81
|
+
* Uses expo-fetch if available, otherwise falls back to standard fetch
|
|
82
|
+
*/
|
|
83
|
+
declare function createReactNativeStreamAdapter(customFetch?: typeof fetch): FetchStreamAdapter;
|
|
84
|
+
|
|
85
|
+
export { type ReactNativeClientOptions, createReactNativeClient, createReactNativeStreamAdapter, getReactNativeFetch, isStreamingSupported, supportsStreaming };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { SaferCityClientOptions, SaferCityClient } from '@safercity/sdk';
|
|
2
|
+
export * from '@safercity/sdk';
|
|
3
|
+
import { FetchStreamAdapter } from '@safercity/sdk-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* React Native SaferCity client
|
|
7
|
+
*
|
|
8
|
+
* Pre-configured client with React Native optimizations:
|
|
9
|
+
* - Uses expo-fetch for streaming support (if available)
|
|
10
|
+
* - Falls back to standard fetch for non-Expo apps
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
interface ReactNativeClientOptions extends Omit<SaferCityClientOptions, 'fetch' | 'streamAdapter'> {
|
|
14
|
+
/**
|
|
15
|
+
* Custom fetch implementation (optional)
|
|
16
|
+
* If not provided, will use expo-fetch (if available) or global fetch
|
|
17
|
+
*/
|
|
18
|
+
customFetch?: typeof fetch;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a SaferCity client optimized for React Native
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```tsx
|
|
25
|
+
* import { createReactNativeClient } from '@safercity/sdk-react-native';
|
|
26
|
+
*
|
|
27
|
+
* const client = createReactNativeClient({
|
|
28
|
+
* baseUrl: 'https://api.safercity.com',
|
|
29
|
+
* token: userToken,
|
|
30
|
+
* tenantId: 'tenant-123',
|
|
31
|
+
* });
|
|
32
|
+
*
|
|
33
|
+
* // Use just like the regular client
|
|
34
|
+
* const { data } = await client.health.check();
|
|
35
|
+
*
|
|
36
|
+
* // Streaming works with expo-fetch
|
|
37
|
+
* for await (const event of client.panics.streamUpdates('panic-123')) {
|
|
38
|
+
* console.log('Update:', event.data);
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
declare function createReactNativeClient(options: ReactNativeClientOptions): SaferCityClient;
|
|
43
|
+
/**
|
|
44
|
+
* Check if streaming is supported in the current React Native environment
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```tsx
|
|
48
|
+
* import { isStreamingSupported } from '@safercity/sdk-react-native';
|
|
49
|
+
*
|
|
50
|
+
* if (isStreamingSupported()) {
|
|
51
|
+
* // Use streaming features
|
|
52
|
+
* } else {
|
|
53
|
+
* // Fall back to polling
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
declare function isStreamingSupported(): boolean;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* React Native fetch adapter with expo-fetch support for streaming
|
|
61
|
+
*
|
|
62
|
+
* Expo SDK 52+ includes expo-fetch which supports ReadableStream
|
|
63
|
+
* for SSE and streaming responses.
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get the best available fetch implementation for React Native
|
|
68
|
+
*
|
|
69
|
+
* Priority:
|
|
70
|
+
* 1. expo-fetch (if available) - supports streaming
|
|
71
|
+
* 2. Custom fetch provided by user
|
|
72
|
+
* 3. Global fetch (limited streaming support)
|
|
73
|
+
*/
|
|
74
|
+
declare function getReactNativeFetch(customFetch?: typeof fetch): typeof fetch;
|
|
75
|
+
/**
|
|
76
|
+
* Check if the current environment supports streaming
|
|
77
|
+
*/
|
|
78
|
+
declare function supportsStreaming(): boolean;
|
|
79
|
+
/**
|
|
80
|
+
* Create a stream adapter for React Native
|
|
81
|
+
* Uses expo-fetch if available, otherwise falls back to standard fetch
|
|
82
|
+
*/
|
|
83
|
+
declare function createReactNativeStreamAdapter(customFetch?: typeof fetch): FetchStreamAdapter;
|
|
84
|
+
|
|
85
|
+
export { type ReactNativeClientOptions, createReactNativeClient, createReactNativeStreamAdapter, getReactNativeFetch, isStreamingSupported, supportsStreaming };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { createSaferCityClient } from '@safercity/sdk';
|
|
2
|
+
export * from '@safercity/sdk';
|
|
3
|
+
import { FetchStreamAdapter } from '@safercity/sdk-core';
|
|
4
|
+
|
|
5
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
6
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
7
|
+
}) : x)(function(x) {
|
|
8
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
9
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
10
|
+
});
|
|
11
|
+
function getExpoFetch() {
|
|
12
|
+
try {
|
|
13
|
+
const expoFetch = __require("expo/fetch");
|
|
14
|
+
return expoFetch?.fetch ?? null;
|
|
15
|
+
} catch {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function getReactNativeFetch(customFetch) {
|
|
20
|
+
const expoFetch = getExpoFetch();
|
|
21
|
+
if (expoFetch) {
|
|
22
|
+
return expoFetch;
|
|
23
|
+
}
|
|
24
|
+
if (customFetch) {
|
|
25
|
+
return customFetch;
|
|
26
|
+
}
|
|
27
|
+
return globalThis.fetch;
|
|
28
|
+
}
|
|
29
|
+
function supportsStreaming() {
|
|
30
|
+
const expoFetch = getExpoFetch();
|
|
31
|
+
return expoFetch !== null;
|
|
32
|
+
}
|
|
33
|
+
function createReactNativeStreamAdapter(customFetch) {
|
|
34
|
+
const fetchFn = getReactNativeFetch(customFetch);
|
|
35
|
+
return new FetchStreamAdapter(fetchFn);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/client.ts
|
|
39
|
+
function createReactNativeClient(options) {
|
|
40
|
+
const fetchFn = getReactNativeFetch(options.customFetch);
|
|
41
|
+
const streamAdapter = createReactNativeStreamAdapter(options.customFetch);
|
|
42
|
+
return createSaferCityClient({
|
|
43
|
+
...options,
|
|
44
|
+
fetch: fetchFn,
|
|
45
|
+
streamAdapter
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
function isStreamingSupported() {
|
|
49
|
+
return supportsStreaming();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export { createReactNativeClient, createReactNativeStreamAdapter, getReactNativeFetch, isStreamingSupported, supportsStreaming };
|
|
53
|
+
//# sourceMappingURL=index.js.map
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/fetch-adapter.ts","../src/client.ts"],"names":[],"mappings":";;;;;;;;;;AAYA,SAAS,YAAA,GAAoC;AAC3C,EAAA,IAAI;AAGF,IAAA,MAAM,SAAA,GAAY,UAAQ,YAAY,CAAA;AACtC,IAAA,OAAO,WAAW,KAAA,IAAS,IAAA;AAAA,EAC7B,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,IAAA;AAAA,EACT;AACF;AAUO,SAAS,oBAAoB,WAAA,EAA0C;AAC5E,EAAA,MAAM,YAAY,YAAA,EAAa;AAE/B,EAAA,IAAI,SAAA,EAAW;AACb,IAAA,OAAO,SAAA;AAAA,EACT;AAEA,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,OAAO,WAAA;AAAA,EACT;AAIA,EAAA,OAAO,UAAA,CAAW,KAAA;AACpB;AAKO,SAAS,iBAAA,GAA6B;AAC3C,EAAA,MAAM,YAAY,YAAA,EAAa;AAC/B,EAAA,OAAO,SAAA,KAAc,IAAA;AACvB;AAMO,SAAS,+BAA+B,WAAA,EAAgD;AAC7F,EAAA,MAAM,OAAA,GAAU,oBAAoB,WAAW,CAAA;AAC/C,EAAA,OAAO,IAAI,mBAAmB,OAAO,CAAA;AACvC;;;ACrBO,SAAS,wBAAwB,OAAA,EAAoD;AAC1F,EAAA,MAAM,OAAA,GAAU,mBAAA,CAAoB,OAAA,CAAQ,WAAW,CAAA;AACvD,EAAA,MAAM,aAAA,GAAgB,8BAAA,CAA+B,OAAA,CAAQ,WAAW,CAAA;AAExE,EAAA,OAAO,qBAAA,CAAsB;AAAA,IAC3B,GAAG,OAAA;AAAA,IACH,KAAA,EAAO,OAAA;AAAA,IACP;AAAA,GACD,CAAA;AACH;AAgBO,SAAS,oBAAA,GAAgC;AAC9C,EAAA,OAAO,iBAAA,EAAkB;AAC3B","file":"index.js","sourcesContent":["/**\n * React Native fetch adapter with expo-fetch support for streaming\n * \n * Expo SDK 52+ includes expo-fetch which supports ReadableStream\n * for SSE and streaming responses.\n */\n\nimport { FetchStreamAdapter } from '@safercity/sdk-core';\n\n/**\n * Detect if expo-fetch is available (Expo SDK 52+)\n */\nfunction getExpoFetch(): typeof fetch | null {\n try {\n // Dynamic import to avoid bundling issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const expoFetch = require('expo/fetch');\n return expoFetch?.fetch ?? null;\n } catch {\n return null;\n }\n}\n\n/**\n * Get the best available fetch implementation for React Native\n * \n * Priority:\n * 1. expo-fetch (if available) - supports streaming\n * 2. Custom fetch provided by user\n * 3. Global fetch (limited streaming support)\n */\nexport function getReactNativeFetch(customFetch?: typeof fetch): typeof fetch {\n const expoFetch = getExpoFetch();\n \n if (expoFetch) {\n return expoFetch;\n }\n \n if (customFetch) {\n return customFetch;\n }\n \n // Fall back to global fetch\n // Note: Streaming may not work properly without expo-fetch\n return globalThis.fetch;\n}\n\n/**\n * Check if the current environment supports streaming\n */\nexport function supportsStreaming(): boolean {\n const expoFetch = getExpoFetch();\n return expoFetch !== null;\n}\n\n/**\n * Create a stream adapter for React Native\n * Uses expo-fetch if available, otherwise falls back to standard fetch\n */\nexport function createReactNativeStreamAdapter(customFetch?: typeof fetch): FetchStreamAdapter {\n const fetchFn = getReactNativeFetch(customFetch);\n return new FetchStreamAdapter(fetchFn);\n}\n","/**\n * React Native SaferCity client\n * \n * Pre-configured client with React Native optimizations:\n * - Uses expo-fetch for streaming support (if available)\n * - Falls back to standard fetch for non-Expo apps\n */\n\nimport { createSaferCityClient, type SaferCityClientOptions, type SaferCityClient } from '@safercity/sdk';\nimport { createReactNativeStreamAdapter, getReactNativeFetch, supportsStreaming } from './fetch-adapter';\n\nexport interface ReactNativeClientOptions extends Omit<SaferCityClientOptions, 'fetch' | 'streamAdapter'> {\n /**\n * Custom fetch implementation (optional)\n * If not provided, will use expo-fetch (if available) or global fetch\n */\n customFetch?: typeof fetch;\n}\n\n/**\n * Create a SaferCity client optimized for React Native\n * \n * @example\n * ```tsx\n * import { createReactNativeClient } from '@safercity/sdk-react-native';\n * \n * const client = createReactNativeClient({\n * baseUrl: 'https://api.safercity.com',\n * token: userToken,\n * tenantId: 'tenant-123',\n * });\n * \n * // Use just like the regular client\n * const { data } = await client.health.check();\n * \n * // Streaming works with expo-fetch\n * for await (const event of client.panics.streamUpdates('panic-123')) {\n * console.log('Update:', event.data);\n * }\n * ```\n */\nexport function createReactNativeClient(options: ReactNativeClientOptions): SaferCityClient {\n const fetchFn = getReactNativeFetch(options.customFetch);\n const streamAdapter = createReactNativeStreamAdapter(options.customFetch);\n \n return createSaferCityClient({\n ...options,\n fetch: fetchFn,\n streamAdapter,\n });\n}\n\n/**\n * Check if streaming is supported in the current React Native environment\n * \n * @example\n * ```tsx\n * import { isStreamingSupported } from '@safercity/sdk-react-native';\n * \n * if (isStreamingSupported()) {\n * // Use streaming features\n * } else {\n * // Fall back to polling\n * }\n * ```\n */\nexport function isStreamingSupported(): boolean {\n return supportsStreaming();\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@safercity/sdk-react-native",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "React Native adapter for SaferCity SDK with expo-fetch streaming support",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": {
|
|
7
|
+
"name": "SaferCity"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/safercity/safercity-v2.git",
|
|
12
|
+
"directory": "packages/sdk/react-native"
|
|
13
|
+
},
|
|
14
|
+
"keywords": ["safercity", "sdk", "react-native", "expo", "streaming"],
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"module": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js",
|
|
24
|
+
"require": "./dist/index.cjs"
|
|
25
|
+
},
|
|
26
|
+
"./package.json": "./package.json"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"CHANGELOG.md"
|
|
32
|
+
],
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsup",
|
|
35
|
+
"dev": "tsup --watch",
|
|
36
|
+
"check-types": "tsc --noEmit",
|
|
37
|
+
"clean": "rm -rf dist",
|
|
38
|
+
"prepublishOnly": "bun run build"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@safercity/sdk": "workspace:*",
|
|
42
|
+
"@safercity/sdk-core": "workspace:*"
|
|
43
|
+
},
|
|
44
|
+
"peerDependencies": {
|
|
45
|
+
"react": ">=18.0.0",
|
|
46
|
+
"react-native": ">=0.72.0"
|
|
47
|
+
},
|
|
48
|
+
"peerDependenciesMeta": {
|
|
49
|
+
"expo": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^22.0.0",
|
|
55
|
+
"@types/react": "^18.0.0",
|
|
56
|
+
"react": "^18.0.0",
|
|
57
|
+
"tsup": "^8.0.0",
|
|
58
|
+
"typescript": "^5.8.0"
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public",
|
|
62
|
+
"registry": "https://registry.npmjs.org/"
|
|
63
|
+
}
|
|
64
|
+
}
|