@sigx/lynx-network 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/LICENSE +21 -0
- package/README.md +55 -0
- package/android/com/sigx/network/NetworkModule.kt +67 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/network.d.ts +22 -0
- package/dist/network.d.ts.map +1 -0
- package/dist/network.js +22 -0
- package/dist/network.js.map +1 -0
- package/ios/NetworkModule.swift +69 -0
- package/package.json +33 -0
- package/sigx-module.json +16 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Andreas Ekdahl
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @sigx/lynx-network
|
|
2
|
+
|
|
3
|
+
Network connectivity status for sigx-lynx. `NWPathMonitor` on iOS, `ConnectivityManager` on Android.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @sigx/lynx-network
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
// sigx.lynx.config.ts
|
|
13
|
+
export default defineLynxConfig({
|
|
14
|
+
modules: ['@sigx/lynx-network'],
|
|
15
|
+
});
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
No special permissions on either platform.
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
import { Network } from '@sigx/lynx-network';
|
|
24
|
+
|
|
25
|
+
const state = await Network.getState();
|
|
26
|
+
if (state.isConnected && state.type === 'wifi') {
|
|
27
|
+
// sync large payload
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
|
|
33
|
+
| Method | Notes |
|
|
34
|
+
| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
35
|
+
| `getState(): Promise<NetworkState>` | Single async snapshot — no subscription stream yet. |
|
|
36
|
+
| `isAvailable(): boolean` | Whether the native module is registered in the current build. |
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
type ConnectionType = 'wifi' | 'cellular' | 'ethernet' | 'bluetooth' | 'none' | 'unknown';
|
|
40
|
+
|
|
41
|
+
interface NetworkState {
|
|
42
|
+
isConnected: boolean;
|
|
43
|
+
type: ConnectionType;
|
|
44
|
+
isInternetReachable: boolean | null; // null = unknown (e.g. captive portal)
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Gotchas
|
|
49
|
+
|
|
50
|
+
- **`isInternetReachable: null`** means the OS hasn't confirmed actual reachability — common on captive-portal Wi-Fi (you're connected to an AP but can't reach the internet without sign-in). Treat as "probably yes".
|
|
51
|
+
- **No subscription API yet.** If you need to react to connectivity changes live, poll `getState()` from a `setInterval` or wrap a small effect — the native publisher exists but isn't surfaced as JS events in this version.
|
|
52
|
+
|
|
53
|
+
## Reference app
|
|
54
|
+
|
|
55
|
+
`examples/lynx-one/my-sigx-app/src/cards/NetworkCard.tsx` renders the snapshot and refreshes on tap.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
package com.sigx.network
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.net.ConnectivityManager
|
|
5
|
+
import android.net.NetworkCapabilities
|
|
6
|
+
import android.os.Build
|
|
7
|
+
import android.util.Log
|
|
8
|
+
import com.lynx.jsbridge.LynxMethod
|
|
9
|
+
import com.lynx.jsbridge.LynxModule
|
|
10
|
+
import com.lynx.react.bridge.Callback
|
|
11
|
+
import com.lynx.react.bridge.JavaOnlyMap
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Network connectivity status module.
|
|
15
|
+
* JS usage: NativeModules.Network.getState(callback)
|
|
16
|
+
*/
|
|
17
|
+
class NetworkModule(context: Context) : LynxModule(context) {
|
|
18
|
+
|
|
19
|
+
companion object {
|
|
20
|
+
private const val TAG = "NetworkModule"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@LynxMethod
|
|
24
|
+
fun getState(callback: Callback?) {
|
|
25
|
+
try {
|
|
26
|
+
val cm = mContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
|
27
|
+
val result = JavaOnlyMap()
|
|
28
|
+
|
|
29
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
30
|
+
val network = cm.activeNetwork
|
|
31
|
+
val capabilities = network?.let { cm.getNetworkCapabilities(it) }
|
|
32
|
+
|
|
33
|
+
if (capabilities != null) {
|
|
34
|
+
result.putBoolean("isConnected", true)
|
|
35
|
+
result.putBoolean("isInternetReachable",
|
|
36
|
+
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET))
|
|
37
|
+
|
|
38
|
+
val type = when {
|
|
39
|
+
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> "wifi"
|
|
40
|
+
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> "cellular"
|
|
41
|
+
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> "ethernet"
|
|
42
|
+
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_BLUETOOTH) -> "bluetooth"
|
|
43
|
+
else -> "unknown"
|
|
44
|
+
}
|
|
45
|
+
result.putString("type", type)
|
|
46
|
+
} else {
|
|
47
|
+
result.putBoolean("isConnected", false)
|
|
48
|
+
result.putString("type", "none")
|
|
49
|
+
result.putBoolean("isInternetReachable", false)
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
@Suppress("DEPRECATION")
|
|
53
|
+
val info = cm.activeNetworkInfo
|
|
54
|
+
result.putBoolean("isConnected", info?.isConnected == true)
|
|
55
|
+
result.putString("type", if (info?.isConnected == true) "unknown" else "none")
|
|
56
|
+
result.putBoolean("isInternetReachable", info?.isConnected == true)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
callback?.invoke(result)
|
|
60
|
+
} catch (e: Exception) {
|
|
61
|
+
val error = JavaOnlyMap()
|
|
62
|
+
error.putString("error", e.message ?: "Unknown error")
|
|
63
|
+
callback?.invoke(error)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export type ConnectionType = 'wifi' | 'cellular' | 'ethernet' | 'bluetooth' | 'none' | 'unknown';
|
|
2
|
+
export interface NetworkState {
|
|
3
|
+
isConnected: boolean;
|
|
4
|
+
type: ConnectionType;
|
|
5
|
+
isInternetReachable: boolean | null;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Network connectivity APIs.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { Network } from '@sigx/lynx-network';
|
|
13
|
+
*
|
|
14
|
+
* const state = await Network.getState();
|
|
15
|
+
* console.log(state.isConnected, state.type);
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare const Network: {
|
|
19
|
+
readonly getState: () => Promise<NetworkState>;
|
|
20
|
+
readonly isAvailable: () => boolean;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=network.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,GAAG,WAAW,GAAG,MAAM,GAAG,SAAS,CAAC;AAEjG,MAAM,WAAW,YAAY;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,cAAc,CAAC;IACrB,mBAAmB,EAAE,OAAO,GAAG,IAAI,CAAC;CACvC;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,OAAO;6BACJ,OAAO,CAAC,YAAY,CAAC;gCAIlB,OAAO;CAGhB,CAAC"}
|
package/dist/network.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { callAsync, isModuleAvailable } from '@sigx/lynx-core';
|
|
2
|
+
const MODULE = 'Network';
|
|
3
|
+
/**
|
|
4
|
+
* Network connectivity APIs.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* import { Network } from '@sigx/lynx-network';
|
|
9
|
+
*
|
|
10
|
+
* const state = await Network.getState();
|
|
11
|
+
* console.log(state.isConnected, state.type);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export const Network = {
|
|
15
|
+
getState() {
|
|
16
|
+
return callAsync(MODULE, 'getState');
|
|
17
|
+
},
|
|
18
|
+
isAvailable() {
|
|
19
|
+
return isModuleAvailable(MODULE);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=network.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network.js","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAE/D,MAAM,MAAM,GAAG,SAAS,CAAC;AAUzB;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG;IACnB,QAAQ;QACJ,OAAO,SAAS,CAAe,MAAM,EAAE,UAAU,CAAC,CAAC;IACvD,CAAC;IAED,WAAW;QACP,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC;CACK,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Network
|
|
3
|
+
import Lynx
|
|
4
|
+
|
|
5
|
+
/// Network connectivity status module.
|
|
6
|
+
/// JS usage: NativeModules.Network.getState(callback)
|
|
7
|
+
class NetworkModule: NSObject, LynxModule {
|
|
8
|
+
|
|
9
|
+
@objc static var name: String { "Network" }
|
|
10
|
+
|
|
11
|
+
@objc static var methodLookup: [String: String] {
|
|
12
|
+
[
|
|
13
|
+
"getState": NSStringFromSelector(#selector(getState(_:))),
|
|
14
|
+
]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
private let monitor = NWPathMonitor()
|
|
18
|
+
private let monitorQueue = DispatchQueue(label: "com.sigx.lynxgo.network-monitor")
|
|
19
|
+
private var currentPath: NWPath?
|
|
20
|
+
|
|
21
|
+
required override init() {
|
|
22
|
+
super.init()
|
|
23
|
+
startMonitor()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
required init(param: Any) {
|
|
27
|
+
super.init()
|
|
28
|
+
startMonitor()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private func startMonitor() {
|
|
32
|
+
monitor.pathUpdateHandler = { [weak self] path in
|
|
33
|
+
self?.currentPath = path
|
|
34
|
+
}
|
|
35
|
+
monitor.start(queue: monitorQueue)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
deinit {
|
|
39
|
+
monitor.cancel()
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@objc func getState(_ callback: LynxCallbackBlock?) {
|
|
43
|
+
let path = currentPath ?? monitor.currentPath
|
|
44
|
+
|
|
45
|
+
let isConnected = path.status == .satisfied
|
|
46
|
+
let isExpensive = path.isExpensive
|
|
47
|
+
|
|
48
|
+
let type: String
|
|
49
|
+
if path.usesInterfaceType(.wifi) {
|
|
50
|
+
type = "wifi"
|
|
51
|
+
} else if path.usesInterfaceType(.cellular) {
|
|
52
|
+
type = "cellular"
|
|
53
|
+
} else if path.usesInterfaceType(.wiredEthernet) {
|
|
54
|
+
type = "ethernet"
|
|
55
|
+
} else if path.status == .satisfied {
|
|
56
|
+
type = "unknown"
|
|
57
|
+
} else {
|
|
58
|
+
type = "none"
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
let result: [String: Any] = [
|
|
62
|
+
"isConnected": isConnected,
|
|
63
|
+
"type": type,
|
|
64
|
+
"isInternetReachable": isConnected,
|
|
65
|
+
"isExpensive": isExpensive,
|
|
66
|
+
]
|
|
67
|
+
callback?(result)
|
|
68
|
+
}
|
|
69
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sigx/lynx-network",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Network connectivity status for sigx-lynx",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
},
|
|
13
|
+
"./sigx-module.json": "./sigx-module.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"ios",
|
|
18
|
+
"android",
|
|
19
|
+
"sigx-module.json"
|
|
20
|
+
],
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@sigx/lynx-core": "^0.1.0"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"typescript": "^5.9.3"
|
|
26
|
+
},
|
|
27
|
+
"author": "Andreas Ekdahl",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc",
|
|
31
|
+
"dev": "tsc --watch"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/sigx-module.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Network",
|
|
3
|
+
"package": "@sigx/lynx-network",
|
|
4
|
+
"description": "Network connectivity status",
|
|
5
|
+
"platforms": ["android", "ios"],
|
|
6
|
+
"ios": {
|
|
7
|
+
"moduleClass": "NetworkModule",
|
|
8
|
+
"sourceDir": "ios",
|
|
9
|
+
"methods": ["getState"]
|
|
10
|
+
},
|
|
11
|
+
"android": {
|
|
12
|
+
"moduleClass": "com.sigx.network.NetworkModule",
|
|
13
|
+
"sourceDir": "android",
|
|
14
|
+
"permissions": []
|
|
15
|
+
}
|
|
16
|
+
}
|