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

@pubflow/react-native

v0.4.1

Published

React Native adapter for Pubflow framework - Now with snake_case support and Bridge Payments

Readme

@pubflow/react-native

React Native adapter for the Pubflow framework with Expo support.

📚 Documentation

Overview

@pubflow/react-native provides React Native-specific implementations and utilities for the Pubflow framework, including:

  • Secure storage with Expo SecureStore (with AsyncStorage fallback)
  • React Native-specific components
  • Hooks optimized for mobile applications
  • Bridge Payment Client for payment processing (NEW in v0.3.0)
  • Support for offline mode with mutation queuing

Installation

# Install the core package and React Native adapter
npm install @pubflow/core @pubflow/react-native

# Install required peer dependencies
npm install @react-native-async-storage/async-storage

# Optional: Install Expo SecureStore for enhanced security
npm install expo-secure-store

# Optional: Install NetInfo for better offline support
npm install @react-native-community/netinfo

# Optional: Install Zod for schema validation
npm install zod

# For payments: Install Stripe React Native
npm install @stripe/stripe-react-native

Persistent Cache

Pubflow React Native adapter supports persistent caching to improve performance and offline experience:

import React from 'react';
import { PubflowProvider, createPersistentCache } from '@pubflow/react-native';

function App() {
  // Create a persistent cache provider
  const persistentCacheProvider = createPersistentCache({
    prefix: 'my_rn_app_cache',
    ttl: 24 * 60 * 60 * 1000, // 24 hours
    debug: __DEV__
  });

  return (
    <PubflowProvider
      config={{
        baseUrl: 'https://api.example.com',
        bridgeBasePath: '/bridge',
        authBasePath: '/auth'
      }}
      persistentCache={{
        enabled: true,
        provider: persistentCacheProvider
      }}
    >
      <YourApp />
    </PubflowProvider>
  );
}

export default App;

For more information, see the persistent cache documentation.

Usage

Provider Setup

// App.js
import React from 'react';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { PubflowProvider } from '@pubflow/react-native';
import AppNavigator from './navigation';

export default function App() {
  return (
    <SafeAreaProvider>
      <PubflowProvider
        config={{
          baseUrl: 'https://api.example.com',
          bridgeBasePath: '/bridge',
          authBasePath: '/auth',
          useSecureStorage: true // Use Expo SecureStore when available
        }}
      >
        <AppNavigator />
      </PubflowProvider>
    </SafeAreaProvider>
  );
}

Authentication

// screens/LoginScreen.js
import React, { useState } from 'react';
import { View, TextInput, Button, Text, StyleSheet } from 'react-native';
import { useAuth } from '@pubflow/react-native';

export default function LoginScreen({ navigation }) {
  const { login, isLoading } = useAuth();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');

  const handleLogin = async () => {
    setError('');

    try {
      const result = await login({ email, password });

      if (result.success) {
        navigation.navigate('Home');
      } else {
        setError(result.error || 'Login failed');
      }
    } catch (err) {
      setError('An error occurred during login');
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Login</Text>
      {error ? <Text style={styles.error}>{error}</Text> : null}

      <TextInput
        style={styles.input}
        placeholder="Email"
        value={email}
        onChangeText={setEmail}
        autoCapitalize="none"
        keyboardType="email-address"
      />

      <TextInput
        style={styles.input}
        placeholder="Password"
        value={password}
        onChangeText={setPassword}
        secureTextEntry
      />

      <Button
        title={isLoading ? "Logging in..." : "Login"}
        onPress={handleLogin}
        disabled={isLoading}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    justifyContent: 'center',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  input: {
    height: 50,
    borderWidth: 1,
    borderColor: '#ccc',
    borderRadius: 5,
    marginBottom: 15,
    paddingHorizontal: 10,
  },
  error: {
    color: 'red',
    marginBottom: 10,
  },
});

Protected Screens

// screens/ProfileScreen.js
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { useAuth, BridgeView } from '@pubflow/react-native';

export default function ProfileScreen({ navigation }) {
  const { user, logout } = useAuth();

  const handleLogout = async () => {
    await logout();
    navigation.navigate('Login');
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Profile</Text>

      {user ? (
        <>
          <Text style={styles.text}>Name: {user.name}</Text>
          <Text style={styles.text}>Email: {user.email}</Text>

          <BridgeView
            allowedTypes={['admin']}
            fallback={<Text>Admin-only content is hidden</Text>}
          >
            <Text style={styles.adminText}>Admin-only content</Text>
          </BridgeView>

          <Button title="Logout" onPress={handleLogout} />
        </>
      ) : (
        <Text>Loading user data...</Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  text: {
    fontSize: 16,
    marginBottom: 10,
  },
  adminText: {
    fontSize: 16,
    marginVertical: 20,
    color: 'purple',
    fontWeight: 'bold',
  },
});

Data Operations

// screens/UsersScreen.js
import React from 'react';
import { View, Text, FlatList, TouchableOpacity, StyleSheet } from 'react-native';
import { useBridgeCrud } from '@pubflow/react-native';

export default function UsersScreen({ navigation }) {
  const {
    items: users,
    loading,
    error,
    refresh,
    deleteItem
  } = useBridgeCrud({
    entityConfig: {
      endpoint: 'users'
    }
  });

  const handleDelete = (id) => {
    deleteItem(id);
  };

  if (loading) {
    return (
      <View style={styles.centered}>
        <Text>Loading...</Text>
      </View>
    );
  }

  if (error) {
    return (
      <View style={styles.centered}>
        <Text style={styles.error}>Error: {error.message}</Text>
        <Button title="Retry" onPress={refresh} />
      </View>
    );
  }

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Users</Text>

      <FlatList
        data={users}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <View style={styles.item}>
            <Text style={styles.name}>{item.name}</Text>
            <Text style={styles.email}>{item.email}</Text>
            <TouchableOpacity
              style={styles.deleteButton}
              onPress={() => handleDelete(item.id)}
            >
              <Text style={styles.deleteText}>Delete</Text>
            </TouchableOpacity>
          </View>
        )}
        refreshing={loading}
        onRefresh={refresh}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  centered: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  item: {
    padding: 15,
    borderBottomWidth: 1,
    borderBottomColor: '#ccc',
  },
  name: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  email: {
    fontSize: 14,
    color: '#666',
  },
  error: {
    color: 'red',
    marginBottom: 10,
  },
  deleteButton: {
    marginTop: 10,
    padding: 5,
    backgroundColor: '#ffdddd',
    borderRadius: 5,
    alignSelf: 'flex-start',
  },
  deleteText: {
    color: 'red',
  },
});

BridgeForm Component

Pubflow provides a powerful form component that integrates with Zod schemas and Bridge API:

import { BridgeForm } from '@pubflow/react-native';
import { z } from 'zod';

// Define schema
const userSchema = z.object({
  name: z.string().min(2, 'Name must be at least 2 characters'),
  email: z.string().email('Invalid email address'),
  role: z.enum(['user', 'admin'], 'Role must be either user or admin')
});

function CreateUser() {
  return (
    <View style={{ flex: 1, padding: 16 }}>
      <Text style={{ fontSize: 24, fontWeight: 'bold', marginBottom: 16 }}>
        Create User
      </Text>
      <BridgeForm
        schema={userSchema}
        mode="create"
        entityConfig={{ endpoint: 'users' }}
        mainColor="#c30000"
        onSuccess={(data) => {
          console.log('User created:', data);
          // Navigate or show success message
        }}
      />
    </View>
  );
}

For more information, see the BridgeForm documentation.

Offline Support

The adapter includes robust support for offline operations:

import React from 'react';
import { View, Text, Button } from 'react-native';
import { useBridgeCrud, OfflineIndicator } from '@pubflow/react-native';

export default function ProductsScreen() {
  const {
    items: products,
    createItem,
    isOffline,
    queuedMutations
  } = useBridgeCrud({
    entityConfig: {
      endpoint: 'products'
    },
    offlineConfig: {
      queueMutations: true, // Enable mutation queuing
      showOfflineAlerts: true // Show alerts when operations are queued
    }
  });

  return (
    <View>
      {/* Offline indicator */}
      <OfflineIndicator />

      {/* Pending operations counter */}
      {queuedMutations > 0 && (
        <Text>
          {queuedMutations} operations pending synchronization
        </Text>
      )}

      {/* Create button works even offline */}
      <Button
        title="Add Product"
        onPress={() => createItem({ name: 'New Product', price: 99.99 })}
      />
    </View>
  );
}

For detailed documentation on offline support, see the full documentation.

Debugging Tools

Pubflow provides utilities for debugging storage-related issues:

import { PubflowProvider, debugStorage, clearStorageByPrefix } from '@pubflow/react-native';

// Enable debug tools in the provider
function App() {
  return (
    <PubflowProvider
      config={config}
      enableDebugTools={__DEV__} // Only enable in development
    >
      {/* Your app components */}
    </PubflowProvider>
  );
}

// Use debug utilities
async function debugStorageIssues() {
  // Inspect storage
  const storage = await debugStorage('prefix');
  console.log(storage.keys, storage.values);

  // Clear storage with specific prefix
  await clearStorageByPrefix('prefix');
}

For more information, see the debugging documentation.

Logging Control

Pubflow allows you to control the verbosity of logs to optimize performance:

import { PubflowProvider } from '@pubflow/react-native';

function App() {
  return (
    <PubflowProvider
      config={config}
      loggingConfig={{
        enabled: __DEV__, // Only enable logs in development
        level: 'warn',    // Only show warnings and errors
        storage: false    // Disable storage logs which can be verbose
      }}
    >
      {/* Your app components */}
    </PubflowProvider>
  );
}

For more information, see the logging control documentation.

License

AGPL-3.0-or-later