TypeScript SDK
Paket NPM @arsaka/puguh-sdk menyediakan client TypeScript bertipe penuh untuk mengintegrasikan layanan infrastruktur ARSAKA PUGUH ke aplikasi frontend dan Node.js Anda. SDK ini dilengkapi 6 modul yang mencakup autentikasi, organisasi, IAM, audit/control, aplikasi, dan webhooks.
Instalasi
npm install @arsaka/puguh-sdk
# or
bun add @arsaka/puguh-sdk Mulai Cepat
import { AuthClient, OrganizationClient, IAMClient } from '@arsaka/puguh-sdk';
const auth = new AuthClient({ baseUrl: 'https://api-puguh.arsaka.io' });
// Login
const { access_token } = await auth.login({
email: 'user@example.com',
password: 'password',
});
// Use authenticated clients
const orgs = new OrganizationClient({
baseUrl: 'https://api-puguh.arsaka.io',
accessToken: access_token,
});
const orgList = await orgs.list();
// orgList = { items: OrganizationWithMembership[], total: number }
console.log(orgList.items[0].organization.name); Modul
SDK diorganisasi dalam 6 modul client, masing-masing memetakan ke layanan inti PUGUH. Import hanya client yang Anda butuhkan — setiap modul mendukung tree-shaking.
1. AuthClient
Menangani autentikasi pengguna, siklus hidup token, magic link, dan multi-factor authentication.
import { AuthClient } from '@arsaka/puguh-sdk';
const auth = new AuthClient({ baseUrl: 'https://api-puguh.arsaka.io' });
// Register a new user
await auth.register({ email: 'new@example.com', password: 'securePass123' });
// Login and receive tokens
const { access_token, refresh_token } = await auth.login({
email: 'new@example.com',
password: 'securePass123',
});
// Refresh an expired access token
const { access_token: newToken } = await auth.refreshToken({ refresh_token });
// Magic link authentication
await auth.requestMagicLink({ email: 'user@example.com' });
const session = await auth.verifyMagicLink({ token: 'magic-link-token' });
// Multi-factor authentication
const { secret, qr_code_url } = await auth.setupMFA({ type: 'totp' });
await auth.confirmMFA({ code: '123456' }); Metode: login, register, refreshToken, requestMagicLink, verifyMagicLink, setupMFA, confirmMFA
2. OrganizationClient
Kelola organisasi, keanggotaan, dan undangan. PUGUH menggunakan model organisasi bergaya GitHub di mana setiap pengguna memiliki workspace personal ditambah organisasi tim.
import { OrganizationClient } from '@arsaka/puguh-sdk';
const orgs = new OrganizationClient({
baseUrl: 'https://api-puguh.arsaka.io',
accessToken: access_token,
});
// List organizations the user belongs to
// Returns { items: OrganizationWithMembership[], total: number }
const orgList = await orgs.list();
console.log(orgList.items, orgList.total);
// Create a new team organization
const org = await orgs.create({ name: 'Acme Corp', slug: 'acme-corp' });
// Get organization details
const details = await orgs.get(org.organization.organizationId);
// Update organization settings
await orgs.update(org.organization.organizationId, { name: 'Acme Corporation' });
// Member management
const members = await orgs.listMembers(org.organization.organizationId);
await orgs.inviteMember(org.organization.organizationId, {
email: 'colleague@example.com', role: 'member',
});
await orgs.removeMember(org.organization.organizationId, memberId);
// Delete organization
await orgs.delete(org.organization.organizationId); Metode: list, get, create, update, delete, listMembers, inviteMember, removeMember
3. IAMClient
Identity and Access Management — kelola pengguna, role, dan penugasan role di organisasi Anda.
import { IAMClient } from '@arsaka/puguh-sdk';
const iam = new IAMClient({
baseUrl: 'https://api-puguh.arsaka.io',
accessToken: access_token,
organizationId: 'org-uuid',
});
// List users in the organization
// Returns { items: IamUser[], total, page, pageSize, hasNext, hasPrev }
const users = await iam.listUsers();
console.log(users.items, users.total);
// Get a specific user
const user = await iam.getUser(userId);
// Get user stats
const stats = await iam.getUserStats();
console.log(stats.total, stats.active);
// Role management
const roles = await iam.listRoles();
const customRole = await iam.createRole({
name: 'billing_admin',
description: 'Can manage billing',
permissions: ['billing.invoices.read', 'billing.invoices.create'],
});
await iam.assignRole(userId, customRole.roleId);
// Permission matrix (roles x permissions)
const matrix = await iam.getPermissionMatrix();
console.log(matrix.roles, matrix.permissions); // permissions is string[] Metode: listUsers, getUserStats, getUser, getUserRoles, listRoles, getRole, getRolePermissions, createRole, updateRole, deleteRole, assignRole, revokeRole, listServiceAccounts, listPermissions, getPermissionMatrix
4. ControlClient
Akses audit trail, event log, dead-letter queue, dan metrik platform. Semua path berada di bawah /control.
import { ControlClient } from '@arsaka/puguh-sdk';
const control = new ControlClient({
baseUrl: 'https://api-puguh.arsaka.io',
accessToken: access_token,
organizationId: 'org-uuid',
});
// Audit logs — who did what, when
// Returns { items: AuditRecord[], total, page, limit, pages }
const audit = await control.listAudit({
resourceType: 'user',
limit: 50,
});
// Single audit record
const record = await control.getAudit(auditId);
// Event stream
// Returns { items: SystemEvent[], total, page, limit, pages }
const events = await control.listEvents({ limit: 50 });
// Dead-letter queue — failed event deliveries
// DLQ items have totalAttempts (not retryCount)
const dlq = await control.listDLQ();
// Metrics trends (7d, 30d, or 90d)
const trends = await control.getMetricsTrends('30d'); Metode: listAudit, getAudit, listEvents, getEvent, listDLQ, getDLQ, retryDLQ, getMetricsTrends
5. ApplicationClient
Kelola aplikasi dalam organisasi. Setiap organisasi dapat memiliki beberapa aplikasi dengan daftar anggota masing-masing.
import { ApplicationClient } from '@arsaka/puguh-sdk';
const apps = new ApplicationClient({
baseUrl: 'https://api-puguh.arsaka.io',
accessToken: access_token,
organizationId: 'org-uuid',
});
// List all applications
// Returns { applications: Application[], total, limit, offset }
const appList = await apps.list();
// Create a new application
const app = await apps.create({ name: 'MANTRA Dashboard', slug: 'mantra' });
// Get application details
const appDetails = await apps.get(app.id);
// Update application
await apps.update(app.id, { name: 'MANTRA Production' });
// Manage application members
const appMembers = await apps.listMembers(app.id);
// Delete application
await apps.delete(app.id); Metode: list, get, create, update, delete, listMembers
6. WebhookClient
Konfigurasi webhook endpoint dan kelola pengiriman event. Gunakan webhooks untuk menerima notifikasi real-time saat event terjadi di organisasi Anda.
import { WebhookClient } from '@arsaka/puguh-sdk';
const webhooks = new WebhookClient({
baseUrl: 'https://api-puguh.arsaka.io',
accessToken: access_token,
organizationId: 'org-uuid',
});
// List registered webhooks
// Returns { items: Webhook[], total, page, limit, pages }
const list = await webhooks.list();
// Create a new webhook (secret only returned on create)
const webhook = await webhooks.create({
url: 'https://example.com/webhooks/puguh',
eventTypes: ['user.registered', 'organization.created'],
description: 'My webhook endpoint',
});
console.log(webhook.secret); // Save this — not returned again
// Get a webhook (no secret in response)
const wh = await webhooks.get(webhook.id);
// Update webhook
await webhooks.update(webhook.id, {
description: 'Updated description',
isActive: false,
});
// List recent deliveries for a webhook
const deliveries = await webhooks.listDeliveries(webhook.id);
// Test webhook (sends ping)
const testResult = await webhooks.test(webhook.id);
console.log(testResult.deliveryId, testResult.status);
// Delete webhook
await webhooks.delete(webhook.id); Metode: create, list, get, update, delete, listDeliveries, test
Tipe TypeScript
SDK mengekspor definisi tipe lengkap untuk semua entitas API. Gunakan untuk mengetik kode aplikasi Anda:
import type {
OrganizationListResponse,
OrganizationWithMembership,
IamUser,
AuditRecord,
LoginResponse,
PuguhError,
} from '@arsaka/puguh-sdk';
// Type your handlers
function handleOrg(item: OrganizationWithMembership): void {
console.log(item.organization.name, item.role);
}
// Organization list is paginated
function showOrgs(response: OrganizationListResponse): void {
console.log(response.items); // OrganizationWithMembership[]
console.log(response.total); // number
} Penanganan Error
Semua metode client melempar PuguhError pada response non-2xx. Error menyertakan kode status HTTP, pesan yang mudah dibaca, dan detail opsional.
import { PuguhError } from '@arsaka/puguh-sdk';
try {
const orgs = await client.list();
} catch (error) {
if (error instanceof PuguhError) {
console.error(error.statusCode); // HTTP status code (e.g. 401, 403, 404)
console.error(error.message); // Human-readable error message
console.error(error.errorCode); // Error code string (e.g. 'UNAUTHORIZED')
console.error(error.details); // Optional additional error details
}
} Opsi Konfigurasi
Semua konstruktor client menerima objek konfigurasi yang sama:
| Opsi | Tipe | Wajib | Deskripsi |
|---|---|---|---|
baseUrl | string | Ya | URL API PUGUH (contoh https://api-puguh.arsaka.io) |
accessToken | string | Tidak* | JWT access token dari AuthClient.login(). Wajib untuk semua client kecuali AuthClient. |
apiKey | string | Tidak | API key untuk autentikasi server-to-server (alternatif dari accessToken) |
organizationId | string | Tidak | UUID organisasi default untuk operasi berskala |
applicationId | string | Tidak | UUID aplikasi default untuk operasi berskala |
timeout | number | Tidak | Timeout request dalam milidetik (default: 30000) |
Catatan
AuthClient tidak memerlukan accessToken karena digunakan untuk mendapatkan token. Semua client lain memerlukan accessToken atau apiKey untuk autentikasi.
Environment Variables
Setup .env yang direkomendasikan untuk penggunaan server-side:
PUGUH_BASE_URL=https://api-puguh.arsaka.io
PUGUH_API_KEY=pk_live_your_api_key
PUGUH_ORGANIZATION_ID=your-org-uuid
PUGUH_APPLICATION_ID=your-app-uuid import { OrganizationClient } from '@arsaka/puguh-sdk';
const client = new OrganizationClient({
baseUrl: process.env.PUGUH_BASE_URL!,
apiKey: process.env.PUGUH_API_KEY!,
organizationId: process.env.PUGUH_ORGANIZATION_ID!,
}); Praktik Terbaik
1. Jangan Pernah Hardcode Kredensial
// Bad
const auth = new AuthClient({ baseUrl: 'https://api-puguh.arsaka.io' });
const { access_token } = await auth.login({
email: 'admin@arsaka.dev',
password: 'hardcoded-password', // Never do this
});
// Good — use environment variables
const { access_token } = await auth.login({
email: process.env.PUGUH_EMAIL!,
password: process.env.PUGUH_PASSWORD!,
}); 2. Gunakan Ulang Instance Client
Buat instance client sekali dan gunakan ulang. Setiap instance mempertahankan konfigurasi dan status autentikasinya.
// Create once at application startup
const orgs = new OrganizationClient({
baseUrl: process.env.PUGUH_BASE_URL!,
accessToken: access_token,
});
// Reuse across your application
export { orgs }; 3. Tangani Refresh Token
Access token kedaluwarsa. Gunakan refreshToken untuk mendapatkan access token baru tanpa meminta pengguna login ulang.
import { AuthClient, PuguhError } from '@arsaka/puguh-sdk';
async function withTokenRefresh<T>(
fn: () => Promise<T>,
auth: AuthClient,
refreshToken: string,
): Promise<T> {
try {
return await fn();
} catch (error) {
if (error instanceof PuguhError && error.statusCode === 401) {
const { access_token } = await auth.refreshToken({
refresh_token: refreshToken,
});
// Update client token and retry
client.accessToken = access_token;
return await fn();
}
throw error;
}
} 4. Gunakan Penanganan Error yang Tepat
import { PuguhError } from '@arsaka/puguh-sdk';
try {
const org = await orgs.get(orgId);
} catch (error) {
if (error instanceof PuguhError) {
switch (error.statusCode) {
case 401:
// Token expired — refresh and retry
break;
case 403:
// Insufficient permissions
break;
case 404:
// Organization not found
break;
case 429:
// Rate limited — back off and retry
break;
default:
// Unexpected error
throw error;
}
}
}