JSPM

@imperial-host/sdk

1.0.0
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1
  • Score
    100M100P100Q58001F
  • License MIT

Official TypeScript SDK for Imperial API

Package Exports

  • @imperial-host/sdk

Readme

@imperial/sdk

Official TypeScript SDK for the Imperial API. Upload and manage images and videos with zero egress fees.

npm version TypeScript License: MIT

Features

  • Full TypeScript support with complete type definitions
  • 🚀 Modern async/await API for clean, readable code
  • 📦 Batch uploads for efficient bulk operations
  • 🔄 Automatic retries with exponential backoff
  • 📊 Rate limit tracking with usage info
  • Zero dependencies (except form-data for Node.js)
  • 🌐 Works in Node.js and browsers

Installation

npm install @imperial/sdk
yarn add @imperial/sdk
pnpm add @imperial/sdk

Quick Start

import { ImperialClient } from '@imperial/sdk';

// Initialize client
const imperial = new ImperialClient({
  apiKey: 'imperial_live_xxxxxxxxxxxxx' // or imperial_upload_ for upload-only access
});

// Upload an image
const result = await imperial.upload({
  file: buffer, // Buffer, Blob, or File
  filename: 'cat.jpg',
  mimeType: 'image/jpeg'
});

console.log(`Uploaded: ${result.url}`);

Authentication

API Keys (Pro/Business)

Pro and Business tiers get full API keys with access to all endpoints:

const imperial = new ImperialClient({
  apiKey: 'imperial_live_xxxxxxxxxxxxx'
});

Upload Keys (Free/Starter)

Free and Starter tiers get upload-only keys:

const imperial = new ImperialClient({
  apiKey: 'imperial_upload_xxxxxxxxxxxxx'
});

// Can upload, but cannot list or delete
await imperial.upload({ ... }); // ✅ Works
await imperial.list(); // ❌ Requires Pro/Business

Get your keys from the Dashboard.

Usage Examples

Upload Single File

import fs from 'fs';
import { ImperialClient } from '@imperial/sdk';

const imperial = new ImperialClient({
  apiKey: process.env.IMPERIAL_API_KEY!
});

// From file
const buffer = fs.readFileSync('./image.jpg');
const result = await imperial.upload({
  file: buffer,
  filename: 'image.jpg',
  mimeType: 'image/jpeg'
});

console.log(result.url); // https://cdn.imperial.gay/uploads/...

Upload Multiple Files (Batch)

const files = [
  { file: buffer1, filename: 'cat.jpg', mimeType: 'image/jpeg' },
  { file: buffer2, filename: 'dog.jpg', mimeType: 'image/jpeg' },
  { file: buffer3, filename: 'bird.jpg', mimeType: 'image/jpeg' }
];

const result = await imperial.uploadBatch(files);

console.log(`Uploaded ${result.count} files`);
result.uploaded.forEach(file => {
  console.log(file.url);
});

if (result.errors) {
  console.error('Some uploads failed:', result.errors);
}

List Uploaded Media

// Get first page
const media = await imperial.list({
  page: 1,
  limit: 50
});

console.log(`Total: ${media.pagination.total}`);
console.log(`Page ${media.pagination.page} of ${media.pagination.totalPages}`);

media.images.forEach(item => {
  console.log(`${item.prompt} - ${item.url}`);
});

Get Specific Media

const item = await imperial.get('67d8f9a1b2c3d4e5f6789012');

console.log(item.url);
console.log(item.mimeType);
console.log(item.createdAt);

Delete Media

// Delete single item
await imperial.delete('67d8f9a1b2c3d4e5f6789012');

// Delete multiple items
await imperial.deleteBatch([
  '67d8f9a1b2c3d4e5f6789012',
  '67d8f9a1b2c3d4e5f6789013',
  '67d8f9a1b2c3d4e5f6789014'
]);

Monitor Rate Limits

const result = await imperial.upload({ ... });

// Check rate limit info after any request
const rateLimit = imperial.getRateLimitInfo();
console.log(`Requests remaining: ${rateLimit?.remaining}/${rateLimit?.limit}`);

// Check usage info
const usage = imperial.getUsageInfo();
console.log(`Operations: ${usage?.operationsUsed}/${usage?.operationsLimit}`);
console.log(`Storage: ${(usage?.storageUsed / 1024 / 1024 / 1024).toFixed(2)} GB`);

Browser Usage

import { ImperialClient } from '@imperial/sdk';

const imperial = new ImperialClient({
  apiKey: 'imperial_upload_xxxxxxxxxxxxx'
});

// Upload from file input
const fileInput = document.querySelector<HTMLInputElement>('#file-input');
const file = fileInput.files[0];

const result = await imperial.upload({
  file: file,
  filename: file.name,
  mimeType: file.type
});

console.log(`Uploaded: ${result.url}`);

Error Handling

The SDK provides specific error classes for different scenarios:

import {
  ImperialClient,
  AuthenticationError,
  StorageLimitError,
  RateLimitError,
  ValidationError
} from '@imperial/sdk';

try {
  await imperial.upload({ ... });
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key');
  } else if (error instanceof StorageLimitError) {
    console.error('Storage limit exceeded');
  } else if (error instanceof RateLimitError) {
    console.error(`Rate limited. Retry after ${error.retryAfter}s`);
  } else if (error instanceof ValidationError) {
    console.error('Validation failed:', error.details);
  } else {
    console.error('Unknown error:', error);
  }
}

Error Types

  • AuthenticationError (401) - Invalid or missing API key
  • PermissionError (403) - Insufficient permissions
  • NotFoundError (404) - Resource not found
  • StorageLimitError (413) - Storage limit exceeded
  • UnsupportedMediaError (415) - Invalid file type
  • RateLimitError (429) - Rate limit exceeded
  • ValidationError (400) - Invalid parameters
  • ServerError (500+) - Server error
  • NetworkError - Network/timeout error

Advanced Configuration

const imperial = new ImperialClient({
  apiKey: 'imperial_live_xxxxxxxxxxxxx',
  baseUrl: 'https://api.imperial.gay', // Custom API URL
  timeout: 30000, // Request timeout in ms (default: 30000)
  fetch: customFetch // Custom fetch implementation
});

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import type {
  UploadResult,
  MediaItem,
  ListMediaResult,
  RateLimitInfo
} from '@imperial/sdk';

const result: UploadResult = await imperial.upload({ ... });
const media: ListMediaResult = await imperial.list();
const item: MediaItem = await imperial.get('id');
const rateLimit: RateLimitInfo | undefined = imperial.getRateLimitInfo();

Response Types

UploadResult

{
  _id: string;
  url: string;
  thumbnailUrl?: string; // For videos
  filename: string;
  originalFilename: string;
  fileSize: number; // Bytes (after compression)
  originalFileSize: number; // Bytes (before compression)
  compressed: boolean;
  compressionQuality?: number;
  mimeType: string;
  createdAt: string; // ISO 8601
}

MediaItem

{
  _id: string;
  url: string;
  thumbnailUrl?: string | null;
  mimeType: string;
  prompt: string; // Original filename
  modelName: string; // File size (human readable)
  size: { width: number; height: number };
  createdAt: string;
  type: 'upload' | 'ai-image';
}

Best Practices

1. Store API Keys Securely

// ✅ Good - Use environment variables
const imperial = new ImperialClient({
  apiKey: process.env.IMPERIAL_API_KEY!
});

// ❌ Bad - Hard-coded keys
const imperial = new ImperialClient({
  apiKey: 'imperial_live_xxxxxxxxxxxxx' // Don't do this!
});

2. Handle Rate Limits

async function uploadWithRetry(file: Buffer, filename: string, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await imperial.upload({ file, filename });
    } catch (error) {
      if (error instanceof RateLimitError && error.retryAfter) {
        await new Promise(resolve => setTimeout(resolve, error.retryAfter * 1000));
        continue;
      }
      throw error;
    }
  }
}

3. Batch Operations

// ✅ Good - Use batch upload
await imperial.uploadBatch(files);

// ❌ Slower - Individual uploads
for (const file of files) {
  await imperial.upload(file);
}

License

MIT © Imperial