@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 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
+
@@ -0,0 +1,3 @@
1
+ export { Network } from './network.js';
2
+ export type { ConnectionType, NetworkState } from './network.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,2 @@
1
+ export { Network } from './network.js';
2
+ //# sourceMappingURL=index.js.map
@@ -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"}
@@ -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
+ }
@@ -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
+ }