@symbiote-native/network 3.0.2 → 3.0.3
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 +43 -31
- package/package.json +15 -15
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# @symbiote-native/network
|
|
2
2
|
|
|
3
3
|
Port of [`expo-network`](https://docs.expo.dev/versions/latest/sdk/network/) for
|
|
4
|
-
[SymbioteNative](../../README.md)
|
|
4
|
+
[SymbioteNative](../../README.md) - network connection state (type/connected/internet-reachable)
|
|
5
5
|
with a change listener, device IP address, and airplane-mode detection, reachable from every
|
|
6
6
|
adapter (React, Vue, Svelte, Solid, Angular), not just React.
|
|
7
7
|
|
|
@@ -25,43 +25,43 @@ npx @symbiote-native/cli new my-app --network
|
|
|
25
25
|
npx @symbiote-native/cli add --network
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
Either way: installs `@symbiote-native/network` and wires the native autolinking automatically
|
|
28
|
+
Either way: installs `@symbiote-native/network` and wires the native autolinking automatically,
|
|
29
29
|
see [`@symbiote-native/cli`](../cli).
|
|
30
30
|
|
|
31
31
|
<details>
|
|
32
|
-
<summary>Manual install (no CLI
|
|
32
|
+
<summary>Manual install (no CLI - installing and wiring native autolinking by hand)</summary>
|
|
33
33
|
|
|
34
34
|
```bash
|
|
35
35
|
npm install @symbiote-native/network
|
|
36
36
|
```
|
|
37
37
|
|
|
38
38
|
Depends on `expo-network` and `expo-modules-core` directly (regular dependencies, pinned to exact
|
|
39
|
-
versions
|
|
39
|
+
versions - never a caret range, since this package's `core/` is hand-ported against one specific
|
|
40
40
|
native API shape and a newer resolve could silently drift the two apart). Never install
|
|
41
|
-
`expo-network` yourself, and never add the `expo` package to this project
|
|
41
|
+
`expo-network` yourself, and never add the `expo` package to this project - it bundles its own
|
|
42
42
|
Metro/Babel pipeline that conflicts with this project's own.
|
|
43
43
|
|
|
44
44
|
### Required one-time step: native autolinking wiring
|
|
45
45
|
|
|
46
46
|
Unlike a plain RN native module, `expo-network`'s native code is discovered by
|
|
47
|
-
`expo-modules-autolinking`, not RN's own `react-native.config.cjs` mechanism
|
|
47
|
+
`expo-modules-autolinking`, not RN's own `react-native.config.cjs` mechanism - this needs wiring
|
|
48
48
|
into the native host app **once**, covering this package and every other `expo-modules-core`
|
|
49
49
|
package (`@symbiote-native/battery`, `@symbiote-native/sensors`, `@symbiote-native/local-auth`)
|
|
50
50
|
with zero further changes:
|
|
51
51
|
|
|
52
52
|
| Platform | Touches |
|
|
53
53
|
| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
54
|
-
| iOS | `ios/Podfile`
|
|
55
|
-
| iOS | `AppDelegate.swift`
|
|
56
|
-
| Android | `settings.gradle` / `app/build.gradle`
|
|
57
|
-
| Android | `MainApplication.kt`
|
|
54
|
+
| iOS | `ios/Podfile` - add `use_expo_modules!` |
|
|
55
|
+
| iOS | `AppDelegate.swift` - Expo's runtime-bootstrap hook |
|
|
56
|
+
| Android | `settings.gradle` / `app/build.gradle` - resolve and include the Expo Gradle projects |
|
|
57
|
+
| Android | `MainApplication.kt` - Expo's bootstrap hook, plus a hand-written native-module name map (there's no `expo` meta-package here to auto-generate one) |
|
|
58
58
|
|
|
59
|
-
Full mechanics
|
|
60
|
-
peer-dependency exclusion list
|
|
59
|
+
Full mechanics - the Podfile pieces that normally ship inside the `expo` package, the `expo`
|
|
60
|
+
peer-dependency exclusion list - live in the `symbiote-expo-native-module` skill. Reference
|
|
61
61
|
implementation: `examples/expo-react/ios/Podfile` and
|
|
62
62
|
`examples/expo-react/android/app/src/main/java/com/canaryexpo/MainApplication.kt`.
|
|
63
63
|
|
|
64
|
-
No platform permission string is needed for network's surface
|
|
64
|
+
No platform permission string is needed for network's surface - connection state, IP address, and
|
|
65
65
|
airplane-mode detection all read system state with no runtime permission prompt on either
|
|
66
66
|
platform.
|
|
67
67
|
|
|
@@ -70,28 +70,28 @@ platform.
|
|
|
70
70
|
## Shape
|
|
71
71
|
|
|
72
72
|
```
|
|
73
|
-
src/core/ network.ts
|
|
73
|
+
src/core/ network.ts - get*Async functions + addNetworkStateListener subscription.
|
|
74
74
|
native-module.ts resolves the native module through expo-modules-core's
|
|
75
|
-
requireNativeModule. types.ts
|
|
75
|
+
requireNativeModule. types.ts - NetworkStateType enum, NetworkState,
|
|
76
76
|
NetworkStateEvent, hand-ported from Network.types.ts.
|
|
77
|
-
src/react/hooks/ @symbiote-native/network/react
|
|
78
|
-
src/vue/composables/ @symbiote-native/network/vue
|
|
79
|
-
src/svelte/runes/ @symbiote-native/network/svelte
|
|
80
|
-
src/solid/primitives/ @symbiote-native/network/solid
|
|
77
|
+
src/react/hooks/ @symbiote-native/network/react - useNetworkState
|
|
78
|
+
src/vue/composables/ @symbiote-native/network/vue - useNetworkState (same name)
|
|
79
|
+
src/svelte/runes/ @symbiote-native/network/svelte - useNetworkState (same name)
|
|
80
|
+
src/solid/primitives/ @symbiote-native/network/solid - createNetworkState (returns an
|
|
81
81
|
Accessor; Solid reserves `use*` for consuming existing state)
|
|
82
|
-
src/angular/services/ @symbiote-native/network/angular
|
|
82
|
+
src/angular/services/ @symbiote-native/network/angular - NetworkStateService (`.connect()`
|
|
83
83
|
returns a Signal)
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
Each adapter's hook/composable/rune/primitive/service is a thin lifecycle wrapper (seed from the
|
|
87
87
|
one-shot `getNetworkStateAsync()` call, subscribe to `addNetworkStateListener`, unsubscribe on
|
|
88
|
-
unmount) over the same `core` functions
|
|
88
|
+
unmount) over the same `core` functions - the subscription logic is written once and shared by all
|
|
89
89
|
of them.
|
|
90
90
|
|
|
91
91
|
## Use it
|
|
92
92
|
|
|
93
93
|
```tsx
|
|
94
|
-
// React
|
|
94
|
+
// React - examples/expo-react/screens/NetworkScreen.tsx
|
|
95
95
|
import { useEffect, useState } from 'react';
|
|
96
96
|
import {
|
|
97
97
|
getIpAddressAsync,
|
|
@@ -128,7 +128,7 @@ function NetworkScreen() {
|
|
|
128
128
|
```
|
|
129
129
|
|
|
130
130
|
```vue
|
|
131
|
-
<!-- Vue
|
|
131
|
+
<!-- Vue - examples/expo-vue-sfc/screens/NetworkScreen.vue -->
|
|
132
132
|
<script setup lang="ts">
|
|
133
133
|
import { ref, watch } from 'vue';
|
|
134
134
|
import {
|
|
@@ -195,7 +195,7 @@ watch(
|
|
|
195
195
|
```
|
|
196
196
|
|
|
197
197
|
```ts
|
|
198
|
-
// Angular
|
|
198
|
+
// Angular - examples/expo-angular/src/screens/NetworkScreen.ts
|
|
199
199
|
import { Component, effect, inject, signal } from '@angular/core';
|
|
200
200
|
import { SYMBIOTE_ELEMENTS } from '@symbiote-native/angular';
|
|
201
201
|
import {
|
|
@@ -227,7 +227,7 @@ export class NetworkScreen {
|
|
|
227
227
|
```
|
|
228
228
|
|
|
229
229
|
```tsx
|
|
230
|
-
// Solid
|
|
230
|
+
// Solid - the accessor is CALLED; a Solid component body runs once, so a snapshot would freeze.
|
|
231
231
|
import { createSignal, onMount } from 'solid-js';
|
|
232
232
|
import {
|
|
233
233
|
getIpAddressAsync,
|
|
@@ -269,7 +269,7 @@ function NetworkScreen() {
|
|
|
269
269
|
|
|
270
270
|
Each of the demo screens above also re-fetches the IP address and airplane-mode card
|
|
271
271
|
whenever the live network state changes (toggling Wi-Fi/airplane mode on the device updates both
|
|
272
|
-
cards together)
|
|
272
|
+
cards together) - see the linked files for the full version, including the connection-type label
|
|
273
273
|
switch and the layout around it.
|
|
274
274
|
|
|
275
275
|
## API
|
|
@@ -285,7 +285,7 @@ addNetworkStateListener(listener): EventSubscription // fires whenever the n
|
|
|
285
285
|
```
|
|
286
286
|
|
|
287
287
|
Plus `NetworkStateType` (enum: `NONE`/`UNKNOWN`/`CELLULAR`/`WIFI`/`BLUETOOTH`/`ETHERNET`/`WIMAX`/
|
|
288
|
-
`VPN`/`OTHER`), `NetworkState`, `NetworkStateEvent`
|
|
288
|
+
`VPN`/`OTHER`), `NetworkState`, `NetworkStateEvent` - ported from upstream's `Network.types.ts`.
|
|
289
289
|
|
|
290
290
|
```ts
|
|
291
291
|
import {
|
|
@@ -304,18 +304,30 @@ import { NetworkStateService } from '@symbiote-native/network/angular';
|
|
|
304
304
|
|
|
305
305
|
`useNetworkState` (Solid: `createNetworkState`) seeds its initial value from a one-shot
|
|
306
306
|
`getNetworkStateAsync()` call, then subscribes to `addNetworkStateListener` for updates, and
|
|
307
|
-
unsubscribes on unmount
|
|
307
|
+
unsubscribes on unmount - mirroring upstream's own `useNetworkState`. The Solid primitive returns
|
|
308
308
|
an `Accessor<NetworkState>` and subscribes from its body rather than an effect, so nothing can slip
|
|
309
309
|
between the seed and the subscription.
|
|
310
310
|
|
|
311
|
+
## Common questions
|
|
312
|
+
|
|
313
|
+
- **Wi-Fi without internet.** `isConnected` only says a network exists; use `isInternetReachable`.
|
|
314
|
+
- **`ERR_NETWORK_NO_ACCESS_NETWORKINFO` on Android.** Catch the rejection and treat it as offline.
|
|
315
|
+
- **Hook stuck offline after the app was frozen (Android).** Events can arrive out of order; call
|
|
316
|
+
`getNetworkStateAsync` on foreground.
|
|
317
|
+
- **Always `NONE` after an SDK update.** Reported upstream; check the network-state permission.
|
|
318
|
+
|
|
319
|
+
Sources: [expo/expo#14527](https://github.com/expo/expo/issues/14527),
|
|
320
|
+
[expo/expo#47846](https://github.com/expo/expo/issues/47846),
|
|
321
|
+
[expo/expo#33070](https://github.com/expo/expo/issues/33070).
|
|
322
|
+
|
|
311
323
|
## Test it
|
|
312
324
|
|
|
313
|
-
No Fabric/Descriptor angle at all
|
|
325
|
+
No Fabric/Descriptor angle at all - network is a pure async-function + `EventEmitter` listener
|
|
314
326
|
surface, never a view. Tests inject a fake native-module object in place of the real
|
|
315
327
|
`requireNativeModule` resolution (`src/core/network.test.ts`,
|
|
316
328
|
`src/{react,vue,svelte,solid,angular}/**/*.test.{ts,tsx}`, `vitest`), the same pattern
|
|
317
|
-
`@symbiote-native/battery`/`@symbiote-native/sensors`/`@symbiote-native/local-auth` use
|
|
318
|
-
`installFabric()`, no ViewConfig. Native rendering itself is verified on-device
|
|
329
|
+
`@symbiote-native/battery`/`@symbiote-native/sensors`/`@symbiote-native/local-auth` use - no
|
|
330
|
+
`installFabric()`, no ViewConfig. Native rendering itself is verified on-device - see the parent
|
|
319
331
|
[README](../../README.md).
|
|
320
332
|
|
|
321
333
|
The Android/iOS native wiring is done across all six `examples/expo-*` canary apps
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@symbiote-native/network",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.3",
|
|
4
4
|
"description": "expo-network wrapped for SymbioteNative — one framework-agnostic core, built once and reachable from the React, Vue, Svelte, Solid, and Angular adapters. Network state (type/connected/internet-reachable) with a change listener, device IP address, and airplane-mode detection.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"expo-network": "57.0.1",
|
|
73
|
-
"expo-modules-core": "57.0.
|
|
73
|
+
"expo-modules-core": "57.0.20"
|
|
74
74
|
},
|
|
75
75
|
"peerDependencies": {
|
|
76
76
|
"@angular/core": ">=20",
|
|
@@ -80,12 +80,12 @@
|
|
|
80
80
|
"solid-js": ">=1.9.0",
|
|
81
81
|
"svelte": ">=5.56.0",
|
|
82
82
|
"vue": ">=3.5.0",
|
|
83
|
-
"@symbiote-native/angular": "^3.
|
|
84
|
-
"@symbiote-native/engine": "^1.
|
|
85
|
-
"@symbiote-native/react": "^3.0
|
|
86
|
-
"@symbiote-native/solid": "^3.0
|
|
87
|
-
"@symbiote-native/svelte": "^3.0
|
|
88
|
-
"@symbiote-native/vue": "^3.0
|
|
83
|
+
"@symbiote-native/angular": "^3.2.0",
|
|
84
|
+
"@symbiote-native/engine": "^1.5.0",
|
|
85
|
+
"@symbiote-native/react": "^3.2.0",
|
|
86
|
+
"@symbiote-native/solid": "^3.1.0",
|
|
87
|
+
"@symbiote-native/svelte": "^3.1.0",
|
|
88
|
+
"@symbiote-native/vue": "^3.2.0"
|
|
89
89
|
},
|
|
90
90
|
"peerDependenciesMeta": {
|
|
91
91
|
"@symbiote-native/angular": {
|
|
@@ -133,13 +133,13 @@
|
|
|
133
133
|
"solid-js": "^1.9.14",
|
|
134
134
|
"svelte": "^5.56.0",
|
|
135
135
|
"typescript": "~6.0.0",
|
|
136
|
-
"@symbiote-native/angular": "3.
|
|
137
|
-
"@symbiote-native/engine": "1.
|
|
138
|
-
"@symbiote-native/react": "3.0
|
|
139
|
-
"@symbiote-native/solid": "3.0
|
|
140
|
-
"@symbiote-native/svelte": "3.0
|
|
141
|
-
"@symbiote-native/test-utils": "0.4.
|
|
142
|
-
"@symbiote-native/vue": "3.0
|
|
136
|
+
"@symbiote-native/angular": "3.2.0",
|
|
137
|
+
"@symbiote-native/engine": "1.5.0",
|
|
138
|
+
"@symbiote-native/react": "3.2.0",
|
|
139
|
+
"@symbiote-native/solid": "3.1.0",
|
|
140
|
+
"@symbiote-native/svelte": "3.1.0",
|
|
141
|
+
"@symbiote-native/test-utils": "0.4.6",
|
|
142
|
+
"@symbiote-native/vue": "3.2.0"
|
|
143
143
|
},
|
|
144
144
|
"scripts": {
|
|
145
145
|
"typecheck": "tsc --build",
|