# @wrnexus/mobile

> SSR-safe access to Capacitor plugins from WRNexusJS browser code.

## Overview

`@wrnexus/mobile` keeps optional native imports out of server rendering while giving
browser-owned modules one consistent registry for Capacitor plugins. During SSR,
`mobile.isNative()` is `false` and `mobile.platform()` is `"web"`.

## Installation

Install a plugin through the WRNexusJS CLI so the web and native projects stay aligned:

```bash
wrnexus mobile add @capacitor/camera @capacitor/haptics
```

## Usage

### Register and invoke a Capacitor plugin

Import Capacitor packages only from browser-owned code, never from API routes or SSR
helpers.

```ts
import { Camera, CameraResultType } from "@capacitor/camera";
import { mobile } from "@wrnexus/mobile";

mobile.registerPlugin("Camera", Camera);

export async function takePhoto() {
  if (!mobile.isNative()) return null;
  return mobile.invoke("Camera", "getPhoto", {
    quality: 85,
    resultType: CameraResultType.Uri,
  });
}
```

### Provide a browser fallback

`whenNative` runs the first callback only in a Capacitor WebView and can return a
web/SSR-safe fallback everywhere else.

```ts
import { Haptics, ImpactStyle } from "@capacitor/haptics";
import { mobile } from "@wrnexus/mobile";

mobile.registerPlugin("Haptics", Haptics);

export const confirmAction = () =>
  mobile.whenNative(
    () => mobile.invoke("Haptics", "impact", { style: ImpactStyle.Medium }),
    () => navigator.vibrate?.(30),
  );
```

### Read an optional plugin without throwing

```ts
import type { NetworkPlugin } from "@capacitor/network";
import { mobile } from "@wrnexus/mobile";

const network = mobile.plugin<NetworkPlugin>("Network");
const status = network ? await network.getStatus() : { connected: true, connectionType: "unknown" };
```

## API

- `registerPlugin(name, instance)` registers a browser-imported plugin.
- `plugin(name)` returns a plugin or `undefined`; `requirePlugin(name)` throws when absent.
- `invoke(plugin, method, options?)` calls a registered method and returns its result.
- `whenNative(native, fallback?)` selects native behavior without breaking SSR.
- `isNative()` and `platform()` report the current Capacitor environment.

Unavailable required plugins throw `MobileUnavailableError` with an actionable message.

The package also provides portable application-facing primitives:

- `listenDeepLinks` normalizes initial and live links with an allowed-scheme list.
- `PushNotifications` performs permission gating and validates registrations.
- `SecureStorage` namespaces and validates keys over an application-supplied encrypted
  Keychain/Keystore adapter; it does not mislabel browser `localStorage` as secure.
- `OfflineQueue` persists bounded sync batches through a pluggable durable store.

## Requirements / Notes

- Capacitor plugin imports must remain in browser-owned modules.
- `@wrnexus/mobile` re-exports `native` from `@wrnexus/native` for applications that
  prefer the higher-level cross-platform capability API.
