Imagery is a provider-agnostic TypeScript library for image generation, image editing, and inpainting across OpenAI GPT Image and Google Gemini image models.
Current version: 0.3.1
The v1 API is intentionally small and explicit:
client.images.generate() for text-to-image generation.client.images.edit() for image-to-image editing with one or more reference images.client.images.inpaint() for pixel-mask inpainting where supported, or semantic inpainting where supported.Provider differences are visible by design. OpenAI and Google do not expose the same capabilities, safety controls, cost units, or response metadata, and this library avoids hiding those differences behind a chat-style abstraction.
pnpm add @rishabhbothra/imagery
The package is ESM-first and requires Node.js 20 or newer.
The hosted documentation is published with GitHub Pages:
https://07rjain.github.io/imagery/
API reference:
https://07rjain.github.io/imagery/api/
import { ImageClient } from '@rishabhbothra/imagery';
const client = ImageClient.fromEnv({
defaultProvider: 'openai',
defaultModel: 'gpt-image-2',
});
const response = await client.images.generate({
prompt: 'A matte black water bottle on sandstone',
size: '1024x1024',
quality: 'low',
outputFormat: 'png',
});
const image = response.images[0];
ImageClient.fromEnv() reads these environment variables:
OPENAI_API_KEY=
GEMINI_API_KEY=
Do not expose provider API keys in browser code. Use this package from trusted server, worker, or edge environments.
Use the built-in mock provider for tests and examples that should not call real APIs:
const client = ImageClient.fromEnv({
defaultProvider: 'mock',
defaultModel: 'mock-image',
});
const response = await client.images.generate({
prompt: 'A local deterministic test image',
});
Both provider adapters support reference-image edits where the selected model supports them:
const edited = await client.images.edit({
provider: 'google',
model: 'gemini-3.1-flash-image-preview',
prompt: 'Combine the product from the first image with the lighting from the second image.',
inputImages: [
{ data: firstImageBytes, mediaType: 'image/png' },
{ data: secondImageBytes, mediaType: 'image/jpeg' },
],
});
OpenAI gpt-image-2 supports pixel-mask inpainting:
await client.images.inpaint({
provider: 'openai',
model: 'gpt-image-2',
prompt: 'Replace the sofa with a vintage leather chair.',
image: { data: roomBytes, mediaType: 'image/png' },
mask: { data: maskBytes, mediaType: 'image/png' },
});
Google Gemini image models support semantic inpainting in v1:
await client.images.inpaint({
provider: 'google',
model: 'gemini-3.1-flash-image-preview',
prompt: 'Edit the supplied product photo.',
image: { data: productBytes, mediaType: 'image/jpeg' },
semanticMask: 'Change only the product color to navy blue.',
});
Passing a pixel mask to a Google model throws an ImageCapabilityError.
| Provider | Model | Notes |
|---|---|---|
| OpenAI | gpt-image-2 |
Generate, edit, pixel-mask inpaint, semantic inpaint |
| Google Gemini API | gemini-3-pro-image-preview |
Generate, edit, semantic inpaint |
| Google Gemini API | gemini-3.1-flash-image-preview |
Generate, edit, semantic inpaint |
Google support targets the Gemini API, not Google Cloud Vertex AI, Gemini Enterprise, or enterprise agent platform APIs.
Safety relaxation is never automatic.
moderation: 'low' must be set explicitly through providerOptions.openai.OFF and BLOCK_NONE safety thresholds require allowLessRestrictiveSafetySettings: true.fallback.onSafetyError is explicitly enabled.The library does not write generated images to durable storage. Responses contain bytes and metadata:
const bytes = response.images[0]?.data;
const mediaType = response.images[0]?.mediaType;
Applications own storage, CDN upload, retention, and access control.
pnpm install
pnpm verify
Useful commands:
pnpm typecheck
pnpm test
pnpm test:consumer
pnpm docs:api
pnpm docs:build
Live tests are opt in and make real provider calls:
LIVE_IMAGE_TESTS=1 pnpm test:live
Live outputs are written to live-artifacts/, which is ignored by git.
Run:
pnpm verify
Check that local credentials and generated artifacts are not staged:
git status --short
The following paths should stay local-only:
.env.env.*realtest/live-artifacts/node_modules/dist/generate, edit, and inpaint.fetch and Web APIs for Node and edge-compatible runtimes.