@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 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"]}
@@ -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 };
@@ -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
+ }