Skip to main content

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

  1. Environment Variables: Store credentials in environment variables
  2. Error Handling: Always wrap API calls in try-catch
  3. Type Safety: Use TypeScript for better type checking
  4. Loading States: Show loading indicators during API calls
  5. Token Refresh: Implement automatic token refresh
  6. Rate Limiting: Respect rate limits and implement backoff
  7. Validation: Validate user input before API calls
  8. 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.