npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@musallam/firefly-services-clients

v2.4.0

Published

TypeScript client library for Adobe Firefly Services API

Readme

@musallam/firefly-services-clients

TypeScript client library for Adobe Firefly Services API

Auto-generated clients powered by Orval from official Adobe Firefly OpenAPI specifications.

Features

  • 🔥 Full TypeScript support with complete type definitions
  • 🤖 Auto-generated clients from OpenAPI specs using Orval
  • 🎨 Complete API coverage for all Firefly operations:
    • Text to Image generation
    • Image expansion
    • Generative fill
    • Similar image generation
    • Object composite generation
    • Video generation
    • Custom models
    • Image upload
  • 🏷️ Namespaced exports to avoid type conflicts between clients
  • Type-safe job polling with progress tracking and error handling
  • 🎯 Full type inference for polling results and progress callbacks
  • 🔐 Fetch-based with flexible authentication
  • 📦 ESM and CommonJS support
  • 🚀 Modern async/await API

Installation

npm install @musallam/firefly-services-clients

Quick Start

Note: All clients are exported under namespaces to avoid type conflicts. See docs/USAGE_EXAMPLES.md for detailed examples.

Generate Images

import { ImageGenerationClient } from '@musallam/firefly-services-clients';

const authOptions = {
  headers: {
    Authorization: `Bearer YOUR_ACCESS_TOKEN`,
    'x-api-key': 'YOUR_CLIENT_ID',
  },
};

// Start image generation job
const job = await ImageGenerationClient.generateImagesV3Async(
  {
    prompt: 'A futuristic city at sunset',
    numVariations: 2,
    size: { width: 2048, height: 2048 },
    contentClass: ImageGenerationClient.ContentClassV3.photo,
  },
  authOptions
);

console.log('Job started:', job.jobId);
console.log('Status URL:', job.statusUrl);

Poll Until Complete

Use the built-in polling utility to automatically wait for job completion with full type safety:

import { ImageGenerationClient, pollJob } from '@musallam/firefly-services-clients';

// Start the job
const job = await ImageGenerationClient.generateImagesV3Async(
  {
    prompt: 'A futuristic city at sunset',
    size: { width: 2048, height: 2048 },
  },
  authOptions
);

// Poll until complete with explicit result type for full type safety
const result = await pollJob<ImageGenerationClient.GenerateImagesResponseV3>(job, {
  fetchOptions: authOptions,
  intervalMs: 2000, // Check every 2 seconds
  onProgress: (status) => {
    console.log(`Status: ${status.status}, Progress: ${status.progress}%`);
    if (status.result) {
      // status.result is properly typed!
      console.log(`Generated ${status.result.outputs.length} images so far`);
    }
  },
});

// result is typed as GenerateImagesResponseV3
console.log('Generated images:', result.outputs);
result.outputs.forEach((output) => {
  console.log(`Image URL: ${output.image.url}`);
});

Available Clients

All clients are exported under their own namespace to prevent type conflicts:

| Client | Description | Source | | ------------------------------- | ----------------------------------- | ------------------------------------------- | | ImageGenerationClient | Text-to-image generation | image-generation-async-v3-client | | GenerateSimilarClient | Generate similar image variations | generate-similar-async-v3-client | | GenerateObjectCompositeClient | Composite objects into images | generate-object-composite-async-v3-client | | GenerativeExpandClient | Expand images with AI | generative-expand-async-v3-client | | GenerativeFillClient | Generative fill/remove objects | generative-fill-async-v3-client | | GenerateVideoClient | Generate videos from images/prompts | generate-video-api-client | | UploadImageClient | Upload images to Firefly storage | upload-image-client | | CustomModelsClient | List and manage custom models | custom-models-listing-client |

Usage Pattern

import {
  ImageGenerationClient,
  GenerateSimilarClient,
  UploadImageClient,
} from '@musallam/firefly-services-clients';

// Each client has its own types - no conflicts!
const alignment1: ImageGenerationClient.AlignmentHorizontal = 'center';
const alignment2: GenerateSimilarClient.AlignmentHorizontal = 'left';

// Use client functions
const result = await ImageGenerationClient.generateImagesV3Async(request, authOptions);

Authentication

All Firefly API calls require authentication headers with an access token and API key.

Built-in IMS Client

This library includes an IMSClient that handles OAuth 2.0 Client Credentials flow automatically:

import { IMSClient, ImageGenerationClient } from '@musallam/firefly-services-clients';

// Create IMS client
const imsClient = new IMSClient({
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
  scopes: ['openid', 'AdobeID', 'firefly_api', 'ff_apis'],
});

// Get auth headers (handles token fetching and caching)
const authHeaders = await imsClient.getAuthHeaders();

// Use with any client
const job = await ImageGenerationClient.generateImagesV3Async(request, {
  headers: authHeaders,
});

Features:

  • ✅ Automatic token fetching and caching
  • ✅ Token expiration handling with 60s buffer
  • ✅ OAuth 2.0 Client Credentials flow
  • ✅ Returns properly formatted headers (Authorization, x-api-key)

Manual Authentication

If you already have an access token, pass it directly:

const authOptions = {
  headers: {
    Authorization: `Bearer YOUR_ACCESS_TOKEN`,
    'x-api-key': 'YOUR_CLIENT_ID',
  },
};

const job = await ImageGenerationClient.generateImagesV3Async(request, authOptions);

Custom IMS Client

You can implement your own authentication strategy by implementing the IIMSClient interface:

import { IIMSClient } from '@musallam/firefly-services-clients';

class MyCustomIMSClient implements IIMSClient {
  async getAccessToken(): Promise<string> {
    // Your custom token fetching logic
    // e.g., fetch from cache, service account, etc.
    return 'your_access_token';
  }

  async getAuthHeaders(): Promise<Record<string, string>> {
    const token = await this.getAccessToken();
    return {
      Authorization: `Bearer ${token}`,
      'x-api-key': 'YOUR_CLIENT_ID',
    };
  }
}

// Use your custom client
const myClient = new MyCustomIMSClient();
const authHeaders = await myClient.getAuthHeaders();

Use cases for custom clients:

  • Token caching in Redis or external cache
  • Service account authentication
  • Integration with existing auth systems
  • Custom token refresh logic
  • Multi-tenant authentication

Token-only IMS Client

For scenarios where you already have a long-lived access token:

import { TokenIMSClient } from '@musallam/firefly-services-clients';

const tokenClient = new TokenIMSClient({
  accessToken: 'YOUR_EXISTING_TOKEN',
  clientId: 'YOUR_CLIENT_ID',
});

const authHeaders = await tokenClient.getAuthHeaders();

For more details on obtaining credentials, see the Adobe Firefly Services Authentication Guide.

Custom Axios Configuration

All API clients use a shared axios instance internally, which is exported as AXIOS_INSTANCE. You can customize this instance to configure global behavior for all API calls, such as timeouts, interceptors, custom headers, or retry logic.

since this mutates AXIOS_INSTANCE, it would need to be executed before any of the client calls.

import { AXIOS_INSTANCE } from '@musallam/firefly-services-clients';

// Add request interceptor
AXIOS_INSTANCE.interceptors.request.use((config) => {
  console.log('Making request to:', config.url);
  return config;
});

// Add response interceptor
AXIOS_INSTANCE.interceptors.response.use(
  (response) => {
    console.log('Response received:', response.status);
    return response;
  },
  (error) => {
    console.error('Request failed:', error.message);
    return Promise.reject(error);
  }
);

// Override base URL (e.g., for proxy or different environment)
AXIOS_INSTANCE.defaults.baseURL = 'https://your-proxy-server.com';

// Set global timeout
AXIOS_INSTANCE.defaults.timeout = 30000; // 30 seconds

// Add custom headers for all requests
AXIOS_INSTANCE.defaults.headers.common['X-Custom-Header'] = 'value';

Common use cases:

  • Setting global timeouts for all API calls
  • Adding request/response logging
  • Implementing retry logic with interceptors
  • Adding custom headers to all requests
  • Overriding the base URL (for proxies or different environments)
  • Monitoring API performance
  • Handling errors globally

For a complete list of available configuration options and interceptor capabilities, see the Axios documentation.

Image Upload

For uploading images to Firefly storage (for use with operations like generate similar, expand, fill), use the uploadImage utility:

import { uploadImage } from '@musallam/firefly-services-clients';

// Read your image file
const imageBuffer = readFileSync('./my-image.jpg');
const imageBlob = new Blob([imageBuffer], { type: 'image/jpeg' });

// Upload to Firefly storage
const uploadResult = await uploadImage(imageBlob, {
  headers: authHeaders,
});

const uploadId = uploadResult.images[0].id;

// Use the uploadId in other operations
const job = await GenerateSimilarClient.generateSimilarImagesV3Async(
  {
    image: {
      source: { uploadId },
    },
    numVariations: 3,
  },
  { headers: authHeaders }
);

Note: Use uploadImage instead of UploadImageClient.storageImageV2 as it properly handles binary data uploads. The generated client has a limitation with Blob serialization that this utility addresses.

Job Polling

All async operations return { jobId, statusUrl, cancelUrl }. Use the polling utilities to wait for completion:

pollJob<TResult>(jobResult, options)

Polls a single job until completion with full TypeScript type safety. Specify the result type explicitly for the best developer experience:

import { ImageGenerationClient, pollJob } from '@musallam/firefly-services-clients';

// Recommended: Specify the result type for full type safety
const result = await pollJob<ImageGenerationClient.GenerateImagesResponseV3>(job, {
  fetchOptions: authOptions,
  intervalMs: 2000, // Poll every 2 seconds (default)
  maxAttempts: 60, // Max 60 attempts (default: 120 seconds)
  timeoutMs: 300000, // Or set explicit 5-minute timeout
  onProgress: (status) => {
    console.log(`Status: ${status.status}`);
    console.log(`Progress: ${status.progress}%`);
    // status.result is properly typed as GenerateImagesResponseV3 | undefined
    if (status.result) {
      console.log(`Generated ${status.result.outputs.length} images`);
    }
  },
});

// result is typed as GenerateImagesResponseV3
console.log(`Image URL: ${result.outputs[0].image.url}`);

Available Result Types:

  • ImageGenerationClient.GenerateImagesResponseV3
  • GenerativeExpandClient.ExpandImageResponseV3
  • GenerativeFillClient.FillImageResponseV3
  • GenerateSimilarClient.GenerateSimilarImagesResponseV3
  • GenerateObjectCompositeClient.GenerateObjectCompositeResponseV3
  • GenerateVideoClient.AsyncResult

See docs/TYPE_INFERENCE_GUIDE.md for detailed examples.

Polling Multiple Jobs

You can poll multiple jobs in parallel using Promise.all:

import { pollJob, ImageGenerationClient } from '@musallam/firefly-services-clients';

const jobs = [job1, job2, job3];

const results = await Promise.all(
  jobs.map((job) =>
    pollJob<ImageGenerationClient.GenerateImagesResponseV3>(job, {
      fetchOptions: authOptions,
    })
  )
);

// results is an array of GenerateImagesResponseV3
results.forEach((result, index) => {
  console.log(`Job ${index + 1} generated ${result.outputs.length} images`);
});

Error Handling

import {
  ImageGenerationClient,
  pollJob,
  PollingError,
  PollingTimeoutError,
} from '@musallam/firefly-services-clients';

try {
  const result = await pollJob<ImageGenerationClient.GenerateImagesResponseV3>(job, {
    fetchOptions: authOptions,
    maxAttempts: 30,
  });
  console.log(`Success! Generated ${result.outputs.length} images`);
} catch (error) {
  if (error instanceof PollingTimeoutError) {
    console.error('Job timed out after maximum attempts');
  } else if (error instanceof PollingError) {
    console.error('Job failed:', error.message);
    console.log('Job status:', error.status);
  }
}

Architecture

This package uses Orval to auto-generate TypeScript clients from OpenAPI specifications:

build-scripts/
  ├── fetch-spec.ts          # Downloads OpenAPI specs
  └── spec-urls.ts           # Configuration for spec URLs

src/
  ├── spec/                  # OpenAPI spec files (JSON)
  ├── generated/             # Auto-generated clients (DO NOT EDIT)
  │   ├── image-generation-async-v3-client/
  │   ├── generate-similar-async-v3-client/
  │   └── ...
  ├── extension/             # Custom extensions
  │   └── job-polling-extension.ts
  ├── mutator/               # Custom fetch client
  └── index.ts               # Main entry (namespaced exports)

orval.config.ts              # Orval configuration

Code Generation Workflow

  1. Fetch specs: Download OpenAPI specs from Adobe

    npm run fetch-spec
  2. Generate clients: Generate TypeScript clients using Orval

    npm run orval
  3. Build: Bundle the library

    npm run build

Namespaced Exports

To avoid type name conflicts (e.g., multiple clients exporting AlignmentHorizontal), all clients are imported and re-exported under namespaces in src/index.ts:

// src/index.ts
import * as ImageGenerationClient from './generated/image-generation-async-v3-client/index.js';
import * as GenerateSimilarClient from './generated/generate-similar-async-v3-client/index.js';

export {
  ImageGenerationClient,
  GenerateSimilarClient,
  // ...
};

This allows consumers to use:

const type1: ImageGenerationClient.AlignmentHorizontal = 'center';
const type2: GenerateSimilarClient.AlignmentHorizontal = 'left';
// No conflicts!

More Examples

See USAGE_EXAMPLES.md for comprehensive examples including:

  • All client types with usage examples
  • Polling patterns and error handling
  • Batch processing multiple jobs
  • Working with different content types

Also check the Adobe Firefly Services documentation for API details and guides.

Development

Setup

# Install dependencies
npm install

# Download OpenAPI specs
npm run fetch-spec

# Generate clients from specs
npm run orval

Common Commands

# Type check
npm run type-check

# Lint
npm run lint

# Format code
npm run format

# Build library
npm run build

# Run all checks
npm run type-check && npm run lint

Regenerating Clients

When Adobe updates their OpenAPI specs:

# 1. Download latest specs
npm run fetch-spec

# 2. Regenerate clients
npm run orval

# 3. Verify everything works
npm run type-check
npm run build

Project Structure

  • src/generated/ - Auto-generated code (never edit manually)
  • src/extension/ - Custom utilities and extensions
  • src/mutator/ - Custom fetch implementation
  • orval.config.ts - Orval configuration for code generation
  • build-scripts/ - Scripts for fetching specs and automation

Contributing

This project uses:

  • Orval - OpenAPI to TypeScript code generation
  • Conventional Commits for commit messages
  • ESLint + Prettier for code quality
  • Husky for git hooks
  • Semantic Release for automated versioning

Contributing Guidelines

  1. Never edit files in src/generated/ directly - they are auto-generated
  2. Use conventional commits format: feat:, fix:, docs:, etc.
  3. Run linter and type-check before committing
  4. Extensions and utilities go in src/extension/

License

MIT


Built with Orval | API by Adobe Firefly Services