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

mesauth-angular

v0.2.14

Published

Angular helper library to connect to a backend API and SignalR hub to surface the current logged-in user and incoming notifications with dark/light theme support

Downloads

1,831

Readme

mesauth-angular

Angular helper library to connect to a backend API and SignalR hub to surface the current logged-in user and incoming notifications with dark/light theme support.

Features

  • 🔐 Authentication: User login/logout with API integration
  • 🔔 Real-time Notifications: SignalR integration for live notifications
  • 🎨 Dark/Light Theme: Automatic theme detection and support
  • 🖼️ Avatar Support: Direct API-based avatar loading
  • 🍞 Toast Notifications: In-app notification toasts
  • 🛡️ HTTP Interceptor: Automatic 403 error handling

Theme Support

The library automatically detects and adapts to your application's theme:

Automatic Theme Detection

The library checks for theme indicators on the <html> element:

  • class="dark"
  • data-theme="dark"
  • theme="dark"
  • data-coreui-theme="dark"

Dynamic Theme Changes

Theme changes are detected in real-time using MutationObserver, so components automatically update when your app switches themes.

Manual Theme Control

import { ThemeService } from 'mesauth-angular';

// Check current theme
const currentTheme = themeService.currentTheme; // 'light' | 'dark'

// Manually set theme
themeService.setTheme('dark');

// Listen for theme changes
themeService.currentTheme$.subscribe(theme => {
  console.log('Theme changed to:', theme);
});

Avatar Loading

Avatars are loaded directly from your API using the pattern: GET /auth/{userId}/avatar

  • API Endpoint: GET {apiBaseUrl}/auth/{userId}/avatar
  • Fallback: UI Avatars service if userId is not available
  • Authentication: Uses the same credentials as other API calls

Quick Start

Quick Start

  1. Install (from local folder during development):

    cd /path/to/your/angular-app
    npm install ../path/to/mesauth-angular
  2. Provide the service and import components:

    • For standalone components/apps: Import MesAuthModule in your standalone component or app.config.ts.
      import { MesAuthModule } from 'mesauth-angular';
      
      @Component({
        standalone: true,
        imports: [MesAuthModule, /* other imports */],
        // ...
      })
      export class MyComponent {}
      Or in app.config.ts:
      import { MesAuthModule } from 'mesauth-angular';
      
      export const appConfig: ApplicationConfig = {
        imports: [MesAuthModule],
        // ... other config
      };
    • For module-based apps: Import MesAuthModule in your AppModule or feature module.
      import { MesAuthModule } from 'mesauth-angular';
      
      @NgModule({
        imports: [MesAuthModule],
        // ... other config
      })
      export class AppModule { }
  3. (Optional) Provide the HTTP interceptor to handle 403 errors:

    • The interceptor redirects to ${userBaseUrl}/403?returnUrl=encodedCurrentUrl using window.location.href for external URLs (since userBaseUrl may be outside the client app).
    • For module-based apps: Add MesAuthInterceptor to providers in AppModule.
      import { HTTP_INTERCEPTORS } from '@angular/common/http';
      import { MesAuthInterceptor } from 'mesauth-angular';
      
      @NgModule({
        // ... other module config ...
        providers: [
          // ... other providers ...
          { provide: HTTP_INTERCEPTORS, useClass: MesAuthInterceptor, multi: true }
        ]
      })
      export class AppModule { }
    • For standalone apps: Add MesAuthInterceptor to providers in app.config.ts.
      import { HTTP_INTERCEPTORS } from '@angular/common/http';
      import { MesAuthInterceptor } from 'mesauth-angular';
      
      export const appConfig: ApplicationConfig = {
        providers: [
          // ... other providers ...
          { provide: HTTP_INTERCEPTORS, useClass: MesAuthInterceptor, multi: true }
        ]
      };
  4. Initialize in your app (e.g. AppComponent constructor or AppModule bootstrap):

    // in AppComponent
    constructor(private mesAuth: MesAuthService) {
      this.mesAuth.init({
        apiBaseUrl: 'https://api.example.com',
        withCredentials: true,
        userBaseUrl: 'https://api.example.com/users'
      });
    
      this.mesAuth.currentUser$.subscribe(user => console.log('user', user));
      this.mesAuth.notifications$.subscribe(n => console.log('notif', n));
    }

    Alternatively, for standalone components or functions (where constructor injection isn't available), use Angular's inject():

    // In a standalone component or function
    const mesAuth = inject(MesAuthService);
    mesAuth.init({
      apiBaseUrl: 'https://api.example.com',
      withCredentials: true,
      userBaseUrl: 'https://api.example.com/users'
    });
    
    mesAuth.currentUser$.subscribe(user => console.log('user', user));
    mesAuth.notifications$.subscribe(n => console.log('notif', n));

    For Standalone Apps (using bootstrapApplication):

    • After providing the service as above, initialize it using APP_INITIALIZER in your app.config.ts for app-wide setup, or in the root component.

    • Example in app.config.ts (add to providers):

      import { APP_INITIALIZER } from '@angular/core';
      import { MesAuthService } from 'mesauth-angular';
      
      export const appConfig: ApplicationConfig = {
        providers: [
          // ... other providers ...
          MesAuthService,
          {
            provide: APP_INITIALIZER,
            useFactory: (mesAuth: MesAuthService) => () => {
              mesAuth.init({
                apiBaseUrl: 'https://api.example.com',
                withCredentials: true,
                userBaseUrl: 'https://api.example.com/users'
              });
            },
            deps: [MesAuthService],
            multi: true
          }
        ]
      };
    • Then, in your root component (e.g., AppComponent), subscribe to observables as usual:

      // In AppComponent (standalone)
      constructor() {
        const mesAuth = inject(MesAuthService);
        mesAuth.currentUser$.subscribe(user => console.log('user', user));
        mesAuth.notifications$.subscribe(n => console.log('notif', n));
      }
  5. Build the package for publishing:

    cd /path/to/mesauth-angular
    npm install
    npm run build

Components

Note: All components are standalone and can only be imported in standalone components or apps. If your app uses NgModules, use dynamic imports or convert to standalone.

ma-user-profile

A reusable Angular component for displaying the current user's profile information, with options for navigation and logout.

  • Description: Renders user details (e.g., name, avatar) fetched via the MesAuthService. Supports custom event handlers for navigation and logout actions.

  • Inputs: None (data is sourced from the MesAuthService).

  • Outputs:

    • onNavigate: Emits an event when the user triggers navigation (e.g., to a profile page). Pass a handler to define behavior.
    • onLogout: Emits an event when the user logs out. Pass a handler to perform logout logic (e.g., clear tokens, redirect).
  • Usage Example:

    <ma-user-profile 
      (onNavigate)="handleNavigation($event)"
      (onLogout)="handleLogout()">
    </ma-user-profile>

    In your component's TypeScript file:

    handleNavigation(event: any) {
      // Navigate to user profile page
      this.router.navigate(['/profile']);
    }
    
    handleLogout() {
      // Perform logout, e.g., clear session and redirect
      this.mesAuth.logout(); // Assuming a logout method exists
      this.router.navigate(['/login']);
    }

ma-notification-panel

A standalone component for displaying a slide-out notification panel with real-time updates.

  • Description: Shows a list of notifications, allows marking as read/delete, and integrates with toast notifications for new alerts.

  • Inputs: None.

  • Outputs: None (uses internal methods for actions).

  • Usage Example:

    <ma-notification-panel #notificationPanel></ma-notification-panel>

    In your component:

    // To open the panel
    notificationPanel.open();

Changelog

v0.2.13 (Latest)

  • 🎨 Notification Format: Cleaned up notification title format by removing redundant [sourceAppName] prefix
  • 📱 Improved Layout: Source app name now displayed separately in metadata row for better organization
  • 🔔 Consistent Toasts: Toast notifications also updated to use clean title format without app name prefix

v0.2.12

  • 📝 HTML Message Support: Added priority support for messageHtml over message in notifications
  • 🎨 Rich Text Display: Notifications now render HTML content when available, with fallback to plain text
  • 🔔 Enhanced Toasts: Toast notifications also support HTML content with proper rendering

v0.2.9

  • 🔐 Credentials Fix: Added withCredentials: true to all HTTP requests to properly send authentication cookies
  • 🐛 403 Forbidden Fix: Resolved authentication issues where API calls were failing due to missing credentials
  • 🔧 Consistent Auth: All API endpoints now properly include credentials for authenticated requests

v0.2.8

  • 🔄 Route Change Optimization: Improved route change detection with debouncing and selective refreshing
  • 🛡️ Protected Route Handling: Only refresh user data on protected routes, avoiding auth flow interference
  • 🔧 Smart URL Construction: Fixed double /auth path issue for auth endpoints when apiBaseUrl includes /auth
  • ⏱️ Timing Improvements: Added delays and better timing for authentication state management

v0.2.7

  • 🔄 Route Change Detection: Added automatic user data refresh when routes change in single-page applications
  • 🎯 SPA Support: Handles login scenarios where page doesn't reload but route changes occur
  • 🛡️ Optional Dependency: Router integration is optional - service works with or without Router injection

v0.2.6

  • 🗑️ Delete Button: Added delete button for read notifications in the read tab
  • 🎯 Contextual Actions: Unread notifications show "mark as read" button, read notifications show "delete" button
  • 🎨 Visual Feedback: Delete button uses error color on hover for clear destructive action indication

v0.2.5

  • 🗂️ Notification Tabs: Added tabs to separate unread and read notifications with unread tab as default
  • 📊 Tab Counters: Display notification counts for each tab (Unread/Read)
  • 🎯 Improved UX: Better organization of notifications with tab-based navigation
  • 🔄 Enhanced Filtering: Load both read and unread notifications for seamless tab switching

v0.2.4

  • 🔔 Notification UX: Changed notification delete button to mark-as-read with checkmark icon
  • 🔄 Badge Updates: Added automatic badge counter refresh when notifications are marked as read
  • 🎯 Event System: Implemented event-driven communication between notification panel and badge components

v0.2.3

  • 🧹 Code Cleanup: Removed all console.log and console.error statements for production readiness
  • 📚 Documentation: Updated README with comprehensive changelog, theme support guide, and API documentation
  • 🏷️ Package Metadata: Updated package description to reflect theme support

v0.2.2

  • Theme Support: Added automatic dark/light theme detection and real-time theme switching
  • 🖼️ Avatar API: Changed avatar loading to use API endpoint (/auth/{userId}/avatar) instead of external service
  • 🎨 UI Improvements: Better toast styling with proper borders and sizing

v0.2.1

  • 🔄 Dynamic Themes: Added real-time theme change detection using MutationObserver
  • 🐛 Toast Fixes: Improved toast background and sizing for dark themes

v0.2.0

  • 🎨 Initial Theme Support: Basic dark/light theme implementation
  • 🖼️ Avatar Updates: Changed to API-based avatar loading

v0.1.20

  • 🐛 Bug fixes and improvements

Notes

  • The service expects an endpoint GET {apiBaseUrl}/auth/me that returns the current user.
  • Avatar endpoint: GET {apiBaseUrl}/auth/{userId}/avatar
  • SignalR events used: ReceiveNotification (adjust to your backend).

Troubleshooting

JIT Compiler Error in Production or AOT Mode

If you encounter an error like "The injectable 'MesAuthService' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available," this typically occurs because:

  • The package is being imported directly from source code (e.g., during development) without building it first.
  • The client app is running in AOT (Ahead-of-Time) compilation mode, which requires pre-compiled libraries.
  • Why JIT is required: Originally, MesAuthService used @Injectable({ providedIn: 'root' }), making it a library-provided service. Angular libraries must be built with tools like ng-packagr to generate AOT-compatible code. If not, or if imported from source, the service requires JIT compilation in the client's app. This change (removing providedIn: 'root' and requiring manual provision) allows the service to be compiled in your app's context, supporting both JIT and AOT modes.

Solutions:

  1. Build the package for production/AOT compatibility:

    • Ensure you have built the package using npm run build (which uses ng-packagr or similar to generate AOT-ready code).
    • Install the built package via npm (e.g., from a local tarball or registry) instead of linking to the source folder.
  2. For development (if you must link to source):

    • Switch your Angular app to JIT mode by bootstrapping with @angular/platform-browser-dynamic instead of @angular/platform-browser.
    • Example in main.ts:
      import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
      import { AppModule } from './app/app.module';
      
      platformBrowserDynamic().bootstrapModule(AppModule);
    • Note: JIT is not recommended for production; use AOT for better performance.
  3. Verify imports:

    • Ensure you're importing from the built package (e.g., import { MesAuthService } from 'mesauth-angular';) and not from the src folder.
    • If using standalone components, confirm the service is available in the injection context.

If issues persist, check your Angular version compatibility and ensure the package's package.json includes the correct entry points for AOT.

Components Appear Empty

If components like ma-user or ma-user-profile render as empty:

  • Ensure MesAuthService is provided in your app (see Quick Start step 2).
  • Check browser console for logs from components (e.g., "UserProfileComponent: currentUser").
  • If currentUser is null, the component shows a login button—verify the service is initialized and the API returns user data.
  • For standalone apps, confirm APP_INITIALIZER or manual init is used.

Dynamic import in a module-based component

import { Component } from '@angular/core';

@Component({...}) export class DefaultHeaderComponent { async ngOnInit() { const { MaUserComponent } = await import('mesauth-angular'); // Use it dynamically } }