@bastionauth/core
v0.1.7
Published
Shared types, constants, and utilities for BastionAuth
Downloads
956
Maintainers
Readme
@bastionauth/core
📚 Table of Contents
- What is BastionAuth?
- When to Use This Package
- Installation
- What's Included
- Complete Type Reference
- Validation Utilities
- Constants & Configuration
- Real-World Examples
- Use Cases
- TypeScript Best Practices
- FAQs
- Related Packages
🏰 What is BastionAuth?
BastionAuth is a complete, self-hostable enterprise authentication system that gives you the developer experience of Clerk with full data sovereignty.
Key Features
- 🔐 Complete Authentication - Email/password, OAuth (Google, GitHub, Microsoft, Apple, LinkedIn), magic links, passkeys
- 🔑 Multi-Factor Authentication - TOTP, backup codes, WebAuthn support
- 🏢 Organizations & RBAC - Full multi-tenancy with role-based access control
- 🎨 Beautiful React Components - Pre-built UI with glass morphism design
- ⚡ Next.js Integration - Middleware, server components, API helpers
- 🔒 Enterprise Security - Argon2id hashing, RS256 JWT, breach detection, audit logging
- 📊 Admin Dashboard - User management, organization control, webhooks, analytics
- 🐳 Self-Hosted - Full control over your data, no per-MAU costs, HIPAA/FedRAMP ready
Learn more: https://bastionauth.dev
🎯 When to Use This Package
✅ You SHOULD use @bastionauth/core if you:
- Are building a custom API client for BastionAuth
- Need type definitions for your custom integration
- Are building a backend service that integrates with BastionAuth
- Want to create a CLI tool for managing BastionAuth
- Need validation utilities for email, passwords, etc.
- Are building a non-React frontend (Vue, Angular, Svelte, etc.)
- Want to build custom authentication UI from scratch
- Need TypeScript types for API responses
❌ You should NOT use this if you:
- Are building a React app → Use
@bastionauth/react - Are building with Next.js → Use
@bastionauth/nextjs - Want pre-built UI components → Use
@bastionauth/react
📦 Installation
npm install @bastionauth/coreOr using other package managers:
# pnpm
pnpm add @bastionauth/core
# yarn
yarn add @bastionauth/core
# bun
bun add @bastionauth/coreTypeScript Configuration
Ensure your tsconfig.json includes:
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"esModuleInterop": true
}
}📂 What's Included
This package contains NO UI components and NO framework-specific code. It's a pure TypeScript library with:
| Category | What It Includes | |----------|------------------| | Types | User, Session, Organization, Token, MFA, Webhook, Audit Log types | | Validation | Email, password, phone, URL validators | | Constants | Password rules, token config, error codes, event names | | Utilities | Helper functions for data manipulation and validation | | Enums | User roles, session status, organization roles, MFA methods |
Bundle Size: ~15KB (minified) - Minimal footprint!
🔤 Complete Type Reference
User Types
User - Complete User Object
import type { User } from '@bastionauth/core';
const user: User = {
// Core Identity
id: 'user_1234567890',
email: '[email protected]',
emailVerified: true,
phone: '+15551234567',
phoneVerified: false,
// Personal Information
firstName: 'John',
lastName: 'Doe',
username: 'johndoe',
avatarUrl: 'https://cdn.example.com/avatars/johndoe.jpg',
// Authentication
passwordHash: null, // Only populated on backend
mfaEnabled: true,
// Status & Metadata
status: 'active', // 'active' | 'suspended' | 'banned' | 'deleted'
role: 'user', // 'user' | 'admin' | 'moderator'
metadata: {
source: 'google_oauth',
lastLoginIp: '192.168.1.1',
customField: 'custom value'
},
// Timestamps
createdAt: new Date('2024-01-01'),
updatedAt: new Date('2024-01-15'),
lastActiveAt: new Date('2024-01-15T10:30:00'),
emailVerifiedAt: new Date('2024-01-01'),
};PublicUser - Public-Safe User Data
import type { PublicUser } from '@bastionauth/core';
// Safe to expose in public APIs
const publicUser: PublicUser = {
id: 'user_1234567890',
firstName: 'John',
lastName: 'Doe',
username: 'johndoe',
avatarUrl: 'https://cdn.example.com/avatars/johndoe.jpg',
createdAt: new Date('2024-01-01'),
};
// Excludes: email, phone, passwordHash, mfaEnabled, metadataUserMetadata - Custom User Metadata
import type { UserMetadata } from '@bastionauth/core';
const metadata: UserMetadata = {
// Completely flexible - add any custom fields
companyName: 'Acme Corp',
department: 'Engineering',
employeeId: 'EMP-12345',
preferences: {
theme: 'dark',
language: 'en-US',
},
tags: ['premium', 'beta-tester'],
};Authentication Types
SignInRequest - Sign-In Payload
import type { SignInRequest } from '@bastionauth/core';
// Email/Password Sign-In
const signInRequest: SignInRequest = {
email: '[email protected]',
password: 'SecurePassword123!',
rememberMe: true, // Optional: extend session duration
mfaCode: '123456', // Optional: if MFA is enabled
};SignUpRequest - Registration Payload
import type { SignUpRequest } from '@bastionauth/core';
const signUpRequest: SignUpRequest = {
email: '[email protected]',
password: 'SecurePassword123!',
firstName: 'Jane',
lastName: 'Smith',
username: 'janesmith', // Optional
metadata: { // Optional custom fields
source: 'landing-page',
referralCode: 'FRIEND20',
},
};TokenPair - Access + Refresh Tokens
import type { TokenPair } from '@bastionauth/core';
const tokens: TokenPair = {
accessToken: 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...',
refreshToken: 'rt_a1b2c3d4e5f6g7h8i9j0',
expiresIn: 900, // 15 minutes in seconds
tokenType: 'Bearer',
};AccessTokenPayload - JWT Structure
import type { AccessTokenPayload } from '@bastionauth/core';
const jwtPayload: AccessTokenPayload = {
sub: 'user_1234567890', // User ID
email: '[email protected]',
role: 'user',
orgId: 'org_abcd1234', // Active organization ID
orgRole: 'member', // Role in that organization
sessionId: 'sess_xyz789',
iat: 1704067200, // Issued at (Unix timestamp)
exp: 1704067800, // Expires at (Unix timestamp)
};Session Types
Session - Session Object
import type { Session } from '@bastionauth/core';
const session: Session = {
id: 'sess_xyz789',
userId: 'user_1234567890',
// Session Details
status: 'active', // 'active' | 'expired' | 'revoked'
ipAddress: '192.168.1.1',
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...',
// Timestamps
createdAt: new Date('2024-01-15T10:00:00'),
expiresAt: new Date('2024-01-22T10:00:00'),
lastActivityAt: new Date('2024-01-15T10:30:00'),
};Organization Types
Organization - Organization Object
import type { Organization } from '@bastionauth/core';
const organization: Organization = {
id: 'org_abcd1234',
name: 'Acme Corporation',
slug: 'acme-corp',
// Branding
logoUrl: 'https://cdn.example.com/logos/acme.png',
primaryColor: '#6366f1',
// Settings
settings: {
allowSignUps: false,
requireMfa: true,
sessionDuration: 86400, // 24 hours
},
// Metadata
metadata: {
industry: 'Technology',
size: 'enterprise',
},
// Timestamps
createdAt: new Date('2023-01-01'),
updatedAt: new Date('2024-01-15'),
};OrganizationMembership - User's Membership
import type { OrganizationMembership } from '@bastionauth/core';
const membership: OrganizationMembership = {
id: 'mem_xyz123',
userId: 'user_1234567890',
organizationId: 'org_abcd1234',
// Role & Permissions
role: 'admin', // 'owner' | 'admin' | 'member' | 'guest'
permissions: ['users:read', 'users:write', 'settings:read'],
// Timestamps
joinedAt: new Date('2023-06-15'),
createdAt: new Date('2023-06-15'),
updatedAt: new Date('2024-01-15'),
};OrganizationInvitation - Invitation Object
import type { OrganizationInvitation } from '@bastionauth/core';
const invitation: OrganizationInvitation = {
id: 'inv_abc123',
organizationId: 'org_abcd1234',
// Invitation Details
email: '[email protected]',
role: 'member',
invitedBy: 'user_1234567890',
// Status
status: 'pending', // 'pending' | 'accepted' | 'expired' | 'revoked'
token: 'inv_token_secure_random_string',
// Timestamps
createdAt: new Date('2024-01-15'),
expiresAt: new Date('2024-01-22'),
acceptedAt: null,
};MFA Types
MfaMethod - MFA Method Enum
import type { MfaMethod } from '@bastionauth/core';
const method: MfaMethod = 'totp'; // 'totp' | 'sms' | 'email' | 'backup_codes' | 'webauthn'TOTPSetup - TOTP Setup Response
import type { TOTPSetup } from '@bastionauth/core';
const totpSetup: TOTPSetup = {
secret: 'JBSWY3DPEHPK3PXP',
qrCode: 'data:image/png;base64,iVBORw0KGgoAAAANS...',
backupCodes: [
'1234-5678',
'9012-3456',
'7890-1234',
'5678-9012',
'3456-7890',
],
};API Response Types
ApiResponse<T> - Standard API Response
import type { ApiResponse, User } from '@bastionauth/core';
const successResponse: ApiResponse<User> = {
success: true,
data: {
id: 'user_1234567890',
email: '[email protected]',
// ... rest of user data
},
message: 'User fetched successfully',
};
const errorResponse: ApiResponse<never> = {
success: false,
error: {
code: 'USER_NOT_FOUND',
message: 'User with ID user_1234567890 not found',
details: {
userId: 'user_1234567890',
},
},
};PaginatedResponse<T> - Paginated Lists
import type { PaginatedResponse, User } from '@bastionauth/core';
const paginatedUsers: PaginatedResponse<User> = {
data: [
{ id: 'user_1', email: '[email protected]', /* ... */ },
{ id: 'user_2', email: '[email protected]', /* ... */ },
{ id: 'user_3', email: '[email protected]', /* ... */ },
],
pagination: {
page: 1,
perPage: 10,
total: 47,
totalPages: 5,
hasMore: true,
},
};✅ Validation Utilities
Email Validation
import { validateEmail, isValidEmail } from '@bastionauth/core';
// Method 1: Boolean check
if (isValidEmail('[email protected]')) {
console.log('Valid email!');
}
// Method 2: Detailed validation
const result = validateEmail('invalid-email');
if (!result.valid) {
console.error('Email validation failed:', result.error);
// Output: "Email validation failed: Invalid email format"
}
// Examples
isValidEmail('[email protected]'); // ✅ true
isValidEmail('[email protected]'); // ✅ true
isValidEmail('user@'); // ❌ false
isValidEmail('not-an-email'); // ❌ falsePassword Validation
import { validatePassword, PASSWORD_CONFIG } from '@bastionauth/core';
const result = validatePassword('MyPassword123!');
console.log(result);
// {
// valid: true,
// strength: 'strong', // 'weak' | 'medium' | 'strong' | 'very_strong'
// score: 4, // 0-5
// errors: [],
// suggestions: []
// }
// Weak password example
const weakResult = validatePassword('12345678');
console.log(weakResult);
// {
// valid: false,
// strength: 'weak',
// score: 1,
// errors: [
// 'Password must contain at least one uppercase letter',
// 'Password must contain at least one special character'
// ],
// suggestions: [
// 'Add uppercase letters',
// 'Include special characters (!@#$%^&*)'
// ]
// }
// Password configuration
console.log(PASSWORD_CONFIG);
// {
// MIN_LENGTH: 8,
// MAX_LENGTH: 128,
// REQUIRE_UPPERCASE: true,
// REQUIRE_LOWERCASE: true,
// REQUIRE_NUMBER: true,
// REQUIRE_SPECIAL: true,
// SPECIAL_CHARS: '!@#$%^&*()_+-=[]{}|;:,.<>?'
// }Phone Validation
import { validatePhone, formatPhone } from '@bastionauth/core';
// Validate phone numbers
const isValid = validatePhone('+15551234567');
console.log(isValid); // true
// Format phone numbers
const formatted = formatPhone('5551234567', 'US');
console.log(formatted); // '+15551234567'
// Supported formats
validatePhone('+15551234567'); // ✅ true (E.164)
validatePhone('555-123-4567'); // ✅ true (US format)
validatePhone('(555) 123-4567'); // ✅ true (US format with parens)
validatePhone('+44 20 7946 0958'); // ✅ true (UK format)URL Validation
import { validateUrl, isSecureUrl } from '@bastionauth/core';
// Validate URLs
const isValid = validateUrl('https://example.com');
console.log(isValid); // true
// Check if URL is secure (HTTPS)
const isSecure = isSecureUrl('https://example.com');
console.log(isSecure); // true
const notSecure = isSecureUrl('http://example.com');
console.log(notSecure); // false
// Examples
validateUrl('https://example.com'); // ✅ true
validateUrl('http://localhost:3000'); // ✅ true
validateUrl('ftp://files.example.com'); // ✅ true
validateUrl('not-a-url'); // ❌ false
validateUrl('javascript:alert("xss")'); // ❌ false (security)📊 Constants & Configuration
Password Configuration
import { PASSWORD_CONFIG } from '@bastionauth/core';
console.log(PASSWORD_CONFIG);
// {
// MIN_LENGTH: 8,
// MAX_LENGTH: 128,
// REQUIRE_UPPERCASE: true,
// REQUIRE_LOWERCASE: true,
// REQUIRE_NUMBER: true,
// REQUIRE_SPECIAL: true,
// SPECIAL_CHARS: '!@#$%^&*()_+-=[]{}|;:,.<>?',
// MIN_STRENGTH_SCORE: 3 // Out of 5
// }Token Configuration
import { TOKEN_CONFIG } from '@bastionauth/core';
console.log(TOKEN_CONFIG);
// {
// ACCESS_TOKEN_EXPIRY_SECONDS: 900, // 15 minutes
// REFRESH_TOKEN_EXPIRY_SECONDS: 604800, // 7 days
// VERIFICATION_TOKEN_EXPIRY: 86400, // 24 hours
// PASSWORD_RESET_EXPIRY: 3600, // 1 hour
// MAGIC_LINK_EXPIRY: 600, // 10 minutes
// INVITATION_EXPIRY: 604800, // 7 days
// }Session Configuration
import { SESSION_CONFIG } from '@bastionauth/core';
console.log(SESSION_CONFIG);
// {
// DEFAULT_DURATION: 604800, // 7 days
// REMEMBER_ME_DURATION: 2592000, // 30 days
// MAX_CONCURRENT_SESSIONS: 5,
// IDLE_TIMEOUT: 1800, // 30 minutes
// ABSOLUTE_TIMEOUT: 86400, // 24 hours
// }Error Codes
import { ERROR_CODES } from '@bastionauth/core';
console.log(ERROR_CODES);
// {
// // Authentication Errors
// INVALID_CREDENTIALS: 'invalid_credentials',
// EMAIL_NOT_VERIFIED: 'email_not_verified',
// MFA_REQUIRED: 'mfa_required',
// INVALID_MFA_CODE: 'invalid_mfa_code',
//
// // User Errors
// USER_NOT_FOUND: 'user_not_found',
// EMAIL_ALREADY_EXISTS: 'email_already_exists',
// USERNAME_TAKEN: 'username_taken',
// ACCOUNT_SUSPENDED: 'account_suspended',
//
// // Session Errors
// SESSION_EXPIRED: 'session_expired',
// INVALID_TOKEN: 'invalid_token',
// TOKEN_REVOKED: 'token_revoked',
//
// // Organization Errors
// ORG_NOT_FOUND: 'organization_not_found',
// NOT_ORG_MEMBER: 'not_organization_member',
// INSUFFICIENT_PERMISSIONS: 'insufficient_permissions',
//
// // ... and many more
// }Webhook Events
import { WEBHOOK_EVENTS } from '@bastionauth/core';
console.log(WEBHOOK_EVENTS);
// {
// USER_CREATED: 'user.created',
// USER_UPDATED: 'user.updated',
// USER_DELETED: 'user.deleted',
// USER_SIGNED_IN: 'user.signed_in',
// USER_SIGNED_OUT: 'user.signed_out',
//
// SESSION_CREATED: 'session.created',
// SESSION_EXPIRED: 'session.expired',
// SESSION_REVOKED: 'session.revoked',
//
// ORG_CREATED: 'organization.created',
// ORG_MEMBER_ADDED: 'organization.member_added',
// ORG_MEMBER_REMOVED: 'organization.member_removed',
//
// // ... and many more
// }💡 Real-World Examples
Example 1: Custom API Client
Build a type-safe API client for BastionAuth:
import type {
User,
SignInRequest,
TokenPair,
ApiResponse
} from '@bastionauth/core';
import { validateEmail } from '@bastionauth/core';
class BastionAuthClient {
private apiUrl: string;
private accessToken: string | null = null;
constructor(apiUrl: string) {
this.apiUrl = apiUrl;
}
/**
* Sign in a user
*/
async signIn(email: string, password: string): Promise<User> {
// Validate email before sending request
if (!validateEmail(email).valid) {
throw new Error('Invalid email format');
}
const request: SignInRequest = { email, password };
const response = await fetch(`${this.apiUrl}/auth/sign-in`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request),
});
const data: ApiResponse<{ user: User; tokens: TokenPair }> = await response.json();
if (!data.success) {
throw new Error(data.error?.message || 'Sign-in failed');
}
// Store access token
this.accessToken = data.data.tokens.accessToken;
return data.data.user;
}
/**
* Get current user
*/
async getCurrentUser(): Promise<User> {
if (!this.accessToken) {
throw new Error('Not authenticated');
}
const response = await fetch(`${this.apiUrl}/users/me`, {
headers: {
'Authorization': `Bearer ${this.accessToken}`,
},
});
const data: ApiResponse<User> = await response.json();
if (!data.success) {
throw new Error(data.error?.message || 'Failed to fetch user');
}
return data.data;
}
/**
* Update user profile
*/
async updateUser(updates: Partial<User>): Promise<User> {
if (!this.accessToken) {
throw new Error('Not authenticated');
}
const response = await fetch(`${this.apiUrl}/users/me`, {
method: 'PATCH',
headers: {
'Authorization': `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(updates),
});
const data: ApiResponse<User> = await response.json();
if (!data.success) {
throw new Error(data.error?.message || 'Update failed');
}
return data.data;
}
}
// Usage
const client = new BastionAuthClient('https://api.bastionauth.dev');
try {
const user = await client.signIn('[email protected]', 'password123');
console.log('Signed in:', user.email);
const updated = await client.updateUser({
firstName: 'John',
lastName: 'Doe',
});
console.log('Updated user:', updated);
} catch (error) {
console.error('Error:', error.message);
}Example 2: Form Validation
Create a sign-up form validator:
import {
validateEmail,
validatePassword,
type SignUpRequest
} from '@bastionauth/core';
interface ValidationErrors {
email?: string;
password?: string;
firstName?: string;
lastName?: string;
}
function validateSignUpForm(data: SignUpRequest): ValidationErrors {
const errors: ValidationErrors = {};
// Validate email
const emailResult = validateEmail(data.email);
if (!emailResult.valid) {
errors.email = emailResult.error;
}
// Validate password
const passwordResult = validatePassword(data.password);
if (!passwordResult.valid) {
errors.password = passwordResult.errors[0] || 'Password is too weak';
}
// Validate first name
if (!data.firstName || data.firstName.trim().length < 2) {
errors.firstName = 'First name must be at least 2 characters';
}
// Validate last name
if (!data.lastName || data.lastName.trim().length < 2) {
errors.lastName = 'Last name must be at least 2 characters';
}
return errors;
}
// Usage
const formData: SignUpRequest = {
email: '[email protected]',
password: 'SecurePass123!',
firstName: 'Jane',
lastName: 'Smith',
};
const errors = validateSignUpForm(formData);
if (Object.keys(errors).length > 0) {
console.error('Validation errors:', errors);
} else {
console.log('Form is valid!');
// Proceed with sign-up
}Example 3: CLI Tool
Build a CLI for managing BastionAuth users:
import type { User, PaginatedResponse } from '@bastionauth/core';
import { ERROR_CODES } from '@bastionauth/core';
class BastionCLI {
private apiKey: string;
private apiUrl: string;
constructor(apiKey: string, apiUrl: string) {
this.apiKey = apiKey;
this.apiUrl = apiUrl;
}
/**
* List all users with pagination
*/
async listUsers(page: number = 1, perPage: number = 10): Promise<void> {
const response = await fetch(
`${this.apiUrl}/users?page=${page}&perPage=${perPage}`,
{
headers: { 'X-API-Key': this.apiKey },
}
);
const data: PaginatedResponse<User> = await response.json();
console.log('\n📋 Users List\n');
console.log('─'.repeat(80));
data.data.forEach((user, index) => {
console.log(`${index + 1}. ${user.email}`);
console.log(` Name: ${user.firstName} ${user.lastName}`);
console.log(` ID: ${user.id}`);
console.log(` Status: ${user.status}`);
console.log(` Joined: ${user.createdAt.toLocaleDateString()}`);
console.log();
});
console.log('─'.repeat(80));
console.log(`Page ${data.pagination.page} of ${data.pagination.totalPages}`);
console.log(`Total users: ${data.pagination.total}`);
}
/**
* Create a new user
*/
async createUser(email: string, firstName: string, lastName: string): Promise<User> {
const response = await fetch(`${this.apiUrl}/users`, {
method: 'POST',
headers: {
'X-API-Key': this.apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, firstName, lastName }),
});
const data = await response.json();
if (!response.ok) {
if (data.error?.code === ERROR_CODES.EMAIL_ALREADY_EXISTS) {
throw new Error(`User with email ${email} already exists`);
}
throw new Error(data.error?.message || 'Failed to create user');
}
console.log(`✅ Created user: ${email}`);
return data.data;
}
/**
* Delete a user
*/
async deleteUser(userId: string): Promise<void> {
const response = await fetch(`${this.apiUrl}/users/${userId}`, {
method: 'DELETE',
headers: { 'X-API-Key': this.apiKey },
});
if (!response.ok) {
const data = await response.json();
throw new Error(data.error?.message || 'Failed to delete user');
}
console.log(`✅ Deleted user: ${userId}`);
}
}
// Usage
const cli = new BastionCLI('your-api-key', 'https://api.bastionauth.dev');
// List users
await cli.listUsers(1, 10);
// Create user
await cli.createUser('[email protected]', 'John', 'Doe');
// Delete user
await cli.deleteUser('user_1234567890');Example 4: Backend Integration (Express)
Integrate BastionAuth types into an Express.js backend:
import express, { Request, Response, NextFunction } from 'express';
import type { User, AccessTokenPayload } from '@bastionauth/core';
import { ERROR_CODES } from '@bastionauth/core';
import jwt from 'jsonwebtoken';
// Extend Express Request to include user
declare global {
namespace Express {
interface Request {
user?: User;
auth?: AccessTokenPayload;
}
}
}
const app = express();
app.use(express.json());
/**
* Authentication middleware
*/
async function authMiddleware(
req: Request,
res: Response,
next: NextFunction
): Promise<void> {
try {
const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) {
res.status(401).json({
error: ERROR_CODES.INVALID_TOKEN,
message: 'Missing or invalid authorization header',
});
return;
}
const token = authHeader.substring(7); // Remove 'Bearer '
// Verify JWT
const payload = jwt.verify(token, process.env.JWT_PUBLIC_KEY!) as AccessTokenPayload;
// Fetch full user from database
const user = await fetchUserFromDatabase(payload.sub);
if (!user) {
res.status(401).json({
error: ERROR_CODES.USER_NOT_FOUND,
message: 'User not found',
});
return;
}
// Attach to request
req.user = user;
req.auth = payload;
next();
} catch (error) {
res.status(401).json({
error: ERROR_CODES.INVALID_TOKEN,
message: 'Invalid or expired token',
});
}
}
/**
* Get current user
*/
app.get('/api/me', authMiddleware, async (req: Request, res: Response) => {
res.json({
success: true,
data: req.user,
});
});
/**
* Update user profile
*/
app.patch('/api/me', authMiddleware, async (req: Request, res: Response) => {
const updates: Partial<User> = req.body;
// Update user in database
const updatedUser = await updateUserInDatabase(req.auth!.sub, updates);
res.json({
success: true,
data: updatedUser,
});
});
// Helper functions (implement with your database)
async function fetchUserFromDatabase(userId: string): Promise<User | null> {
// Implement your database query
return null;
}
async function updateUserInDatabase(userId: string, updates: Partial<User>): Promise<User> {
// Implement your database update
return {} as User;
}
app.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});🎯 Use Cases
1. Building a Custom Frontend
If you're building a frontend in Vue, Angular, Svelte, or vanilla JavaScript:
import type { User, SignInRequest } from '@bastionauth/core';
import { validateEmail, validatePassword } from '@bastionauth/core';
// Your custom authentication service
class AuthService {
async signIn(email: string, password: string): Promise<User> {
// Validate inputs
if (!validateEmail(email).valid) {
throw new Error('Invalid email');
}
// Make API call
const request: SignInRequest = { email, password };
const response = await fetch('/api/auth/sign-in', {
method: 'POST',
body: JSON.stringify(request),
});
return response.json();
}
}2. Type-Safe Backend
Build a type-safe Node.js/Express/Fastify backend:
import type { User, Organization, Session } from '@bastionauth/core';
import { ERROR_CODES, WEBHOOK_EVENTS } from '@bastionauth/core';
// Your database models will match BastionAuth types
async function createUser(data: Partial<User>): Promise<User> {
// Type-safe database operations
const user = await db.users.create(data);
// Emit webhook event
await emitWebhook(WEBHOOK_EVENTS.USER_CREATED, user);
return user;
}3. Testing & Mocking
Create type-safe mocks for testing:
import type { User } from '@bastionauth/core';
// Mock user factory
function createMockUser(overrides?: Partial<User>): User {
return {
id: 'user_mock_123',
email: '[email protected]',
emailVerified: true,
firstName: 'Test',
lastName: 'User',
status: 'active',
role: 'user',
createdAt: new Date(),
updatedAt: new Date(),
...overrides,
};
}
// Use in tests
const testUser = createMockUser({ email: '[email protected]' });🔧 TypeScript Best Practices
Strict Type Checking
import type { User } from '@bastionauth/core';
// ✅ Good: Type-safe user creation
function createUserProfile(user: User): void {
console.log(user.email); // TypeScript knows this exists
}
// ❌ Bad: Unsafe any type
function unsafeFunction(user: any): void {
console.log(user.emial); // Typo won't be caught!
}Utility Types
import type { User, Organization } from '@bastionauth/core';
// Pick specific fields
type UserSummary = Pick<User, 'id' | 'email' | 'firstName' | 'lastName'>;
// Omit sensitive fields
type SafeUser = Omit<User, 'passwordHash' | 'mfaSecret'>;
// Make all fields optional
type PartialUser = Partial<User>;
// Make all fields required
type CompleteUser = Required<User>;Type Guards
import type { User, PublicUser } from '@bastionauth/core';
function isFullUser(user: User | PublicUser): user is User {
return 'email' in user;
}
function displayUser(user: User | PublicUser): void {
if (isFullUser(user)) {
console.log(user.email); // TypeScript knows email exists
} else {
console.log(user.username); // Only public fields
}
}❓ FAQs
Q: Do I need to install @bastionauth/core separately?
A: No, if you're using @bastionauth/react or @bastionauth/nextjs, they automatically include @bastionauth/core as a dependency. Only install it directly if you're building custom integrations.
Q: Can I use this with JavaScript (not TypeScript)?
A: Yes! While the package is written in TypeScript, it works perfectly with JavaScript. You just won't get type checking and autocompletion.
Q: What's the bundle size?
A: Approximately 15KB (minified), 5KB (gzipped). It's a lightweight package with minimal dependencies.
Q: Does this work with Node.js, Deno, and Bun?
A: Yes! The package is compatible with all modern JavaScript runtimes.
Q: Can I extend the types?
A: Yes! You can use TypeScript's module augmentation:
import '@bastionauth/core';
declare module '@bastionauth/core' {
interface UserMetadata {
customField: string;
companyId: string;
}
}Q: Are the validation functions customizable?
A: The built-in validators use industry best practices. For custom validation, you can build on top of them or create your own using the provided types.
📦 Related Packages
BastionAuth is split into three packages for maximum flexibility:
| Package | Description | When to Use | |---------|-------------|-------------| | @bastionauth/core | Types, constants, utilities | Custom integrations, backends, CLI tools | | @bastionauth/react | React components & hooks | React apps (Vite, CRA, Remix) | | @bastionauth/nextjs | Next.js integration | Next.js apps (middleware, server components) |
Package Dependency Tree
@bastionauth/nextjs
├── @bastionauth/react
│ └── @bastionauth/core
└── @bastionauth/coreYou only install ONE package - npm handles the rest!
📚 Documentation
- Full Documentation: https://docs.bastionauth.dev
- Live Demo: https://bastionauth.dev
- Pricing: https://bastionauth.dev/pricing
- API Reference: https://docs.bastionauth.dev/api/core
💰 Pricing
BastionAuth offers self-hosted authentication with transparent pricing:
- Free Tier: Up to 1,000 monthly active users
- Pro: $29/month for up to 10,000 users
- Enterprise: Custom pricing for unlimited users + premium support
Why Self-Hosted?
- 📊 No per-user costs at scale - Pay for hosting, not for users
- 🔐 Complete data ownership - Your data stays on your infrastructure
- 🌍 GDPR, HIPAA, SOC2 compliance ready - Meet any regulatory requirement
- 🚀 No vendor lock-in - You control your auth infrastructure
💬 Support
Need help? We're here for you:
- Email: [email protected]
- Website: bastionauth.dev
- Documentation: docs.bastionauth.dev
- Discord: Join our community (coming soon)
