npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@piwit/react-native-aws-waf-plugin

v0.1.1

Published

React Native wrapper for AWS WAF challenge.js — exposes WAF token acquisition at the JS app level via a hidden WebView bridge

Readme

react-native-aws-waf-plugin

React Native wrapper for AWS WAF challenge.js. Acquires WAF tokens via a hidden WebView bridge.

AWS WAF also offers native mobile SDKs for Android and iOS, but they require contacting AWS for access and are distributed as private artifacts. This library takes a different approach — it uses the publicly available web SDK (challenge.js) on all platforms, running it inside a hidden WebView. Works out of the box — you can find the challenge.js URL in your AWS WAF console (see docs).

Install

npm install github:piotrekwitkowski/react-native-aws-waf-plugin

Peer dependency: react-native-webview >= 13.

Android

No extra setup. react-native-webview auto-links on RN 0.60+. Just rebuild:

npx react-native run-android

iOS

Install CocoaPods dependencies for react-native-webview, then rebuild:

cd ios && pod install && cd ..
npx react-native run-ios

Quick Start

import { WafProvider, useWafToken } from 'react-native-aws-waf-plugin';

const CHALLENGE_JS = 'https://<your-id>.<region>.sdk.awswaf.com/<your-id>/<your-hash>/challenge.js';
// or edge: 'https://<your-id>.edge.sdk.awswaf.com/<your-id>/<your-hash>/challenge.js'

function App() {
  return (
    <WafProvider challengeJsUrl={CHALLENGE_JS} onReady={() => console.log('WAF ready')}>
      <MyScreen />
    </WafProvider>
  );
}

function MyScreen() {
  const { token, loading, error, refresh } = useWafToken();

  if (loading) return <Text>Acquiring token...</Text>;
  if (error) return <Text>Error: {error.message}</Text>;

  return <Text>Token: {token}</Text>;
}

Script Injection Modes

The library supports two ways to load challenge.js into the hidden WebView. Both avoid putting a <script src="..."> tag directly in the HTML source.

Mode 1: bridge (default)

Pure JS injection. The HTML is a bare shell containing only the message bridge handler. When the shell is ready, the RN bridge creates a <script> element via injectJavaScript and appends it to the document. All loading logic lives on the React Native side.

<WafProvider challengeJsUrl="https://..." />
// equivalent to:
<WafProvider challengeJsUrl="https://..." scriptInjection="bridge" />

Mode 2: html

HTML-based loader. The HTML template includes a __wafLoadScript(url) helper function. The RN bridge calls this function (via injectJavaScript) to kick off script loading. The loading logic lives in the HTML template rather than being constructed from the app layer.

<WafProvider challengeJsUrl="https://..." scriptInjection="html" />

Comparison

| | bridge (default) | html | |---|---|---| | Script loader location | Injected from RN via injectJavaScript | Pre-defined in HTML template (__wafLoadScript) | | HTML contains script logic | No | Yes | | Runtime control | Full, app decides what/when to inject | Partial, app provides URL, HTML loads it |

Pick bridge when you want maximum control from the RN layer. Pick html if you prefer the loading mechanism to be self-contained in the WebView page.

API Reference

<WafProvider>

Wrap your app (or a subtree) with this component. It renders a hidden 0x0 WebView and provides the WAF client to descendant hooks.

| Prop | Type | Default | Description | |---|---|---|---| | challengeJsUrl | string | required | Full URL to the AWS WAF challenge.js script | | scriptInjection | 'bridge' \| 'html' | 'bridge' | How challenge.js is loaded into the WebView | | timeout | number | 10000 | Timeout in ms for bridge operations | | onReady | () => void | undefined | Called when challenge.js has loaded and is ready | | onError | (error: Error) => void | undefined | Called on unrecoverable errors |

useWafToken()

Returns a reactive token state. Automatically fetches a token once the bridge is ready.

const { token, loading, error, refresh } = useWafToken();

| Field | Type | Description | |---|---|---| | token | string \| null | Current token value, or null if not yet acquired | | loading | boolean | Whether a token request is in flight | | error | Error \| null | Last error from token acquisition | | refresh | () => Promise<string> | Manually trigger a fresh token request |

useWafFetch()

Returns a fetch-like function that auto-attaches the WAF token to requests.

const wafFetch = useWafFetch();

const response = await wafFetch('https://api.example.com/data', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ key: 'value' }),
});

console.log(response.status, response.body);

Returns Promise<WafFetchResponse> with { status: number, headers: Record<string, string>, body: string }.

useWafClient()

Returns the underlying WafClient object for direct access. Must be called within a <WafProvider>.

const client = useWafClient();

if (client.isReady) {
  const token = await client.getToken();
  const hasOne = await client.hasToken();
  const resp = await client.fetch(url, options);
}

| Method / Property | Type | Description | |---|---|---| | getToken() | Promise<string> | Get a fresh WAF token | | hasToken() | Promise<boolean> | Check if an unexpired token exists | | fetch(url, options?) | Promise<WafFetchResponse> | Fetch with WAF token auto-attached | | isReady | boolean | Whether challenge.js has loaded |

WafBridge (advanced)

Low-level bridge class for use outside of React. You probably don't need this unless you're building a custom integration.

import { WafBridge } from 'react-native-aws-waf-plugin';

const bridge = new WafBridge(10_000);
bridge.setInjector((js) => webViewRef.current?.injectJavaScript(js));
bridge.setCallbacks(
  () => console.log('ready'),
  (err) => console.error(err),
);

await bridge.whenShellReady();
bridge.loadScript('https://...');

await bridge.whenReady();
const token = await bridge.getToken();

bridge.dispose();

How It Works

  1. WafProvider renders a hidden 0x0 WebView off-screen.
  2. The WebView loads a minimal HTML shell containing a message bridge (listens for postMessage commands).
  3. challenge.js is injected at runtime using the chosen injection mode.
  4. Once loaded, AwsWafIntegration.getToken() and friends become available inside the WebView.
  5. RN hooks send commands via injectJavaScript → the bridge handler calls the WAF SDK → results come back via window.ReactNativeWebView.postMessage.
  6. The token surfaces in your React components through useWafToken() or useWafClient().

License

MIT