spaps-sdk
Version:
Sweet Potato Authentication & Payment Service SDK - Zero-config client with built-in permission checking and role-based access control
439 lines (338 loc) • 11.2 kB
Markdown
---
id: spaps-typescript-sdk
title: spaps TypeScript SDK
category: sdk
tags:
- sdk
- typescript
- client
ai_summary: |
Reference for the spaps TypeScript SDK covering configuration, admin helpers,
and examples for interacting with authentication, payments, and permission
APIs from JavaScript or TypeScript applications.
last_updated: 2025-02-14
---
# @spaps/sdk
<a href="https://www.npmjs.com/package/spaps-sdk"><img alt="npm" src="https://img.shields.io/npm/v/spaps-sdk.svg"></a>
<img alt="node" src="https://img.shields.io/badge/node-%3E%3D14-brightgreen">
<img alt="types" src="https://img.shields.io/badge/types-TypeScript-blue">
> Sweet Potato Authentication & Payment Service SDK
Zero-config client for SPAPS authentication, payments, and permission checking. Works automatically with local development mode.
## 🔐 New in v1.1.0: Admin API Methods!
Built-in admin API methods for Stripe product management:
```typescript
import { SPAPSClient } from 'spaps-sdk';
const spaps = new SPAPSClient({
apiKey: 'your-api-key',
apiUrl: 'https://api.sweetpotato.dev'
});
// Authenticate as admin
await spaps.signIn('admin@example.com', 'password');
// Admin API methods
await spaps.admin.createProduct({
name: 'Premium Plan',
category: 'subscription',
description: 'Advanced features'
});
await spaps.admin.updateProduct('prod_123', {
name: 'Premium Plan Pro'
});
await spaps.admin.createPrice({
product_id: 'prod_123',
unit_amount: 2999,
currency: 'usd',
interval: 'month'
});
// Super admin operations
await spaps.admin.syncProducts();
```
## 🔐 Permission Utilities
Built-in permission checking and role-based access control:
```typescript
import { isAdminAccount, canAccessAdmin, getUserRole } from 'spaps-sdk';
// Check admin status
const isAdmin = isAdminAccount('buildooor@gmail.com'); // true
// Check admin access with detailed result
const adminCheck = canAccessAdmin(user);
if (adminCheck.allowed) {
// Show admin UI
}
// Get user role
const role = getUserRole('user@example.com'); // 'user' | 'admin' | 'guest'
// Check if authenticated user is admin
if (spaps.isAdmin(currentUser)) {
// Show admin features
}
```
See [PERMISSIONS.md](./PERMISSIONS.md) for React examples and complete documentation.
## Installation
```bash
npm install spaps-sdk
# or
yarn add spaps-sdk
# or
pnpm add spaps-sdk
```
### Compatibility
- ✅ **Node.js**: Fully supported (v14+) with automatic fetch polyfill
- ✅ **Browser**: Works in all modern browsers
- ✅ **TypeScript**: Full type definitions included
- ✅ **Next.js**: Server and client components supported
- ✅ **React Native**: Compatible with proper setup
The SDK automatically includes a `cross-fetch` polyfill for Node.js environments that don't have native fetch support.
## Quick Start
```javascript
import { SPAPSClient } from 'spaps-sdk';
// or
const { SPAPSClient } = require('spaps-sdk');
// Auto-detects local mode - no API key needed for localhost!
const spaps = new SPAPSClient({
apiUrl: 'http://localhost:3300' // Optional, auto-detected
});
// Login
const { data } = await spaps.login('user@example.com', 'password');
console.log('User:', data.user);
// Check authentication
if (spaps.isAuthenticated()) {
const user = await spaps.getUser();
console.log('Current user:', user.data);
}
```
## Local Mode Explained
- If `apiUrl` is omitted or points to `localhost`/`127.0.0.1`, the SDK runs in local mode.
- Local mode integrates seamlessly with the `spaps` CLI (`npx spaps local`), defaulting to `http://localhost:3300`.
- No API key is required in local mode; tokens and data are managed locally for development.
You can check the mode at runtime:
```ts
spaps.isLocalMode(); // true | false
```
## Environment Variables
The SDK can read configuration from environment variables (useful in Next.js and Node):
- `SPAPS_API_URL` or `NEXT_PUBLIC_SPAPS_API_URL` — API base URL
- `SPAPS_API_KEY` — API key for production use
Example (Node):
```bash
export SPAPS_API_URL=https://api.sweetpotato.dev
export SPAPS_API_KEY=spaps_xxx
```
Example (Next.js):
```env
NEXT_PUBLIC_SPAPS_API_URL=https://api.sweetpotato.dev
```
## Features
### 🚀 Zero Configuration
- **Auto-detects local mode** - No API key needed for localhost
- **Auto-refreshes tokens** - Handles expired tokens automatically
- **TypeScript support** - Full type definitions included
- **Crypto payments ready** - Create invoices, poll status, verify webhooks, trigger reconciliation
### 🔐 Authentication Methods
```javascript
// Email/Password
await spaps.login(email, password);
await spaps.register(email, password);
// Wallet Authentication
await spaps.walletSignIn(walletAddress, signature, message, 'solana');
// Token Management
await spaps.refresh();
await spaps.logout();
// Get User
const user = await spaps.getUser();
```
### 💳 Stripe Integration
```javascript
// Create checkout session
const session = await spaps.createCheckoutSession(priceId, successUrl);
window.location.href = session.data.url;
// Manage subscription
const subscription = await spaps.getSubscription();
await spaps.cancelSubscription();
```
### 📊 Usage Tracking
```javascript
// Check balance
const balance = await spaps.getUsageBalance();
console.log(`Credits: ${balance.data.balance}`);
// Record usage
await spaps.recordUsage('api-call', 1);
```
### ✉️ Secure Messaging
```javascript
// Create a secure message (content encrypted server-side when pii_enabled)
const message = await spaps.secureMessages.create({
patientId: '3d6f0a51-8d77-4b38-8248-2d1b2f1f6c7f',
practitionerId: 'a3d7f431-6c9d-4cbc-9f78-4e5b6a7c8d9e',
content: 'Patient is experiencing intermittent headaches.',
metadata: { urgency: 'high' }
});
// List secure messages for the current application
const messages = await spaps.secureMessages.list();
console.log(messages[0].content);
```
> Ensure your application has `settings.pii_enabled = true` so payloads are encrypted automatically.
```typescript
// Provide a strongly typed metadata shape for downstream usage
type SecureMessageMetadata = { urgency: 'low' | 'high'; tags?: string[] };
const spaps = new SPAPSClient<SecureMessageMetadata>({ apiKey: process.env.SPAPS_API_KEY });
await spaps.secureMessages.create({
patientId: '3d6f0a51-8d77-4b38-8248-2d1b2f1f6c7f',
practitionerId: 'a3d7f431-6c9d-4cbc-9f78-4e5b6a7c8d9e',
content: 'Follow up scheduled for next week.',
metadata: { urgency: 'low', tags: ['follow-up'] }
});
const typedMessages = await spaps.secureMessages.list();
typedMessages[0].metadata.urgency; // "low" | "high"
```
Need runtime validation too? Reuse the shared schemas that ship with the SDK:
```typescript
import { z } from 'zod';
import { createSecureMessageRequestSchema } from 'spaps-sdk';
const secureMessageRequestSchema = createSecureMessageRequestSchema(
z.object({ urgency: z.enum(['low', 'high']), tags: z.array(z.string()).optional() })
);
secureMessageRequestSchema.parse({
patientId: '3d6f0a51-8d77-4b38-8248-2d1b2f1f6c7f',
practitionerId: 'a3d7f431-6c9d-4cbc-9f78-4e5b6a7c8d9e',
content: 'All clear.',
metadata: { urgency: 'low' }
});
```
## Configuration
### Production Mode
```javascript
const spaps = new SPAPSClient({
apiUrl: 'https://api.sweetpotato.dev',
apiKey: 'spaps_your_api_key_here',
timeout: 10000 // Optional timeout in ms
});
```
### Local Development Mode (Auto-detected)
```javascript
const spaps = new SPAPSClient();
// Automatically uses http://localhost:3300 with no API key
```
### Environment Variables
```bash
# .env
SPAPS_API_URL=https://api.sweetpotato.dev
SPAPS_API_KEY=spaps_your_api_key_here
# Next.js
NEXT_PUBLIC_SPAPS_API_URL=https://api.sweetpotato.dev
```
## Helper Methods
```javascript
// Check if authenticated
spaps.isAuthenticated() // boolean
// Get current access token
spaps.getAccessToken() // string | undefined
// Set access token manually
spaps.setAccessToken(token)
// Check if in local mode
spaps.isLocalMode() // boolean
// Health check
await spaps.health()
```
## Types
The SDK ships with full TypeScript definitions. For most apps, import types directly from `spaps-sdk`:
```ts
import { SPAPSClient, type User, type Session, type Role } from 'spaps-sdk';
```
For advanced or library use cases, you can also import canonical types from the standalone package:
```ts
import type {
User,
Session,
Role,
Permission,
TokenPayload,
} from 'spaps-types';
```
Notes:
- `spaps-sdk` re-exports commonly used types for convenience.
- `spaps-types` is useful when building framework integrations, server middleware, or utilities that need to share types without depending on the SDK runtime.
## Import Styles
All these work:
```javascript
// ES6 Import
import { SPAPSClient } from 'spaps-sdk';
import SPAPSClient from 'spaps-sdk';
// CommonJS
const { SPAPSClient } = require('spaps-sdk');
const SPAPSClient = require('spaps-sdk');
// Alternative names
import { SPAPS } from 'spaps-sdk';
import { SweetPotatoSDK } from 'spaps-sdk';
```
## Admin API Methods
The SDK includes comprehensive admin methods for Stripe product management:
### Product Management
```typescript
// Create product (Admin required)
const product = await spaps.admin.createProduct({
name: 'Premium Plan',
category: 'subscription',
description: 'Advanced features for power users',
images: ['https://example.com/product-image.jpg'],
metadata: { feature_set: 'premium' },
active: true
});
// Update product (Admin required)
const updatedProduct = await spaps.admin.updateProduct('prod_123', {
name: 'Premium Plan Pro',
description: 'Updated features'
});
// Archive product (Admin required)
await spaps.admin.deleteProduct('prod_123');
// Get products (includes admin metadata if user is admin)
const { data } = await spaps.admin.getProducts();
if (data.adminMetadata) {
console.log('Total revenue:', data.adminMetadata.total_revenue);
}
```
### Price Management
```typescript
// Create price (Admin required)
const price = await spaps.admin.createPrice({
product_id: 'prod_123',
unit_amount: 2999, // $29.99
currency: 'usd',
interval: 'month',
interval_count: 1,
nickname: 'Monthly Premium'
});
```
### Super Admin Operations
```typescript
// Sync all products from Stripe (Super Admin required)
const syncResult = await spaps.admin.syncProducts();
console.log(`Synced ${syncResult.data.synced_count} products`);
```
### Permission Checking
```typescript
// Check if current user can access admin features
const user = await spaps.getCurrentUser();
if (spaps.isAdmin(user)) {
// Show admin UI components
console.log('User has admin privileges');
} else {
// Show regular user UI
console.log('Regular user');
}
```
## Error Handling
```javascript
try {
await spaps.admin.createProduct(productData);
} catch (error) {
if (error.response?.status === 401) {
console.error('Authentication required');
} else if (error.response?.status === 403) {
console.error('Admin privileges required');
} else if (error.response?.status === 429) {
console.error('Rate limited');
} else {
console.error('Error:', error.message);
}
}
```
## License
MIT