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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@mehdashti/auth-react

v0.2.0

Published

React authentication hooks and components for Smart Platform

Readme

@smart/auth-react

React authentication hooks and components for Smart Platform

Installation

pnpm add @smart/auth-react @tanstack/react-query

Features

  • Auth Context: Centralized authentication state
  • Auth Hooks: useAuth, useUser, useHasRole
  • Protected Routes: Component for protecting authenticated routes
  • Token Management: Automatic token storage and retrieval
  • TanStack Query Integration: Works seamlessly with @smart/data-client

Quick Start

1. Setup Auth Provider

import { QueryClientProvider } from "@tanstack/react-query";
import { createQueryClient } from "@smart/data-client";
import { AuthProvider } from "@smart/auth-react";

const queryClient = createQueryClient();

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <AuthProvider
        loginEndpoint="/api/auth/login"
        logoutEndpoint="/api/auth/logout"
        currentUserEndpoint="/api/users/me"
        refreshEndpoint="/api/auth/refresh"
      >
        <YourApp />
      </AuthProvider>
    </QueryClientProvider>
  );
}

2. Use Auth Hooks

import { useAuth } from "@smart/auth-react";

function LoginPage() {
  const { login, isLoading } = useAuth();

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    const formData = new FormData(e.target as HTMLFormElement);

    try {
      await login({
        email: formData.get("email") as string,
        password: formData.get("password") as string,
      });
      // Redirect to dashboard
    } catch (error) {
      console.error("Login failed:", error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input name="email" type="email" required />
      <input name="password" type="password" required />
      <button type="submit" disabled={isLoading}>
        Login
      </button>
    </form>
  );
}

3. Protect Routes

import { ProtectedRoute } from "@smart/auth-react";
import { Navigate } from "react-router-dom";

function Dashboard() {
  return (
    <ProtectedRoute
      fallback={<div>Loading...</div>}
      unauthorized={<Navigate to="/login" />}
    >
      <DashboardContent />
    </ProtectedRoute>
  );
}

Hooks

useAuth

Access authentication state and methods.

import { useAuth } from "@smart/auth-react";

function Header() {
  const { user, isAuthenticated, logout } = useAuth();

  if (!isAuthenticated) {
    return <LoginButton />;
  }

  return (
    <div>
      <span>Welcome, {user?.email}</span>
      <button onClick={logout}>Logout</button>
    </div>
  );
}

useUser

Access current user data.

import { useUser } from "@smart/auth-react";

function UserProfile() {
  const user = useUser();

  if (!user) {
    return <div>Not logged in</div>;
  }

  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

useHasRole

Check if user has a specific role.

import { useHasRole } from "@smart/auth-react";

function AdminPanel() {
  const isAdmin = useHasRole("admin");

  if (!isAdmin) {
    return <div>Access Denied</div>;
  }

  return <div>Admin Panel</div>;
}

useHasAnyRole

Check if user has any of the specified roles.

import { useHasAnyRole } from "@smart/auth-react";

function EditorTools() {
  const canEdit = useHasAnyRole(["admin", "editor"]);

  if (!canEdit) {
    return null;
  }

  return <EditToolbar />;
}

Components

ProtectedRoute

Protect routes that require authentication.

import { ProtectedRoute } from "@smart/auth-react";
import { Navigate } from "react-router-dom";

// Basic usage
<ProtectedRoute>
  <Dashboard />
</ProtectedRoute>

// With custom fallbacks
<ProtectedRoute
  fallback={<Spinner />}
  unauthorized={<Navigate to="/login" />}
>
  <Dashboard />
</ProtectedRoute>

// With role-based access
<ProtectedRoute
  requiredRoles={["admin"]}
  unauthorized={<Navigate to="/forbidden" />}
>
  <AdminPanel />
</ProtectedRoute>

Token Management

Tokens are automatically stored in localStorage.

Manual Token Access

import {
  getAccessToken,
  setTokens,
  clearTokens,
} from "@smart/auth-react";

// Get current access token
const token = getAccessToken();

// Manually set tokens (not usually needed)
setTokens(accessToken, refreshToken);

// Clear tokens
clearTokens();

Integration with Data Client

Use auth tokens automatically with API requests.

import { useApiQuery, apiFetch } from "@smart/data-client";
import { getAccessToken } from "@smart/auth-react";

function UserList() {
  const { data } = useApiQuery({
    queryKey: ["users"],
    queryFn: async () => {
      const token = getAccessToken();
      return apiFetch("/api/users", {
        headers: {
          Authorization: `Bearer ${token}`,
        },
      });
    },
  });

  return <div>{/* Render users */}</div>;
}

Router Integration

React Router

import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom";
import { ProtectedRoute } from "@smart/auth-react";

function AppRoutes() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/login" element={<LoginPage />} />
        <Route
          path="/dashboard"
          element={
            <ProtectedRoute unauthorized={<Navigate to="/login" />}>
              <Dashboard />
            </ProtectedRoute>
          }
        />
        <Route
          path="/admin"
          element={
            <ProtectedRoute
              requiredRoles={["admin"]}
              unauthorized={<Navigate to="/" />}
            >
              <AdminPanel />
            </ProtectedRoute>
          }
        />
      </Routes>
    </BrowserRouter>
  );
}

TanStack Router

import { createRoute } from "@tanstack/react-router";
import { useAuth } from "@smart/auth-react";

const dashboardRoute = createRoute({
  getParentRoute: () => rootRoute,
  path: "/dashboard",
  beforeLoad: async () => {
    const { isAuthenticated } = useAuth();
    if (!isAuthenticated) {
      throw redirect({ to: "/login" });
    }
  },
  component: Dashboard,
});

Error Handling

import { useAuth } from "@smart/auth-react";

function LoginForm() {
  const { login } = useAuth();
  const [error, setError] = useState<string | null>(null);

  const handleLogin = async (credentials) => {
    try {
      setError(null);
      await login(credentials);
    } catch (err) {
      setError(err instanceof Error ? err.message : "Login failed");
    }
  };

  return (
    <form>
      {error && <div className="error">{error}</div>}
      {/* Form fields */}
    </form>
  );
}

Type Safety

All exports are fully typed:

import type {
  User,
  AuthTokens,
  LoginCredentials,
  LoginResponse,
  AuthContextValue,
} from "@smart/auth-react";

License

MIT