Comprehensive TypeScript SDK for the Star Wars Combine API v2.0
Features • Installation • Quick Start • Documentation • Examples
npm install swcombine-sdk
# or
yarn add swcombine-sdk
# or
pnpm add swcombine-sdk
import { SWCombine } from 'swcombine-sdk';
// Public mode (no auth)
const publicClient = new SWCombine();
// Token-only mode (use an existing token)
const tokenClient = new SWCombine({
token: process.env.SWC_ACCESS_TOKEN!,
});
// Full OAuth mode (required for OAuth flows and token refresh)
const fullClient = new SWCombine({
clientId: process.env.SWC_CLIENT_ID!,
clientSecret: process.env.SWC_CLIENT_SECRET!,
token: process.env.SWC_ACCESS_TOKEN, // Optional - string or OAuthToken object
redirectUri: 'http://localhost:3000/callback',
accessType: 'offline',
});
// Get public character information (no auth required)
const character = await publicClient.character.getByHandle({
handle: 'character-handle',
});
console.log(character.uid); // "1:12345"
console.log(character.name); // "Character Name"
// For authenticated endpoints, provide an access token
const authenticatedClient = new SWCombine({
token: process.env.SWC_ACCESS_TOKEN!,
});
// Get character details
const character = await authenticatedClient.character.get({
uid: '1:12345',
});
// Get character messages
const messages = await authenticatedClient.character.messages.list({
uid: '1:12345',
mode: 'received',
});
// List returns metadata items (MessageListItem[])
const firstMessageId = messages[0]?.attributes.uid;
if (firstMessageId) {
const fullMessage = await authenticatedClient.character.messages.get({
uid: '1:12345',
messageId: firstMessageId,
});
console.log(fullMessage.communication);
}
// Send a message
// IMPORTANT: use receiver handle(s), not UID(s), for `receivers`
await authenticatedClient.character.messages.create({
uid: '1:12345',
receivers: 'recipient_handle',
communication: 'Test message',
});
// Get faction information
const faction = await authenticatedClient.faction.get({
uid: '20:123',
});
Use the included helper script to get an access token:
# 1. Add your credentials to .env
echo "SWC_CLIENT_ID=your_client_id" >> .env
echo "SWC_CLIENT_SECRET=your_client_secret" >> .env
# 2. Run the OAuth helper
npm run get-token
# 3. Visit http://localhost:3000 in your browser
# 4. Authorize the app and copy the token to .env
OAuth-only methods require full OAuth mode (clientId + clientSecret):
client.auth.getAuthorizationUrl(...)client.auth.handleCallback(...)client.auth.revokeToken(...)client.refreshToken()import { SWCombine, CharacterScopes, MessageScopes } from 'swcombine-sdk';
const client = new SWCombine({
clientId: 'your-client-id',
clientSecret: 'your-client-secret',
redirectUri: 'http://localhost:3000/callback',
accessType: 'offline', // Get refresh token
});
// 1. Generate authorization URL
const authUrl = client.auth.getAuthorizationUrl({
scopes: [
CharacterScopes.READ,
CharacterScopes.STATS,
MessageScopes.READ,
MessageScopes.SEND,
],
state: 'random-csrf-token',
});
// 2. Redirect user to authUrl...
// 3. Handle callback
const result = await client.auth.handleCallback(req.query);
if (result.success) {
const token = result.token!;
console.log('Access Token:', token.accessToken);
console.log('Refresh Token:', token.refreshToken);
}
import {
CharacterScopes,
MessageScopes,
Scopes,
getAllScopes,
getReadOnlyScopes,
} from 'swcombine-sdk';
// Use constants with autocomplete
const scopes = [
CharacterScopes.READ, // TypeScript suggests all scopes
CharacterScopes.STATS,
MessageScopes.SEND,
Scopes.PersonalInventory.SHIPS.READ,
];
// Or use helpers
const readOnly = getReadOnlyScopes();
const everything = getAllScopes();
See OAuth Scopes Guide for all 170+ available scopes.
The SDK provides access to all SW Combine API v2.0 resources through a fluent, type-safe interface:
| Resource | Access | Description |
|---|---|---|
client.api |
Utilities | Hello world, permissions, rate limits, time conversion |
client.character |
Characters | Profile, messages, skills, privileges, credits, credit log |
client.faction |
Factions | Info, members, budgets, stockholders, credits, credit log |
client.galaxy |
Galaxy | Systems, sectors, planets, stations, cities |
client.inventory |
Inventory | Entity listing, management, tagging |
client.market |
Market | Vendor listings |
client.news |
News | GNS and Sim News feeds |
client.types |
Types | Entity types, classes, and detailed type info |
client.events |
Events | Personal, faction, inventory, and combat events |
client.location |
Location | Entity location lookups |
client.datacard |
Datacards | Datacard management and assignment |
Also includes a Timestamp utility for Combine Galactic Time (CGT) conversion and formatting.
For complete method signatures, parameters, and examples, see the API Reference Documentation.
The SW Combine API has a rate limit of 600 requests per hour. The SDK provides tools to monitor and handle rate limits:
// Check current rate limit status after any API call
const rateLimit = client.getRateLimitInfo();
if (rateLimit) {
console.log(`${rateLimit.remaining}/${rateLimit.limit} requests remaining`);
console.log(`Resets at: ${rateLimit.resetTime}`);
}
// Set up a callback to monitor rate limits in real-time
client.onRateLimitUpdate((info) => {
if (info.remaining < 100) {
console.warn(`Warning: Only ${info.remaining} API requests remaining!`);
}
});
// Or check via API endpoint for detailed per-endpoint limits
const limits = await client.api.rateLimits();
The SDK automatically handles rate limit errors with exponential backoff and respects the Retry-After header when provided.
import { SWCError } from 'swcombine-sdk';
try {
const character = await client.character.get({ uid: '1:12345' });
} catch (error) {
if (error instanceof SWCError) {
console.error('Status:', error.statusCode); // 404
console.error('Message:', error.message); // "Resource not found"
console.error('Type:', error.type); // "not_found"
console.error('Retryable:', error.retryable); // false
}
}
Full TypeScript support with intelligent type inference:
import { Message, MessageListItem } from 'swcombine-sdk';
// Types are automatically inferred
const character = await client.character.get({ uid: '1:12345' });
// character: Character
// Request parameters are typed
const listedMessages = await client.character.messages.list({
uid: '1:12345',
mode: 'received', // Optional - TypeScript knows valid values: 'sent' | 'received'
// mode: 'invalid', // TypeScript error
});
const messageListItem: MessageListItem | undefined = listedMessages[0];
const messageId = messageListItem?.attributes.uid;
if (messageId) {
const messageDetail: Message = await client.character.messages.get({
uid: '1:12345',
messageId,
});
console.log(messageDetail.communication);
}
// Send message: receivers must be handle(s), not UID(s)
await client.character.messages.create({
uid: '1:12345',
receivers: 'recipient_handle_1;recipient_handle_2',
communication: 'Hello there',
});
interface ClientConfig {
// Optional OAuth credentials
// If provided, both must be set together
clientId?: string;
clientSecret?: string;
// Optional authentication - string or full OAuthToken object
token?: string | OAuthToken;
// Optional OAuth settings
redirectUri?: string;
accessType?: 'online' | 'offline';
// Optional HTTP settings
baseURL?: string; // Default: https://www.swcombine.com/ws/v2.0/
timeout?: number; // Default: 30000 (30 seconds)
maxRetries?: number; // Default: 3
retryDelay?: number; // Default: 1000ms
debug?: boolean; // Default: false
}
interface OAuthToken {
accessToken: string;
refreshToken?: string;
expiresAt: number; // Timestamp in milliseconds
}
See the examples directory for complete working examples:
import { SWCombine } from 'swcombine-sdk';
const client = new SWCombine();
// Get character info
const character = await client.character.getByHandle({
handle: 'character-name',
});
console.log(`${character.name} (${character.uid})`);
Interactive OAuth flow to obtain access tokens:
npm run get-token
Quickly get a character's UID from their handle:
npm run get-character-uid YourHandle
npm run test:integration
# Install dependencies
npm install
# Build
npm run build
# Run unit tests (fast, no API calls)
npm test
# Run unit tests in watch mode
npm run test:watch
# Run all integration tests (requires .env with API credentials)
npm run test:integration
# Run integration tests for a specific resource
npm run test:integration:character
npm run test:integration:galaxy
npm run test:integration:faction
# Also: test:integration:api, test:integration:market, test:integration:news,
# test:integration:types, test:integration:misc
# Lint
npm run lint
# Format code
npm run format
MIT © Dreks Selmur aka JonMarkGo
Contributions are welcome! Please: