JavaScript SDK
The Guardhouse JavaScript SDK provides a comprehensive API for integrating Guardhouse into your JavaScript/TypeScript applications, including Node.js, React, Vue, and browser applications.
Installation
npm
npm install @guardhouse/sdk
yarn
yarn add @guardhouse/sdk
pnpm
pnpm add @guardhouse/sdk
CDN
<script src="https://cdn.jsdelivr.net/npm/@guardhouse/sdk@latest/dist/guardhouse.min.js"></script>
Getting Started
Initialize Client
import { GuardhouseClient } from '@guardhouse/sdk';
const client = new GuardhouseClient({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
domain: 'your-tenant.guardhouse.cloud'
});
TypeScript
import { GuardhouseClient, GuardhouseOptions } from '@guardhouse/sdk';
const options: GuardhouseOptions = {
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
domain: 'your-tenant.guardhouse.cloud'
};
const client = new GuardhouseClient(options);
Configuration Options
const client = new GuardhouseClient({
// Required
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
domain: 'your-tenant.guardhouse.cloud',
// Optional
apiVersion: 'v2',
timeout: 30000, // 30 seconds
retryPolicy: {
maxRetries: 3,
delay: 1000,
backoffFactor: 2,
retryableStatusCodes: [408, 429, 500, 502, 503, 504]
},
logLevel: 'debug'
});
User Management
List Users
// Get all users (paginated)
const users = await client.users.getAll();
// With pagination
const users = await client.users.getAll({
page: 1,
perPage: 50
});
// With filtering and sorting
const users = await client.users.getAll({
page: 1,
perPage: 50,
email: 'john.doe@example.com',
query: 'john',
sort: 'created_at',
order: 'desc'
});
// Access results
users.items.forEach(user => {
console.log(`${user.userId}: ${user.name} (${user.email})`);
});
console.log(`Total: ${users.total}`);
console.log(`Page: ${users.page} of ${users.totalPages}`);
Get User by ID
const user = await client.users.get('usr_123456789');
console.log(`User: ${user.name}`);
console.log(`Email: ${user.email}`);
console.log(`Created: ${user.createdAt}`);
console.log(`Last Login: ${user.lastLogin}`);
console.log(`Logins Count: ${user.loginsCount}`);
Update User
const user = await client.users.get('usr_123456789');
// Update basic fields
user.name = 'John Updated Doe';
user.email = 'new.email@example.com';
user.phoneNumber = '+1-555-987-6543';
user.picture = 'https://cdn.example.com/avatars/new.jpg';
// Update metadata
user.userMetadata = {
department: 'Marketing',
employee_id: 'EMP002'
};
user.appMetadata = {
roles: ['user', 'moderator'],
permissions: ['read:users', 'write:users']
};
// Block/Unblock user
user.blocked = false;
// Save changes
const updated = await client.users.update(user);
Create User
const newUser = await client.users.create({
email: 'new.user@example.com',
password: 'SecurePassword123!',
name: 'New User',
connection: 'Username-Password-Authentication',
emailVerified: true,
userMetadata: {
department: 'Engineering'
}
});
Delete User
await client.users.delete('usr_123456789');
Batch Operations
// Update multiple users
const userIds = ['usr_123', 'usr_456', 'usr_789'];
for (const userId of userIds) {
try {
const user = await client.users.get(userId);
user.blocked = false;
await client.users.update(user);
console.log(`Updated user: ${userId}`);
} catch (error) {
console.error(`Failed to update user ${userId}:`, error.message);
}
}
Current User Profile Management
Get Current User Profile
const currentUser = await client.users.getMe();
console.log(`User ID: ${currentUser.userId}`);
console.log(`Name: ${currentUser.name}`);
console.log(`Email: ${currentUser.email}`);
console.log(`Email Verified: ${currentUser.emailVerified}`);
Change Password
await client.users.changePassword({
currentPassword: 'OldPassword123!',
newPassword: 'NewSecurePassword123!',
confirmPassword: 'NewSecurePassword123!'
});
Update Name
await client.users.updateName({
givenName: 'John',
familyName: 'Doe'
});
Update Email
await client.users.updateEmail({
email: 'new.email@example.com',
verifyEmail: true
});
Update Profile
await client.users.updateProfile({
name: 'John Updated Doe',
nickname: 'johndoe_new',
picture: 'https://cdn.example.com/avatars/new.jpg',
userMetadata: {
department: 'Marketing',
location: 'New York'
}
});
Authentication
Get Access Token
const token = await client.auth.getAccessToken();
console.log(`Access Token: ${token.accessToken}`);
console.log(`Token Type: ${token.tokenType}`);
console.log(`Expires In: ${token.expiresIn} seconds`);
console.log(`Scope: ${token.scope}`);
Refresh Token
const newToken = await client.auth.refreshToken(refreshToken);
Revoke Token
await client.auth.revokeToken(accessToken);
User Login
const loginResult = await client.auth.login({
username: 'user@example.com',
password: 'Password123!',
connection: 'Username-Password-Authentication'
});
console.log(`Access Token: ${loginResult.accessToken}`);
console.log(`ID Token: ${loginResult.idToken}`);
console.log(`Refresh Token: ${loginResult.refreshToken}`);
User Logout
await client.auth.logout(refreshToken);
Error Handling
Try-Catch Pattern
try {
const user = await client.users.get('usr_123456789');
} catch (error) {
if (error instanceof GuardhouseApiError) {
// API errors (4xx, 5xx)
console.error(`API Error: ${error.message}`);
console.error(`Code: ${error.code}`);
console.error(`Status: ${error.statusCode}`);
console.error(`Request ID: ${error.requestId}`);
} else if (error instanceof GuardhouseAuthenticationError) {
// Authentication errors (invalid credentials, expired tokens)
console.error(`Authentication failed: ${error.message}`);
} else if (error instanceof GuardhouseValidationError) {
// Validation errors (invalid request data)
console.error(`Validation failed: ${error.message}`);
error.validationErrors.forEach(err => {
console.error(` Field: ${err.field}`);
console.error(` Message: ${err.message}`);
});
}
}
Custom Error Handler
const client = new GuardhouseClient({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
domain: 'your-tenant.guardhouse.cloud',
errorHandler: (error) => {
// Log error
logger.error(`Guardhouse API error: ${error.message}`);
// Send alert
alertService.sendAlert(error);
// Return custom error or throw
throw error;
}
});
Advanced Features
Retry Policy
const client = new GuardhouseClient({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
domain: 'your-tenant.guardhouse.cloud',
retryPolicy: {
maxRetries: 5,
delay: 2000,
backoffFactor: 2,
retryableStatusCodes: [408, 429, 500, 502, 503, 504]
}
});
Request Timeout
const client = new GuardhouseClient({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
domain: 'your-tenant.guardhouse.cloud',
timeout: 30000 // 30 seconds
});
Logging
const client = new GuardhouseClient({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
domain: 'your-tenant.guardhouse.cloud',
logLevel: 'debug',
logger: console
});
Custom Logger
const customLogger = {
debug: (message, ...args) => console.log(`[DEBUG] ${message}`, ...args),
info: (message, ...args) => console.log(`[INFO] ${message}`, ...args),
warn: (message, ...args) => console.warn(`[WARN] ${message}`, ...args),
error: (message, ...args) => console.error(`[ERROR] ${message}`, ...args)
};
const client = new GuardhouseClient({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
domain: 'your-tenant.guardhouse.cloud',
logger: customLogger
});
React Integration
Provider Setup
import React, { createContext, useContext } from 'react';
import { GuardhouseClient } from '@guardhouse/sdk';
const GuardhouseContext = createContext();
export const GuardhouseProvider = ({ children }) => {
const client = new GuardhouseClient({
clientId: process.env.REACT_APP_GUARDHOUSE_CLIENT_ID,
clientSecret: process.env.REACT_APP_GUARDHOUSE_CLIENT_SECRET,
domain: process.env.REACT_APP_GUARDHOUSE_DOMAIN
});
return (
<GuardhouseContext.Provider value={client}>
{children}
</GuardhouseContext.Provider>
);
};
export const useGuardhouse = () => {
const client = useContext(GuardhouseContext);
return client;
};
Custom Hook
import { useState, useEffect } from 'react';
import { useGuardhouse } from './GuardhouseProvider';
export const useUsers = (page = 1, perPage = 50) => {
const client = useGuardhouse();
const [users, setUsers] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchUsers = async () => {
try {
setLoading(true);
const response = await client.users.getAll({ page, perPage });
setUsers(response);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
};
fetchUsers();
}, [page, perPage, client]);
return { users, loading, error };
};
// Usage in component
const UserList = () => {
const { users, loading, error } = useUsers(1, 50);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<ul>
{users?.items.map(user => (
<li key={user.userId}>{user.name} ({user.email})</li>
))}
</ul>
);
};
Component Example
import React, { useState } from 'react';
import { useGuardhouse } from './GuardhouseProvider';
const UserProfile = ({ userId }) => {
const client = useGuardhouse();
const [user, setUser] = useState(null);
const fetchUser = async () => {
try {
const userData = await client.users.get(userId);
setUser(userData);
} catch (error) {
console.error('Failed to fetch user:', error);
}
};
const updateUserName = async () => {
if (!user) return;
try {
user.name = 'Updated Name';
const updated = await client.users.update(user);
setUser(updated);
} catch (error) {
console.error('Failed to update user:', error);
}
};
useEffect(() => {
fetchUser();
}, [userId]);
if (!user) return <div>Loading...</div>;
return (
<div>
<h2>{user.name}</h2>
<p>Email: {user.email}</p>
<button onClick={updateUserName}>Update Name</button>
</div>
);
};
Vue.js Integration
Plugin Setup
// src/plugins/guardhouse.js
import { GuardhouseClient } from '@guardhouse/sdk';
export default {
install: (app) => {
const client = new GuardhouseClient({
clientId: import.meta.env.VITE_GUARDHOUSE_CLIENT_ID,
clientSecret: import.meta.env.VITE_GUARDHOUSE_CLIENT_SECRET,
domain: import.meta.env.VITE_GUARDHOUSE_DOMAIN
});
app.provide('guardhouse', client);
app.config.globalProperties.$guardhouse = client;
}
};
Main.js Registration
import { createApp } from 'vue';
import App from './App.vue';
import guardhousePlugin from './plugins/guardhouse';
const app = createApp(App);
app.use(guardhousePlugin);
app.mount('#app');
Component Usage
<template>
<div>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error }}</div>
<div v-else>
<h2>{{ user?.name }}</h2>
<p>Email: {{ user?.email }}</p>
<button @click="updateUserName">Update Name</button>
</div>
</div>
</template>
<script>
import { ref, onMounted, inject } from 'vue';
export default {
props: {
userId: {
type: String,
required: true
}
},
setup(props) {
const client = inject('guardhouse');
const user = ref(null);
const loading = ref(true);
const error = ref(null);
const fetchUser = async () => {
try {
loading.value = true;
user.value = await client.users.get(props.userId);
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
};
const updateUserName = async () => {
if (!user.value) return;
try {
user.value.name = 'Updated Name';
user.value = await client.users.update(user.value);
} catch (err) {
console.error('Failed to update user:', err);
}
};
onMounted(() => {
fetchUser();
});
return {
user,
loading,
error,
updateUserName
};
}
};
</script>
Node.js Express Integration
Middleware
const express = require('express');
const { GuardhouseClient } = require('@guardhouse/sdk');
const app = express();
const client = new GuardhouseClient({
clientId: process.env.GUARDHOUSE_CLIENT_ID,
clientSecret: process.env.GUARDHOUSE_CLIENT_SECRET,
domain: process.env.GUARDHOUSE_DOMAIN
});
// Middleware to authenticate requests
const authenticateToken = async (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
if (!token) {
return res.status(401).json({ error: 'Access token required' });
}
try {
// Verify token with Guardhouse
await client.users.getMe();
next();
} catch (error) {
return res.status(403).json({ error: 'Invalid token' });
}
};
// Routes
app.get('/api/users', authenticateToken, async (req, res) => {
try {
const users = await client.users.getAll({ page: 1, perPage: 50 });
res.json({ users: users.items, total: users.total });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.get('/api/users/:userId', authenticateToken, async (req, res) => {
try {
const user = await client.users.get(req.params.userId);
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.put('/api/users/:userId', authenticateToken, async (req, res) => {
try {
const user = await client.users.get(req.params.userId);
user.name = req.body.name;
user.email = req.body.email;
const updated = await client.users.update(user);
res.json(updated);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
Best Practices
- Environment Variables: Store credentials in environment variables
- Error Handling: Always wrap API calls in try-catch
- Type Safety: Use TypeScript for better type checking
- Loading States: Show loading indicators during API calls
- Token Refresh: Implement automatic token refresh
- Rate Limiting: Respect rate limits and implement backoff
- Validation: Validate user input before API calls
- Security: Never expose client secrets in browser code
Environment Variables
# .env file
GUARDHOUSE_CLIENT_ID=your_client_id
GUARDHOUSE_CLIENT_SECRET=your_client_secret
GUARDHOUSE_DOMAIN=your-tenant.guardhouse.cloud
import dotenv from 'dotenv';
dotenv.config();
const client = new GuardhouseClient({
clientId: process.env.GUARDHOUSE_CLIENT_ID,
clientSecret: process.env.GUARDHOUSE_CLIENT_SECRET,
domain: process.env.GUARDHOUSE_DOMAIN
});
Status
The JavaScript SDK is currently in development and coming soon.