npm package: @saasbase-io/loginflow-websdk
Description: Loginflow WebSDK for browser-based SPA applications
Latest version: 1.10.4

# Loginflow WebSDK

A TypeScript SDK for browser-based SPA applications to integrate with Loginflow authentication APIs. Features automatic flow management, state persistence, and token refresh.

## Features

- 🚀 **Automatic Flow Management**: Detects signin/signup flows from URL paths
- 💾 **State Persistence**: Resumes authentication flows after page refresh
- 🔄 **Token Refresh**: Background token refresh at 80% of token lifetime
- 🍪 **Session Management**: Cookie-based sessions with automatic handling
- 📦 **Multiple Build Formats**: UMD, ESM for flexible integration
- 🔒 **TypeScript Support**: Full type definitions included
- ⚡ **Simple API**: Single initialization method with automatic flow setup

## Installation

```bash
npm install @saasbase-io/loginflow-websdk
```

Or include directly via CDN:

```html
<script src="https://unpkg.com/@saasbase-io/loginflow-websdk/dist/loginflow-websdk.min.js"></script>
```

## Quick Start

### ES6 Modules

```typescript
import { LoginflowSDK } from '@saasbase-io/loginflow-websdk';

// Initialize SDK with automatic flow management
const response = await LoginflowSDK.init({
  apiUrl: 'https://api.example.com',
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  locale: 'en-US',
  // flowType: 'signin' // Optional: override auto-detection
});

// SDK is ready to use
const { sdk, flowType, isResumed } = response;

if (isResumed) {
  console.log('Resumed existing flow:', flowType);
} else {
  console.log('Started new flow:', flowType);
}

// Process authentication events
const eventResponse = await sdk.processEvent({
  event: 'signin',
  data: {
    username: 'user@example.com',
    password: 'password'
  }
});
```

### Browser (UMD)

```javascript
const response = await LoginflowSDK.LoginflowSDK.init({
  apiUrl: 'https://api.example.com',
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  locale: 'en-US'
});

const sdk = response.sdk;
```

### React Integration

```typescript
import { useEffect, useState } from 'react';
import { LoginflowSDK } from '@saasbase-io/loginflow-websdk';

function AuthFlow() {
  const [sdk, setSdk] = useState(null);
  const [flowState, setFlowState] = useState(null);

  useEffect(() => {
    const initSDK = async () => {
      try {
        const response = await LoginflowSDK.init({
          apiUrl: process.env.REACT_APP_API_URL,
          clientId: process.env.REACT_APP_CLIENT_ID,
          clientSecret: process.env.REACT_APP_CLIENT_SECRET,
          locale: 'en'
        });

        setSdk(response.sdk);
        setFlowState(response);
      } catch (error) {
        console.error('SDK init failed:', error);
      }
    };

    initSDK();
    return () => sdk?.cleanup();
  }, []);

  if (!flowState) return <div>Loading...</div>;

  return (
    <div>
      {flowState.isResumed && <p>Welcome back!</p>}
      {/* Render UI based on flowState.render_spec */}
    </div>
  );
}
```

## API Reference

### Static Initialization

```typescript
LoginflowSDK.init(config: LoginflowConfig): Promise<InitSDKResponse>
```

**Config Options:**
- `apiUrl` (string, required): Base URL of the Loginflow API
- `clientId` (string, required): Your application's client ID
- `clientSecret` (string, required): Your application's client secret
- `locale` (string, optional): Locale for the authentication flow (default: 'en')
- `flowType` ('signin' | 'signup', optional): Override automatic flow detection
- `apiKey` (string, optional): API key for authentication
- `timeout` (number, optional): Request timeout in milliseconds (default: 30000)
- `headers` (object, optional): Additional headers to include in all requests

**Response:**
```typescript
{
  sdk: LoginflowSDK;      // SDK instance ready to use
  flowType: FlowType;     // Detected or specified flow type
  isResumed: boolean;     // Whether an existing flow was resumed
  state: string;          // Current flow state
  render_spec?: any;      // UI rendering instructions
  auth_result?: AuthResult; // Authentication result (if completed)
  redirect_url?: string;  // Redirect URL (if applicable)
}
```

### Instance Methods

#### processEvent(request: ProcessEventRequest): Promise<ProcessEventResponse>

Processes events within an active authentication flow.

**Parameters:**
```typescript
{
  event: string;          // Event type (e.g., 'signin', 'signup', 'verify_otp', 'resume')
  data?: {                // Event-specific data
    [key: string]: any;
  }
}
```

**Response:**
```typescript
{
  state: string;          // Current flow state
  render_spec?: any;      // Updated UI rendering instructions
  auth_result?: AuthResult; // Authentication result (if completed)
  redirect_url?: string;  // Redirect URL for OAuth flows
}
```

#### startFlow(request: StartFlowRequest): Promise<StartFlowResponse>

Manually starts a new authentication flow (advanced usage).

**Note:** Most applications should use the automatic flow management via `init()`.

#### getCurrentSession(): AuthSession | null

Returns the current authenticated session with tokens.

```typescript
const session = sdk.getCurrentSession();
if (session) {
  console.log('Access token:', session.access_token);
  console.log('Expires at:', new Date(session.expires_at));
}
```

#### getAuthenticatedUser(): User | null

Returns the authenticated user information from the ID token.

```typescript
const user = sdk.getAuthenticatedUser();
if (user) {
  console.log('User email:', user.email);
  console.log('User name:', user.name);
}
```

#### isAuthenticated(): boolean

Checks if the user is currently authenticated.

```typescript
if (sdk.isAuthenticated()) {
  // User is logged in
}
```

#### cleanup(): void

Cleanup method to call when unmounting/destroying the SDK instance.

```typescript
// Clean up timers and pending operations
sdk.cleanup();
```

## Flow Management

The SDK automatically manages authentication flows with intelligent detection and persistence.

### Automatic Flow Detection

The SDK detects the flow type from the URL path:
- `/signin`, `/login` → Sign-in flow
- `/signup`, `/register` → Sign-up flow

### State Persistence

- **Separate Storage**: Sign-in and sign-up flows are stored separately
- **Automatic Resume**: Flows resume automatically after page refresh
- **30-Minute Expiry**: Flows expire after 30 minutes of inactivity
- **Completion Cleanup**: Flow states are cleared upon successful authentication

### Manual Flow Control

Override automatic detection when needed:

```typescript
const response = await LoginflowSDK.init({
  apiUrl: 'https://api.example.com',
  clientId: 'your-client-id',
  clientSecret: 'your-client-secret',
  locale: 'en',
  flowType: 'signup' // Force signup flow regardless of URL
});
```

## Token Management

### Automatic Token Refresh

The SDK automatically refreshes tokens in the background:
- Triggers at 80% of token lifetime
- Runs silently without user interruption
- Updates stored tokens automatically
- Schedules next refresh cycle

### Manual Token Management

```typescript
// Get current session with tokens
const session = sdk.getCurrentSession();

// Check token expiry
if (session && Date.now() >= session.expires_at) {
  console.log('Token expired');
}
```

## Error Handling

The SDK throws `LoginflowError` with structured error information:

```typescript
try {
  const response = await LoginflowSDK.init({ ... });
} catch (error) {
  if (error instanceof LoginflowError) {
    console.error('Error code:', error.code);
    console.error('Error message:', error.message);
    console.error('Error details:', error.details);
  }
}
```

Common error codes:
- `CONFIG_ERROR`: Invalid SDK configuration
- `VALIDATION_ERROR`: Invalid request parameters
- `FLOW_TYPE_ERROR`: Unable to determine flow type
- `NETWORK_ERROR`: Network connectivity issues
- `TIMEOUT`: Request timeout
- `API_ERROR`: Server-side error
- `START_FLOW_ERROR`: Failed to start flow
- `PROCESS_EVENT_ERROR`: Failed to process event

## Session Management

The SDK automatically handles session cookies. After successful authentication:
- Session maintained through browser cookies
- Uses `credentials: 'include'` for all API calls
- Tokens stored securely in localStorage
- Automatic cleanup on logout

## TypeScript Types

The SDK exports all necessary TypeScript types:

```typescript
import type {
  LoginflowConfig,
  InitSDKResponse,
  StartFlowRequest,
  StartFlowResponse,
  ProcessEventRequest,
  ProcessEventResponse,
  AuthSession,
  User,
  FlowType,
  FlowState
} from '@saasbase-io/loginflow-websdk';
```

## Development

### Setup

```bash
# Install dependencies
npm install

# Build the SDK
npm run build

# Run in development mode
npm run dev
```

### Running Examples

```bash
# Build the SDK first
npm run build

# Start the example server
npm run example

# Open in your browser:
# - Home: http://localhost:3001
# - Sign In: http://localhost:3001/signin
# - Sign Up: http://localhost:3001/signup
```

### Available Scripts

- `npm run build` - Build production bundles
- `npm run dev` - Build and watch for changes
- `npm run lint` - Run ESLint
- `npm run typecheck` - Check TypeScript types
- `npm run example` - Start example server on port 3001
- `npm test` - Run tests (when implemented)

### Project Structure

```
loginflow-websdk/
├── src/
│   ├── index.ts           # Main exports
│   ├── loginflow-sdk.ts   # SDK implementation
│   ├── http-client.ts     # HTTP client wrapper
│   └── types.ts           # TypeScript definitions
├── example/
│   ├── signin.html        # Sign-in flow example
│   ├── signup.html        # Sign-up flow example
│   └── server.js          # Example HTTP server
├── dist/                  # Built files
│   ├── loginflow-websdk.js     # UMD bundle
│   ├── loginflow-websdk.min.js # Minified UMD
│   └── index.esm.js      # ES module
└── types/                 # Generated TypeScript declarations
```

## Browser Support

The SDK supports all modern browsers with ES2015+ support:
- Chrome 51+
- Firefox 54+
- Safari 10+
- Edge 15+

## Migration Guide

### From v1.0 to v1.1+

The main change is moving from a two-step initialization to a single async init:

**Before (v1.0):**
```typescript
const sdk = new LoginflowSDK({ apiUrl: '...' });
const flow = await sdk.initializeFlow({
  clientId: '...',
  clientSecret: '...'
});
```

**After (v1.1+):**
```typescript
const { sdk } = await LoginflowSDK.init({
  apiUrl: '...',
  clientId: '...',
  clientSecret: '...'
});
```

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

### Development Workflow

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

### Code Style

- Use TypeScript for all new code
- Follow existing code formatting
- Add tests for new features
- Update documentation as needed

## License

MIT

## Support

For issues and questions:
- GitHub Issues: [Report a bug](https://github.com/your-org/loginflow-websdk/issues)
- Documentation: [Full API docs](https://docs.example.com/loginflow-sdk)