226 lines
18 KiB
Plaintext
226 lines
18 KiB
Plaintext
page wrnexusmobile {
|
|
seo {
|
|
title = "@wrnexus/mobile"
|
|
description = "SSR-safe compatibility access to Capacitor plugins."
|
|
}
|
|
|
|
view {
|
|
<div class="docs-shell">
|
|
<a href="#main" class="skip-link">Skip to content</a>
|
|
<header class="topbar">
|
|
<a class="brand" href="/"><span>W</span> WRNexusJS</a>
|
|
<nav aria-label="Primary"><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a></nav>
|
|
<div class="topbar-actions"><a class="preview-pill" href="/access">Private preview · v0.8.8</a><button data-wire-theme-toggle class="theme-button" aria-label="Toggle color theme" title="Toggle color theme">◐</button></div>
|
|
</header>
|
|
<div class="mobile-doc-nav"><details><summary>Browse documentation</summary><nav><a href="/getting-started">Get started</a><a href="/packages">Packages</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/language">Language</a><a href="/architecture">Architecture</a><a href="/tutorial">Tutorial</a><a href="/guides/project-structure">Guides</a><a href="/examples">Examples</a><a href="/search">Search</a></nav></details></div>
|
|
<main id="main" class="portal-main docs-layout docs-layout--navigation"><aside class="docs-section-menu" aria-label="Documentation sections"><nav>
|
|
<section><strong>Get started</strong><a href="/getting-started">Quick start</a><a href="/tutorial">Tutorial</a><a href="/guides/full-stack-auth-demo">Auth dashboard demo</a><a href="/guides/configuration-and-profiles">Configuration</a></section>
|
|
<section><strong>Build</strong><a href="/guides/pages-and-components">Pages and components</a><a href="/guides/routing">Routing</a><a href="/guides/server-data">Server data</a><a href="/guides/forms-and-validation">Forms and validation</a><a href="/guides/database">Database</a></section>
|
|
<section><strong>Auth and security</strong><a href="/guides/authentication">Authentication</a><a href="/guides/authorization">Authorization</a><a href="/guides/security">Application security</a><a href="/security">Security policy</a></section>
|
|
<section><strong>Reference</strong><a href="/packages">Packages overview</a><a href="/packages/cli">CLI</a><a href="/language">.wrn language</a><a href="https://component.wrnexusjs.dev/">Components</a><a href="/examples">Examples</a></section>
|
|
<section class="package-menu"><strong>Packages</strong><a href="/packages/ai">@wrnexus/ai</a><a href="/packages/auth">@wrnexus/auth</a><a href="/packages/authz">@wrnexus/authz</a><a href="/packages/benchmark">@wrnexus/benchmark</a><a href="/packages/cache">@wrnexus/cache</a><a href="/packages/captcha">@wrnexus/captcha</a><a href="/packages/cli">@wrnexus/cli</a><a href="/packages/compiler">@wrnexus/compiler</a><a href="/packages/content">@wrnexus/content</a><a href="/packages/core">@wrnexus/core</a><a href="/packages/csr">@wrnexus/csr</a><a href="/packages/db">@wrnexus/db</a><a href="/packages/dev-server">@wrnexus/dev-server</a><a href="/packages/dev-toolbar">@wrnexus/dev-toolbar</a><a href="/packages/encryption">@wrnexus/encryption</a><a href="/packages/graphql">@wrnexus/graphql</a><a href="/packages/helpers">@wrnexus/helpers</a><a href="/packages/i18n">@wrnexus/i18n</a><a href="/packages/identity">@wrnexus/identity</a><a href="/packages/image">@wrnexus/image</a><a href="/packages/jwt">@wrnexus/jwt</a><a href="/packages/language-server">@wrnexus/language-server</a><a href="/packages/mcp">@wrnexus/mcp</a><a href="/packages/mobile">@wrnexus/mobile</a><a href="/packages/native">@wrnexus/native</a><a href="/packages/oauth">@wrnexus/oauth</a><a href="/packages/observability">@wrnexus/observability</a><a href="/packages/playground">@wrnexus/playground</a><a href="/packages/plugin">@wrnexus/plugin</a><a href="/packages/pubsub">@wrnexus/pubsub</a><a href="/packages/pwa">@wrnexus/pwa</a><a href="/packages/queue">@wrnexus/queue</a><a href="/packages/reactive">@wrnexus/reactive</a><a href="/packages/realtime">@wrnexus/realtime</a><a href="/packages/router">@wrnexus/router</a><a href="/packages/security">@wrnexus/security</a><a href="/packages/ssr">@wrnexus/ssr</a><a href="/packages/store">@wrnexus/store</a><a href="/packages/styles">@wrnexus/styles</a><a href="/packages/syntax">@wrnexus/syntax</a><a href="/packages/test">@wrnexus/test</a><a href="/packages/tracking">@wrnexus/tracking</a><a href="/packages/typecheck">@wrnexus/typecheck</a><a href="/packages/ui">@wrnexus/ui</a><a href="/packages/uploader">@wrnexus/uploader</a><a href="/packages/validation">@wrnexus/validation</a></section>
|
|
</nav></aside><div class="docs-reading-column">
|
|
<article class="documentation prose standalone package-document"><nav class="breadcrumbs" aria-label="Breadcrumb"><a href="/">Home</a><span>/</span><a href="/packages">Packages</a><span>/</span><span aria-current="page">@wrnexus/mobile</span></nav><section class="doc-intro"><span class="eyebrow">Native · Package reference</span><h1>@wrnexus/mobile</h1><p>SSR-safe compatibility access to Capacitor plugins.</p><div class="doc-meta"><span>v0.8.8</span><span>Private registry</span><span>Native</span></div><section id="access" class="access-callout"><h2>Install the package</h2><p>After WorkRoot approves private registry access, install the release-aligned package:</p><pre><code>bun add @wrnexus/mobile@0.8.8</code><button type="button" class="copy-button" aria-label="Copy installation command">Copy</button></pre><p><a href="/access">Request preview access</a>. Never put registry tokens in source control.</p></section></section><section id="guide"><blockquote>SSR-safe access to Capacitor plugins from WRNexusJS browser code.</blockquote>
|
|
<h3 id="overview">Overview</h3>
|
|
<p><code>@wrnexus/mobile</code> keeps optional native imports out of server rendering while giving browser-owned modules one consistent registry for Capacitor plugins. During SSR, <code>mobile.isNative()</code> is <code>false</code> and <code>mobile.platform()</code> is <code>"web"</code>.</p>
|
|
<p>Install a plugin through the WRNexusJS CLI so the web and native projects stay aligned:</p>
|
|
<pre data-language="bash"><code>wrnexus mobile add @capacitor/camera @capacitor/haptics</code></pre>
|
|
<h3 id="usage">Usage</h3>
|
|
<h4 id="register-and-invoke-a-capacitor-plugin">Register and invoke a Capacitor plugin</h4>
|
|
<p>Import Capacitor packages only from browser-owned code, never from API routes or SSR helpers.</p>
|
|
<pre data-language="ts"><code>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,
|
|
});
|
|
}</code></pre>
|
|
<h4 id="provide-a-browser-fallback">Provide a browser fallback</h4>
|
|
<p><code>whenNative</code> runs the first callback only in a Capacitor WebView and can return a web/SSR-safe fallback everywhere else.</p>
|
|
<pre data-language="ts"><code>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),
|
|
);</code></pre>
|
|
<h4 id="read-an-optional-plugin-without-throwing">Read an optional plugin without throwing</h4>
|
|
<pre data-language="ts"><code>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" };</code></pre>
|
|
<h3 id="api">API</h3>
|
|
<ul>
|
|
<li><code>registerPlugin(name, instance)</code> registers a browser-imported plugin.</li>
|
|
<li><code>plugin(name)</code> returns a plugin or <code>undefined</code>; <code>requirePlugin(name)</code> throws when absent.</li>
|
|
<li><code>invoke(plugin, method, options?)</code> calls a registered method and returns its result.</li>
|
|
<li><code>whenNative(native, fallback?)</code> selects native behavior without breaking SSR.</li>
|
|
<li><code>isNative()</code> and <code>platform()</code> report the current Capacitor environment.</li>
|
|
</ul>
|
|
<p>Unavailable required plugins throw <code>MobileUnavailableError</code> with an actionable message.</p>
|
|
<p>The package also provides portable application-facing primitives:</p>
|
|
<ul>
|
|
<li><code>listenDeepLinks</code> normalizes initial and live links with an allowed-scheme list.</li>
|
|
<li><code>PushNotifications</code> performs permission gating and validates registrations.</li>
|
|
<li><code>SecureStorage</code> namespaces and validates keys over an application-supplied encrypted</li>
|
|
<p>Keychain/Keystore adapter; it does not mislabel browser <code>localStorage</code> as secure.</p>
|
|
<li><code>OfflineQueue</code> persists bounded sync batches through a pluggable durable store.</li>
|
|
</ul>
|
|
<h3 id="requirements-notes">Requirements / Notes</h3>
|
|
<ul>
|
|
<li>Capacitor plugin imports must remain in browser-owned modules.</li>
|
|
<li><code>@wrnexus/mobile</code> re-exports <code>native</code> from <code>@wrnexus/native</code> for applications that</li>
|
|
<p>prefer the higher-level cross-platform capability API.</p>
|
|
</ul></section><section id="api" class="api"><h2>Complete TypeScript API</h2><p>Generated from the exact installed package declarations.</p><pre data-language="typescript"><code>export { native } from '@wrnexus/native';
|
|
|
|
interface DeepLink {
|
|
url: URL;
|
|
path: string;
|
|
query: URLSearchParams;
|
|
}
|
|
declare function parseDeepLink(value: string, schemes?: string[]): DeepLink | null;
|
|
interface DeepLinkSource {
|
|
current?(): Promise<string | undefined>;
|
|
subscribe(listener: (url: string) => void): void | (() => void);
|
|
}
|
|
/** Normalize initial and live native links and ignore malformed/unapproved schemes. */
|
|
declare function listenDeepLinks(source: DeepLinkSource, listener: (link: DeepLink) => void, schemes?: string[]): () => void;
|
|
interface PushRegistration {
|
|
token: string;
|
|
platform?: string;
|
|
}
|
|
interface PushAdapter {
|
|
permission(): Promise<"granted" | "denied" | "prompt" | "unavailable">;
|
|
requestPermission?(): Promise<"granted" | "denied">;
|
|
register(): Promise<PushRegistration>;
|
|
subscribe?(listener: (notification: unknown) => void): () => void;
|
|
}
|
|
declare class PushNotifications {
|
|
private readonly adapter;
|
|
constructor(adapter: PushAdapter);
|
|
register(): Promise<PushRegistration>;
|
|
subscribe(listener: (notification: unknown) => void): () => void;
|
|
}
|
|
interface SecureStorageAdapter {
|
|
get(key: string): Promise<string | null>;
|
|
set(key: string, value: string): Promise<void>;
|
|
remove(key: string): Promise<void>;
|
|
}
|
|
declare class SecureStorage {
|
|
#private;
|
|
private readonly adapter;
|
|
private readonly namespace;
|
|
constructor(adapter: SecureStorageAdapter, namespace?: string);
|
|
get(key: string): Promise<string | null>;
|
|
set(key: string, value: string): Promise<void>;
|
|
remove(key: string): Promise<void>;
|
|
}
|
|
interface OfflineTask<T = unknown> {
|
|
id: string;
|
|
type: string;
|
|
payload: T;
|
|
createdAt: number;
|
|
attempts: number;
|
|
}
|
|
interface OfflineTaskStore {
|
|
load(): Promise<OfflineTask[]>;
|
|
save(tasks: OfflineTask[]): Promise<void>;
|
|
}
|
|
declare function memoryOfflineTaskStore(): OfflineTaskStore;
|
|
declare class OfflineQueue {
|
|
#private;
|
|
private readonly store;
|
|
constructor(store?: OfflineTaskStore);
|
|
process<T>(type: string, handler: (payload: T) => Promise<void>): void;
|
|
add<T>(type: string, payload: T): Promise<OfflineTask<T>>;
|
|
sync(limit?: number): Promise<{
|
|
completed: number;
|
|
failed: number;
|
|
}>;
|
|
size(): Promise<number>;
|
|
}
|
|
interface MobileEnvironment {
|
|
platform: string;
|
|
native: boolean;
|
|
online: boolean;
|
|
userAgent?: string;
|
|
}
|
|
declare function mobileEnvironment(): MobileEnvironment;
|
|
|
|
/** @wrnexus/mobile — SSR-safe access to Capacitor's native bridge. */
|
|
|
|
type MobilePlatform = "ios" | "android" | "web" | string;
|
|
interface CapacitorBridge {
|
|
isNativePlatform?: () => boolean;
|
|
getPlatform?: () => MobilePlatform;
|
|
Plugins?: Record<string, unknown>;
|
|
}
|
|
declare class MobileUnavailableError extends Error {
|
|
constructor(message?: string);
|
|
}
|
|
/** Register a plugin imported by browser-only application code. */
|
|
declare function registerPlugin<T extends object>(name: string, instance: T): T;
|
|
/** True only inside a native Capacitor iOS or Android WebView. SSR-safe. */
|
|
declare function isNative(): boolean;
|
|
/** Current Capacitor platform, falling back to `web` during SSR and in browsers. */
|
|
declare function platform(): MobilePlatform;
|
|
/** Return an injected Capacitor plugin, or undefined when it is unavailable. */
|
|
declare function plugin<T extends object>(name: string): T | undefined;
|
|
/** Require an installed native plugin and produce a useful error when absent. */
|
|
declare function requirePlugin<T extends object>(name: string): T;
|
|
/** Invoke a plugin method without importing native code into an SSR module. */
|
|
declare function invoke<TResult = unknown>(pluginName: string, method: string, options?: unknown): Promise<TResult>;
|
|
/** Run native behavior when available, with an optional SSR/web fallback. */
|
|
declare function whenNative<T>(native: () => T | Promise<T>, fallback?: () => T | Promise<T>): Promise<T | undefined>;
|
|
declare const mobile: {
|
|
isNative: typeof isNative;
|
|
platform: typeof platform;
|
|
registerPlugin: typeof registerPlugin;
|
|
plugin: typeof plugin;
|
|
requirePlugin: typeof requirePlugin;
|
|
invoke: typeof invoke;
|
|
whenNative: typeof whenNative;
|
|
};
|
|
|
|
export { type CapacitorBridge, type DeepLink, type DeepLinkSource, type MobileEnvironment, type MobilePlatform, MobileUnavailableError, OfflineQueue, type OfflineTask, type OfflineTaskStore, type PushAdapter, PushNotifications, type PushRegistration, SecureStorage, type SecureStorageAdapter, invoke, isNative, listenDeepLinks, memoryOfflineTaskStore, mobile, mobileEnvironment, parseDeepLink, platform, plugin, registerPlugin, requirePlugin, whenNative };
|
|
</code></pre></section><section id="examples" class="examples"><h2>Examples</h2><p>Copy-ready examples from the installed package documentation.</p><div class="example-grid"><article class="example-card"><h3>Register and invoke a Capacitor plugin</h3><pre data-language="ts"><code>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,
|
|
});
|
|
}</code></pre></article><article class="example-card"><h3>Provide a browser fallback</h3><pre data-language="ts"><code>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),
|
|
);</code></pre></article><article class="example-card"><h3>Read an optional plugin without throwing</h3><pre data-language="ts"><code>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" };</code></pre></article></div></section></article></div>
|
|
<aside class="on-this-page"><h2>On this page</h2><nav><a class="toc-level-2" href="#guide">Guide</a><a class="toc-level-3" href="#overview">Overview</a><a class="toc-level-3" href="#usage">Usage</a><a class="toc-level-4" href="#register-and-invoke-a-capacitor-plugin">Register and invoke a Capacitor plugin</a><a class="toc-level-4" href="#provide-a-browser-fallback">Provide a browser fallback</a><a class="toc-level-4" href="#read-an-optional-plugin-without-throwing">Read an optional plugin without throwing</a><a class="toc-level-3" href="#api">API</a><a class="toc-level-3" href="#requirements-notes">Requirements / Notes</a><a class="toc-level-2" href="#api">Complete API</a><a class="toc-level-2" href="#examples">Examples</a></nav></aside>
|
|
</main>
|
|
<footer><div class="footer-brand"><span class="footer-mark" aria-hidden="true">W</span><p><strong>WRNexusJS 0.8.8</strong><span>Complete API documentation generated from installed package declarations.</span></p></div><nav aria-label="Footer"><a href="/packages">All packages</a><a href="/getting-started">Get started</a><a href="/security">Security</a><a href="/support">Support</a><a href="/llms.txt">AI guide</a></nav><p class="footer-meta">Private Developer Preview · Bun-native</p></footer>
|
|
</div>
|
|
}
|
|
}
|