feat(docs): add package READMEs and publish metadata; update web package publish order
This commit is contained in:
@@ -0,0 +1,372 @@
|
||||
# @idp.global/idpclient
|
||||
|
||||
A TypeScript client library for integrating with the idp.global Identity Provider. Works in both browser and Node.js environments.
|
||||
|
||||
## Overview
|
||||
|
||||
The IdpClient provides a complete API for authentication, session management, and organization operations. It uses WebSocket connections via TypedSocket for real-time, type-safe communication with the IdP server.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @idp.global/idpclient
|
||||
# or
|
||||
pnpm add @idp.global/idpclient
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
import { IdpClient } from '@idp.global/idpclient';
|
||||
|
||||
// Initialize the client
|
||||
const idpClient = new IdpClient('https://idp.global');
|
||||
|
||||
// Enable WebSocket connection
|
||||
await idpClient.enableTypedSocket();
|
||||
|
||||
// Check login status
|
||||
const isLoggedIn = await idpClient.determineLoginStatus();
|
||||
|
||||
if (isLoggedIn) {
|
||||
const userInfo = await idpClient.whoIs();
|
||||
console.log('Logged in as:', userInfo.user.data.name);
|
||||
}
|
||||
```
|
||||
|
||||
## Core Features
|
||||
|
||||
### Authentication
|
||||
|
||||
#### Password Login
|
||||
|
||||
```typescript
|
||||
const response = await idpClient.requests.loginWithUserNameAndPassword.fire({
|
||||
username: 'user@example.com',
|
||||
password: 'securepassword',
|
||||
});
|
||||
|
||||
if (response.refreshToken) {
|
||||
await idpClient.refreshJwt(response.refreshToken);
|
||||
console.log('Login successful!');
|
||||
} else if (response.twoFaNeeded) {
|
||||
console.log('2FA verification required');
|
||||
}
|
||||
```
|
||||
|
||||
#### Magic Link Login
|
||||
|
||||
```typescript
|
||||
// Request magic link
|
||||
await idpClient.requests.loginWithEmail.fire({
|
||||
email: 'user@example.com',
|
||||
});
|
||||
|
||||
// After clicking the email link
|
||||
const result = await idpClient.requests.loginWithEmailAfterToken.fire({
|
||||
email: 'user@example.com',
|
||||
token: 'token-from-email-link',
|
||||
});
|
||||
|
||||
if (result.refreshToken) {
|
||||
await idpClient.refreshJwt(result.refreshToken);
|
||||
}
|
||||
```
|
||||
|
||||
#### API Token Login
|
||||
|
||||
```typescript
|
||||
const result = await idpClient.requests.loginWithApiToken.fire({
|
||||
apiToken: 'your-api-token',
|
||||
});
|
||||
|
||||
if (result.jwt) {
|
||||
await idpClient.setJwt(result.jwt);
|
||||
}
|
||||
```
|
||||
|
||||
### Session Management
|
||||
|
||||
```typescript
|
||||
// Get current JWT
|
||||
const jwt = await idpClient.getJwt();
|
||||
|
||||
// Get parsed JWT data
|
||||
const jwtData = await idpClient.getJwtData();
|
||||
console.log('User ID:', jwtData.id);
|
||||
|
||||
// Refresh JWT (automatic housekeeping)
|
||||
await idpClient.performJwtHousekeeping();
|
||||
|
||||
// Manual refresh
|
||||
await idpClient.refreshJwt();
|
||||
|
||||
// Logout
|
||||
await idpClient.logout();
|
||||
```
|
||||
|
||||
### User Information
|
||||
|
||||
```typescript
|
||||
// Get current user details
|
||||
const whoIsResponse = await idpClient.whoIs();
|
||||
console.log('Name:', whoIsResponse.user.data.name);
|
||||
console.log('Email:', whoIsResponse.user.data.email);
|
||||
|
||||
// Get user data
|
||||
const userData = await idpClient.requests.getUserData.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
userId: jwtData.id,
|
||||
});
|
||||
|
||||
// Update user data
|
||||
await idpClient.requests.setUserData.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
userId: jwtData.id,
|
||||
name: 'New Name',
|
||||
});
|
||||
```
|
||||
|
||||
### Organization Management
|
||||
|
||||
```typescript
|
||||
// Get user's organizations and roles
|
||||
const orgsAndRoles = await idpClient.getRolesAndOrganizations();
|
||||
console.log('Organizations:', orgsAndRoles.organizations);
|
||||
console.log('Roles:', orgsAndRoles.roles);
|
||||
|
||||
// Create a new organization
|
||||
const result = await idpClient.createOrganization(
|
||||
'My Company', // name
|
||||
'my-company', // slug
|
||||
'manifest' // mode: 'checkAvailability' or 'manifest'
|
||||
);
|
||||
|
||||
if (result.resultingOrganization) {
|
||||
console.log('Created:', result.resultingOrganization.id);
|
||||
}
|
||||
|
||||
// Get organization details
|
||||
const orgDetails = await idpClient.requests.getOrganizationById.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
organizationId: 'org-id',
|
||||
});
|
||||
```
|
||||
|
||||
### Member & Invitation Management
|
||||
|
||||
```typescript
|
||||
// Get organization members
|
||||
const members = await idpClient.requests.getOrgMembers.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
organizationId: 'org-id',
|
||||
});
|
||||
|
||||
// Invite a new member
|
||||
await idpClient.requests.createInvitation.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
organizationId: 'org-id',
|
||||
email: 'newmember@example.com',
|
||||
roles: ['member'],
|
||||
});
|
||||
|
||||
// Bulk invite members
|
||||
await idpClient.requests.bulkCreateInvitations.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
organizationId: 'org-id',
|
||||
invitations: [
|
||||
{ email: 'user1@example.com', roles: ['member'] },
|
||||
{ email: 'user2@example.com', roles: ['admin'] },
|
||||
],
|
||||
});
|
||||
|
||||
// Accept an invitation
|
||||
await idpClient.requests.acceptInvitation.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
invitationToken: 'token-from-invite-email',
|
||||
});
|
||||
|
||||
// Remove a member
|
||||
await idpClient.requests.removeMember.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
organizationId: 'org-id',
|
||||
userId: 'user-id',
|
||||
});
|
||||
|
||||
// Transfer ownership
|
||||
await idpClient.requests.transferOwnership.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
organizationId: 'org-id',
|
||||
newOwnerId: 'new-owner-user-id',
|
||||
});
|
||||
```
|
||||
|
||||
### Password Management
|
||||
|
||||
```typescript
|
||||
// Request password reset
|
||||
await idpClient.requests.resetPassword.fire({
|
||||
email: 'user@example.com',
|
||||
});
|
||||
|
||||
// Set new password (with token from email)
|
||||
await idpClient.requests.setNewPassword.fire({
|
||||
email: 'user@example.com',
|
||||
tokenArg: 'reset-token',
|
||||
newPassword: 'newsecurepassword',
|
||||
});
|
||||
|
||||
// Change password (when logged in)
|
||||
await idpClient.requests.setNewPassword.fire({
|
||||
email: 'user@example.com',
|
||||
oldPassword: 'currentpassword',
|
||||
newPassword: 'newsecurepassword',
|
||||
});
|
||||
```
|
||||
|
||||
### Session & Device Management
|
||||
|
||||
```typescript
|
||||
// Get active sessions
|
||||
const sessions = await idpClient.requests.getUserSessions.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
userId: jwtData.id,
|
||||
});
|
||||
|
||||
// Revoke a session
|
||||
await idpClient.requests.revokeSession.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
sessionId: 'session-id',
|
||||
});
|
||||
|
||||
// Get device ID
|
||||
const deviceInfo = await idpClient.requests.obtainDeviceId.fire({});
|
||||
|
||||
// Attach device to session
|
||||
await idpClient.requests.attachDeviceId.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
deviceId: deviceInfo.deviceId.id,
|
||||
});
|
||||
```
|
||||
|
||||
### Cross-Domain Authentication
|
||||
|
||||
```typescript
|
||||
// Get transfer token for SSO between apps
|
||||
const transferToken = await idpClient.getTransferToken();
|
||||
|
||||
// Switch to another app with authentication
|
||||
await idpClient.getTransferTokenAndSwitchToLocation('https://app.example.com/');
|
||||
|
||||
// Process incoming transfer token (in target app)
|
||||
const success = await idpClient.processTransferToken();
|
||||
if (success) {
|
||||
console.log('Cross-domain login successful');
|
||||
}
|
||||
```
|
||||
|
||||
### Billing Integration
|
||||
|
||||
```typescript
|
||||
// Get billing plan for an organization
|
||||
const billingPlan = await idpClient.requests.getBillingPlan.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
organizationId: 'org-id',
|
||||
});
|
||||
|
||||
// Get Paddle configuration
|
||||
const paddleConfig = await idpClient.requests.getPaddleConfig.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
});
|
||||
|
||||
// Update payment method
|
||||
await idpClient.updatePaddleCheckoutId('org-id', 'checkout-id');
|
||||
```
|
||||
|
||||
### Admin Operations (Global Admins Only)
|
||||
|
||||
```typescript
|
||||
// Check if user is global admin
|
||||
const isAdmin = await idpClient.requests.checkGlobalAdmin.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
});
|
||||
|
||||
// Get platform statistics
|
||||
const stats = await idpClient.requests.getGlobalAppStats.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
});
|
||||
|
||||
// Create a global app
|
||||
await idpClient.requests.createGlobalApp.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
name: 'My App',
|
||||
description: 'App description',
|
||||
});
|
||||
|
||||
// Suspend a user
|
||||
await idpClient.requests.suspendUser.fire({
|
||||
jwt: await idpClient.getJwt(),
|
||||
userId: 'user-id',
|
||||
});
|
||||
```
|
||||
|
||||
## Reactive Subscriptions
|
||||
|
||||
The client provides RxJS subjects for reactive updates:
|
||||
|
||||
```typescript
|
||||
// Subscribe to login status changes
|
||||
idpClient.statusObservable.subscribe((status) => {
|
||||
console.log('Login status changed:', status);
|
||||
});
|
||||
|
||||
// Subscribe to roles updates
|
||||
idpClient.rolesReplaySubject.subscribe((roles) => {
|
||||
console.log('Roles updated:', roles);
|
||||
});
|
||||
|
||||
// Subscribe to organizations updates
|
||||
idpClient.organizationsReplaySubject.subscribe((orgs) => {
|
||||
console.log('Organizations updated:', orgs);
|
||||
});
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### IdpClient Class
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `enableTypedSocket()` | Initialize WebSocket connection |
|
||||
| `determineLoginStatus(requireLogin?)` | Check if user is logged in |
|
||||
| `getJwt()` | Get stored JWT string |
|
||||
| `getJwtData()` | Get parsed JWT data |
|
||||
| `setJwt(jwt)` | Store JWT |
|
||||
| `deleteJwt()` | Remove stored JWT |
|
||||
| `refreshJwt(refreshToken?)` | Refresh the JWT |
|
||||
| `performJwtHousekeeping()` | Auto-refresh JWT if needed |
|
||||
| `logout()` | End session and redirect |
|
||||
| `whoIs()` | Get current user info |
|
||||
| `getRolesAndOrganizations()` | Get user's orgs and roles |
|
||||
| `createOrganization(name, slug, mode)` | Create new organization |
|
||||
| `getTransferToken(appData?)` | Get SSO transfer token |
|
||||
| `processTransferToken()` | Process incoming transfer token |
|
||||
| `stop()` | Close WebSocket connection |
|
||||
|
||||
### IdpRequests Class
|
||||
|
||||
Access via `idpClient.requests.*`:
|
||||
|
||||
**Authentication**: `loginWithUserNameAndPassword`, `loginWithEmail`, `loginWithEmailAfterToken`, `loginWithApiToken`, `resetPassword`, `setNewPassword`
|
||||
|
||||
**User**: `getUserData`, `setUserData`, `getUserSessions`, `revokeSession`, `getUserActivity`
|
||||
|
||||
**Organization**: `getOrganizationById`, `updateOrganization`, `createInvitation`, `bulkCreateInvitations`, `getOrgMembers`, `getOrgInvitations`, `acceptInvitation`, `cancelInvitation`, `resendInvitation`, `removeMember`, `updateMemberRoles`, `transferOwnership`
|
||||
|
||||
**Billing**: `getBillingPlan`, `getPaddleConfig`
|
||||
|
||||
**Admin**: `checkGlobalAdmin`, `getGlobalAppStats`, `createGlobalApp`, `updateGlobalApp`, `deleteGlobalApp`, `suspendUser`, `deleteSuspendedUser`
|
||||
|
||||
## License
|
||||
|
||||
MIT - See the main repository for full license details.
|
||||
Reference in New Issue
Block a user