diff --git a/apps/mobile-shell/scripts/check-config.mjs b/apps/mobile-shell/scripts/check-config.mjs index 1210a3472..ab9b759da 100644 --- a/apps/mobile-shell/scripts/check-config.mjs +++ b/apps/mobile-shell/scripts/check-config.mjs @@ -2227,6 +2227,27 @@ for (const snippet of [ } } +for (const snippet of [ + 'try {', + 'return ok(request, await getMobileNetworkStatus())', + 'return failure(request, {', + "code: 'host_error'", + "message: 'network status unavailable'", +]) { + if (!hostBridgeNetworkSource.includes(snippet)) { + throw new Error(`mobile shell network HostBridge must stabilize native failures: ${snippet}`); + } +} +for (const snippet of [ + 'converts native network failures to a stable host_error response', + "new Error('network query failed')", + "message: 'network status unavailable'", +]) { + if (!hostBridgeNetworkTestSource.includes(snippet)) { + throw new Error(`mobile shell network tests must cover stable native failure responses: ${snippet}`); + } +} + if ( !hapticsSource.includes('normalizeHostBridgeHapticsImpactStyle(rawStyle)') || !hapticsSource.includes('type HapticsImpactPayload') || @@ -2670,7 +2691,8 @@ if ( for (const snippet of [ 'getMobileHostBridgeNetworkStatus', 'request: HostBridgeRequest', - 'ok(request, await getMobileNetworkStatus())', + 'return ok(request, await getMobileNetworkStatus())', + 'return failure(request, {', 'getMobileNetworkStatus()', ]) { if (!hostBridgeNetworkSource.includes(snippet)) { @@ -2680,10 +2702,11 @@ for (const snippet of [ for (const snippet of [ 'wraps Expo Network status in the HostBridge response shape', 'normalizes disconnected network state before wrapping response', - 'lets protocol layer convert native network failures to host errors', + 'converts native network failures to a stable host_error response', 'connectionType: \'cellular\'', 'connectionType: \'none\'', 'network query failed', + 'network status unavailable', ]) { if (!hostBridgeNetworkTestSource.includes(snippet)) { throw new Error(`mobile shell network tests missing ${snippet}`); diff --git a/apps/mobile-shell/src/host-bridge/network.test.ts b/apps/mobile-shell/src/host-bridge/network.test.ts index f19a27064..579308554 100644 --- a/apps/mobile-shell/src/host-bridge/network.test.ts +++ b/apps/mobile-shell/src/host-bridge/network.test.ts @@ -71,13 +71,20 @@ describe('mobile HostBridge network helper', () => { }); }); - test('lets protocol layer convert native network failures to host errors', async () => { + test('converts native network failures to a stable host_error response', async () => { vi.mocked(Network.getNetworkStateAsync).mockRejectedValue( new Error('network query failed'), ); - await expect(getMobileHostBridgeNetworkStatus(request())).rejects.toThrow( - 'network query failed', - ); + await expect(getMobileHostBridgeNetworkStatus(request())).resolves.toEqual({ + bridge: HOST_BRIDGE_PROTOCOL, + version: HOST_BRIDGE_VERSION, + id: 'network-request', + ok: false, + error: { + code: 'host_error', + message: 'network status unavailable', + }, + }); }); }); diff --git a/apps/mobile-shell/src/host-bridge/network.ts b/apps/mobile-shell/src/host-bridge/network.ts index ef046a42a..18db4ed80 100644 --- a/apps/mobile-shell/src/host-bridge/network.ts +++ b/apps/mobile-shell/src/host-bridge/network.ts @@ -1,9 +1,16 @@ import { getMobileNetworkStatus } from '../shell/network'; import { type HostBridgeRequest } from '../../../../packages/shared/src/contracts/hostBridge'; -import { ok } from './protocol'; +import { failure, ok } from './protocol'; export async function getMobileHostBridgeNetworkStatus( request: HostBridgeRequest, ) { - return ok(request, await getMobileNetworkStatus()); + try { + return ok(request, await getMobileNetworkStatus()); + } catch { + return failure(request, { + code: 'host_error', + message: 'network status unavailable', + }); + } }