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

@artatol-acp/auth-js

v0.5.0

Published

Vanilla JavaScript/TypeScript SDK for ACP Auth

Readme

@artatol-acp/auth-js

JavaScript SDK for Artatol Cloud Platform Authentication.

Changelog

v0.4.0

Breaking Changes:

  • apiKey is now optional in ACPAuthClientOptions

Improvements:

  • Better error messages: baseUrl validation now throws a clear error message instead of cryptic Cannot read properties of undefined
  • Improved ACPAuthError: Error message is now always properly extracted from API response
    • New helper methods: isAuthError(), isValidationError(), isNetworkError()
    • Added code property for error codes
  • Better network error handling: Network errors are now wrapped in ACPAuthError with clear messages
  • New FetchFunction type: Custom fetch functions are now typed more flexibly for compatibility with Bun and other runtimes

Installation

npm install @artatol-acp/auth-js
# or
pnpm add @artatol-acp/auth-js
# or
yarn add @artatol-acp/auth-js

Prerequisites

Before using this SDK, you need to obtain from the ACP AUTH service:

  1. API Key (required) - Contact your system administrator for an API key for your application
  2. Base URL (required) - The auth service URL (e.g., https://sso.artatol.net)

This SDK handles all authentication operations via API calls and does not require JWT verification on the client side.

Features

  • Automatic Token Refresh: Automatically refreshes access tokens before they expire
  • Email Verification: Built-in email verification flow
  • Two-Factor Authentication: Support for TOTP-based 2FA
  • Password Reset: Secure password reset flow
  • Account Management: Complete user account lifecycle management

Usage

import { ACPAuthClient } from '@artatol-acp/auth-js';

const client = new ACPAuthClient({
  baseUrl: 'https://sso.artatol.net',
  apiKey: 'your-api-key-here',
  // Optional: Configure automatic token refresh (enabled by default)
  autoRefresh: true,
  refreshThresholdSeconds: 60 // Refresh token 60 seconds before expiration
});

// Register
const user = await client.register({
  email: '[email protected]',
  password: 'securepassword123'
});
// User will receive verification email

// Login
const loginResult = await client.login({
  email: '[email protected]',
  password: 'securepassword123'
});

if ('requiresTwoFactor' in loginResult) {
  // 2FA required
  const { accessToken, user } = await client.verify2FALogin({
    tempToken: loginResult.tempToken,
    code: '123456'
  });
} else {
  // Login successful
  const { accessToken, user } = loginResult;
}

// Refresh token
const { accessToken } = await client.refresh();

// Setup 2FA
const { secret, qrCodeUrl, recoveryCodes } = await client.setup2FA(
  { password: 'current-password' },
  accessToken
);

// Verify 2FA
await client.verify2FA({ code: '123456' }, accessToken);

// Disable 2FA
await client.disable2FA(
  { password: 'current-password', code: '123456' },
  accessToken
);

// Forgot password
await client.forgotPassword({ email: '[email protected]' });

// Reset password
await client.resetPassword({
  token: 'reset-token-from-email',
  newPassword: 'newSecurePassword123'
});

// Delete account
await client.deleteAccount(
  { password: 'current-password', confirmation: 'DELETE' },
  accessToken
);

// Verify email
await client.verifyEmail({ token: 'token-from-email' });

// Resend verification email
await client.resendVerificationEmail({ email: '[email protected]' });

// Logout
await client.logout();

Password Requirements

Passwords must meet the following requirements:

  • Minimum 10 characters
  • At least one lowercase letter (a-z)
  • At least one uppercase letter (A-Z)
  • At least one number (0-9)
function validatePassword(password: string): string[] {
  const errors: string[] = [];

  if (password.length < 10) {
    errors.push('Password must be at least 10 characters');
  }
  if (!/[a-z]/.test(password)) {
    errors.push('Password must contain at least one lowercase letter');
  }
  if (!/[A-Z]/.test(password)) {
    errors.push('Password must contain at least one uppercase letter');
  }
  if (!/[0-9]/.test(password)) {
    errors.push('Password must contain at least one number');
  }

  return errors;
}

Email Verification

After registration, users must verify their email address before they can log in. The auth service automatically sends a verification email upon registration.

Verification Flow

  1. User registers → receives verification email
  2. User clicks link in email → email is verified
  3. User can now log in

Example Usage

import { ACPAuthClient } from '@artatol-acp/auth-js';

const client = new ACPAuthClient({
  baseUrl: 'https://sso.artatol.net',
  apiKey: 'your-api-key-here'
});

// Register - sends verification email automatically
await client.register({
  email: '[email protected]',
  password: 'SecurePass123'
});

// Verify email using token from email
try {
  await client.verifyEmail({ token: 'token-from-email-link' });
  console.log('Email verified successfully');
} catch (error) {
  console.error('Verification failed:', error);
}

// Resend verification email if needed
await client.resendVerificationEmail({ email: '[email protected]' });
// Always succeeds to prevent email enumeration

// Login - will fail if email not verified
try {
  const result = await client.login({
    email: '[email protected]',
    password: 'SecurePass123'
  });
} catch (error) {
  if (error.message?.includes('Email not verified')) {
    console.error('Please verify your email before logging in');
  }
}

API Reference

Constructor

new ACPAuthClient(options: ACPAuthClientOptions)

Options:

  • baseUrl (string, required): Base URL of the ACP AUTH service
  • apiKey (string, required): API key for authenticating your application
  • fetch (function, optional): Custom fetch implementation
  • autoRefresh (boolean, optional, default: true): Enable automatic token refresh
  • refreshThresholdSeconds (number, optional, default: 60): Number of seconds before token expiration to trigger auto-refresh

Methods

All methods return a Promise.

register(data: RegisterRequest): Promise<User>

Register a new user. Automatically sends a verification email.

verifyEmail(data: VerifyEmailRequest): Promise<{ message: string }>

Verify user's email address using the token from the verification email.

resendVerificationEmail(data: ResendVerificationEmailRequest): Promise<{ message: string }>

Resend verification email to the user.

login(data: LoginRequest): Promise<LoginResult>

Login a user. Returns either login response with tokens or 2FA requirement.

verify2FALogin(data: Verify2FALoginRequest): Promise<LoginResponse>

Complete 2FA login flow.

logout(): Promise<{ message: string }>

Logout the current user.

refresh(): Promise<RefreshResponse>

Refresh the access token using the refresh token cookie.

me(accessToken?: string): Promise<User>

Get current user information. Uses the internally stored access token if not provided. Returns full user data including 2FA status.

type User = {
  id: string;
  email: string;
  twoFactorEnabled: boolean;
};

setup2FA(data: Setup2FARequest, accessToken: string): Promise<Setup2FAResponse>

Setup 2FA for the authenticated user.

verify2FA(data: Verify2FARequest, accessToken: string): Promise<{ message: string }>

Verify and enable 2FA.

disable2FA(data: Disable2FARequest, accessToken: string): Promise<{ message: string }>

Disable 2FA for the authenticated user.

forgotPassword(data: ForgotPasswordRequest): Promise<{ message: string }>

Request a password reset.

resetPassword(data: ResetPasswordRequest): Promise<{ message: string }>

Reset password using the token from email.

deleteAccount(data: DeleteAccountRequest, accessToken: string): Promise<{ message: string }>

Delete the authenticated user's account.

health(): Promise<{ status: string; timestamp: string }>

Check API health status.

Automatic Token Refresh

The SDK provides lazy auto-refresh - it checks and refreshes tokens before each API request if they're close to expiration.

How It Works (Lazy Mode)

  1. When you call login() or verify2FALogin(), the SDK automatically stores the access token internally
  2. Before each API request, the SDK checks if the token is close to expiration
  3. If the token will expire within refreshThresholdSeconds (default: 60 seconds), it automatically refreshes
  4. The refresh happens in the background, transparent to your application
  5. All subsequent requests use the new token

Note: This is "lazy" refresh - it only refreshes when you make an API call. For proactive refresh with intervals, use the framework-specific SDKs (Next.js or Nuxt) which implement background refresh timers.

Configuration

const client = new ACPAuthClient({
  baseUrl: 'https://sso.artatol.net',
  apiKey: 'your-api-key',
  autoRefresh: true, // Enable auto-refresh (default: true)
  refreshThresholdSeconds: 60 // Refresh 60s before expiration (default: 60)
});

// After login, the token is automatically managed
const result = await client.login({ email: '...', password: '...' });

// All subsequent calls automatically use and refresh the token
const user = await client.me(); // No need to pass accessToken
await client.setup2FA({ password: '...' }); // Token automatically refreshed if needed

Manual Token Management

You can also manually manage tokens if needed:

// Set token manually
client.setAccessToken('your-token', 300); // 300 seconds expiry

// Get current token
const token = client.getAccessToken();

// Clear token
client.setAccessToken(null);

Disabling Auto-Refresh

If you prefer to handle token refresh manually:

const client = new ACPAuthClient({
  baseUrl: 'https://sso.artatol.net',
  apiKey: 'your-api-key',
  autoRefresh: false // Disable auto-refresh
});

// Manually refresh when needed
const { accessToken } = await client.refresh();
client.setAccessToken(accessToken, 300);

Error Handling

import { ACPAuthError } from '@artatol-acp/auth-js';

try {
  await client.login({ email: '[email protected]', password: 'wrong' });
} catch (error) {
  if (error instanceof ACPAuthError) {
    console.error('Auth error:', error.message);
    console.error('Status code:', error.statusCode);
  }
}

License

MIT