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

@metalevel/snapix-sdk-core

v1.0.0

Published

TypeScript SDK for the Snapix REST API - image upload, conversion, resizing, gallery management, and AI generation

Readme

@metalevel/snapix-sdk-core

Typed TypeScript SDK for the Snapix REST API - image upload, on-the-fly conversion, resizing, gallery management, and AI generation. Three client classes cover every runtime: a full-featured Node.js server client, a browser-safe client for any JS runtime, and an abstract base you can extend directly.

  • Full TypeScript types for all requests and responses
  • Zero runtime dependencies - uses native fetch and FormData
  • Three client classes - SnapixClientServer (Node.js, full CRUD), SnapixClientBrowser (any JS runtime, read + convert), SnapixClientBasic (abstract base)
  • Auto-configuration from environment variables

Installation

npm install @metalevel/snapix-sdk-core

or

pnpm add @metalevel/snapix-sdk-core

Quick Start

SnapixClientServer

Upload an image from your Node.js server using SNAPIX_API_KEY:

export SNAPIX_API_KEY=your_api_key_here
import { SnapixClientServer } from "@metalevel/snapix-sdk-core";

const client = new SnapixClientServer(); // reads SNAPIX_API_KEY from env

const result = await client.uploadImage({
  imageUrl: "https://example.com/photo.jpg",
  name: "my-photo",
  formatOptions: [{ format: "webp" }],
});

console.log(result.simpleData.variants);
// { webp: "https://cdn.snapix.space/..." }

SnapixClientBrowser

Read images and galleries safely in any JS runtime using NEXT_PUBLIC_SNAPIX_API_KEY. A read-only API key is sufficient and recommended:

export NEXT_PUBLIC_SNAPIX_API_KEY=your_read_only_api_key_here
import { SnapixClientBrowser } from "@metalevel/snapix-sdk-core/browser";

const client = new SnapixClientBrowser(); // reads NEXT_PUBLIC_SNAPIX_API_KEY from env

// List galleries
const { galleries } = await client.listGalleries();

// List images with pagination
const { data: images, simpleData } = await client.listImages({ page: 1, limit: 10 });

// Get a single image
const { data: image } = await client.getImage({ imageId: "image-uuid" });
console.log(image.urlBase, image.metadata);

Class Hierarchy

SnapixClientBasic           (abstract - shared read methods, zero Node.js deps)
├── SnapixClientServer      (full CRUD + Node.js file I/O, uses SNAPIX_* env vars)
└── SnapixClientBrowser     (read + convert, browser-safe, uses NEXT_PUBLIC_SNAPIX_* env vars)

SnapixClientBasic is the abstract base - you do not instantiate it directly. Use SnapixClientServer in Node.js environments for full access to upload, generate, and gallery write operations. Use SnapixClientBrowser in browsers, edge runtimes, or any environment where you only need read access and on-the-fly image conversion with a restricted API key.

Package Exports

The SDK ships three dedicated entry points. Use the subpath that matches your runtime — importing from the wrong one will cause build errors in browser-targeting bundlers (Turbopack, Webpack, Vite, etc.).

Why three entry points?

SnapixClientServer uses node:fs/promises for file I/O. Browser bundlers statically resolve every import in a module's graph, even code you never call at runtime. When a barrel file re-exports both SnapixClientServer and SnapixClientBrowser together, the bundler tries to include node:fs/promises in the browser chunk and fails with:

the chunking context does not support external modules (request: node:fs/promises)

Dedicated subpath exports ensure each entry point only pulls in what its target runtime supports.

Subpath exports

| Import path | Class | Use in | | --- | --- | --- | | @metalevel/snapix-sdk-core | SnapixClientServer | Node.js server, MCP server, Next.js server actions, API routes | | @metalevel/snapix-sdk-core/browser | SnapixClientBrowser | Browser, Next.js client components, edge runtimes | | @metalevel/snapix-sdk-core/basic | SnapixClientBasic | Custom subclasses only | | @metalevel/snapix-sdk-core/server | SnapixClientServer | Alias for root — identical to "." |

All subpaths export the error classes (SnapixApiError, SnapixConfigError) and all TypeScript types relevant to that client.

SnapixClientBasic

The abstract base class shared by both subclasses. It holds all read methods and requires zero Node.js dependencies. Use it only if you are extending the SDK with a custom subclass; otherwise use SnapixClientServer or SnapixClientBrowser directly.

Configuration

Pass options directly to the constructor:

// When subclassing SnapixClientBasic directly:
super({
  apiKey: "your_api_key",
  baseUrl: "https://www.snapix.space", // optional
  bucketKey: "my-bucket",              // optional
  logLevel: "debug",                   // optional
});

Logging

The logLevel option (or the corresponding env var on each subclass) controls log verbosity:

| Level | Description | | --- | --- | | debug | All requests logged with method + URL | | info | Informational messages (e.g., file written) | | warn | Rate limit hits (HTTP 429) | | error | API errors, quota exceeded | | silent | No output |

Read Methods

All read methods are inherited by both SnapixClientServer and SnapixClientBrowser:

// List images with optional pagination and filters
await client.listImages(params?: ListImagesParams): Promise<ListImagesResponse>
// params: { page?, limit?, sort?: "asc" | "desc", bucketKey? }
// response includes: data, simpleData, accountStatistics, pagination

// Get a single image by ID
await client.getImage(params: GetImageParams): Promise<GetImageResponse>
// params: { imageId }

// List all galleries
await client.listGalleries(): Promise<ListGalleriesResponse>

// Get a single gallery with its images
await client.getGallery(params: GetGalleryParams): Promise<GetGalleryResponse>
// params: { galleryId }

// Get images not assigned to any gallery
await client.getImagesWithoutGallery(params?: GetImagesWithoutGalleryParams): Promise<GetGalleryResponse>
// params: { bucketKey? }

// Fetch a documentation page as Markdown
await client.getDocs(params: GetDocsParams): Promise<string>
// params: { docType: "sdk" | "api" | "mcp" | "about" }

Error Handling

Both SnapixApiError and SnapixConfigError are thrown by all three client classes. Import them from the same subpath as your client:

// Server / Node.js
import { SnapixClientServer, SnapixApiError, SnapixConfigError } from "@metalevel/snapix-sdk-core";

// Browser / client components
// import { SnapixClientBrowser, SnapixApiError, SnapixConfigError } from "@metalevel/snapix-sdk-core/browser";

try {
  const client = new SnapixClientServer();
  await client.uploadImage({ imageUrl: "https://example.com/photo.jpg" });
} catch (err) {
  if (err instanceof SnapixConfigError) {
    // Missing SNAPIX_API_KEY or invalid configuration
    console.error("Config error:", err.message);
  } else if (err instanceof SnapixApiError) {
    console.error("API error:", err.status, err.message);
    if (err.isRetryable) { /* HTTP 429 - retry after backoff */ }
    if (err.isReadOnly) { /* HTTP 403 - key lacks required permission */ }
  }
}

SnapixClientBrowser

Designed for any JavaScript runtime - browsers, Next.js client components, edge runtimes. Zero Node.js dependencies. Reads NEXT_PUBLIC_SNAPIX_* environment variables by default (standard in Next.js), but accepts explicit config options in any environment.

Security: When used client-side, your API key is exposed in the browser bundle. Use a dedicated API key with restricted read-only permissions - see API Key Permissions.

Environment Variables

| Variable | Required | Default | Description | | --- | --- | --- | --- | | NEXT_PUBLIC_SNAPIX_API_KEY | Yes | - | Your Snapix API key | | NEXT_PUBLIC_SNAPIX_BASE_URL | No | https://www.snapix.space | Override API base URL | | NEXT_PUBLIC_SNAPIX_BUCKET_KEY | No | primary bucket | Default storage bucket key | | NEXT_PUBLIC_SNAPIX_LOG_LEVEL | No | warn | debug | info | warn | error | silent |

Manual Configuration

import { SnapixClientBrowser } from "@metalevel/snapix-sdk-core/browser";

const client = new SnapixClientBrowser({
  apiKey: "your_api_key",
  baseUrl: "https://www.snapix.space", // optional
  bucketKey: "my-bucket",              // optional
  logLevel: "debug",                   // optional
});

Read Methods

SnapixClientBrowser inherits all read methods from SnapixClientBasic - see Read Methods above.

Convert Methods

On-the-fly conversion - results are not stored in cloud storage. imageFilePath is not supported (no filesystem access in browser environments); use SnapixClientServer for that. imageBlob accepts a File from <input type="file"> directly - no base64 encoding needed.

Write methods (uploadImage, updateImage, deleteImage, generateImage, and all gallery write methods) are only available on SnapixClientServer.

convertImage - raw binary + MIME type

await client.convertImage(params: ConvertImageParams): Promise<ConvertImageBrowserResult>
// ConvertImageBrowserResult: { buffer: Uint8Array, type: string }
// `type` is the MIME type from the API response Content-Type header
const file = inputElement.files[0];
const result = await client.convertImage({
  imageBlob: file,
  formatOptions: { format: "webp" },
  resizeOptions: { width: 800 },
});
// result.buffer - Uint8Array of the converted image
// result.type  - e.g. "image/webp"

convertImageToBlob - returns a Blob

await client.convertImageToBlob(params: ConvertImageToBlobParams): Promise<Blob>
// params extends ConvertImageParams with { mimeType?: string }
// mimeType overrides the API-returned Content-Type; defaults to result.type
const blob = await client.convertImageToBlob({
  imageBlob: file,
  formatOptions: { format: "webp" },
});

convertImageToObjectUrl - returns a blob: URL

await client.convertImageToObjectUrl(params: ConvertImageToObjectUrlParams): Promise<string>
// params extends ConvertImageParams with { mimeType?: string }
// Returns a temporary blob: URL - caller must call URL.revokeObjectURL() when done
const objectUrl = await client.convertImageToObjectUrl({
  imageBlob: file,
  formatOptions: { format: "webp" },
});
imgElement.src = objectUrl;
// Later, when no longer needed:
URL.revokeObjectURL(objectUrl);

convertImageAndDownload - triggers a download dialog

await client.convertImageAndDownload(params: ConvertImageAndDownloadParams): Promise<void>
// params extends ConvertImageParams with { filename: string, mimeType?: string }
// Browser-only - throws if called outside a browser environment (SSR, Node.js, Workers)
// URL.revokeObjectURL() is called automatically after the download is triggered
await client.convertImageAndDownload({
  imageBlob: file,
  formatOptions: { format: "avif" },
  filename: "converted.avif",
});

SnapixClientServer

The full-featured server client for Node.js ≥ 18. Provides all read methods inherited from SnapixClientBasic, plus image upload, update, delete, AI generation, on-the-fly conversion to Buffer, and gallery management.

Environment Variables

| Variable | Required | Default | Description | | --- | --- | --- | --- | | SNAPIX_API_KEY | Yes | - | Your Snapix API key | | SNAPIX_BASE_URL | No | https://www.snapix.space | Override API base URL | | SNAPIX_BUCKET_KEY | No | primary bucket | Default storage bucket key | | SNAPIX_LOG_LEVEL | No | warn | debug | info | warn | error | silent |

Manual Configuration

import { SnapixClientServer } from "@metalevel/snapix-sdk-core";

const client = new SnapixClientServer({
  apiKey: "your_api_key",
  baseUrl: "https://www.snapix.space", // optional
  bucketKey: "my-bucket",              // optional
  logLevel: "debug",                   // optional
});

Read Methods

SnapixClientServer inherits all read methods from SnapixClientBasic - see Read Methods above.

Image Methods

// Upload from URL, file path, base64, or Blob/File
await client.uploadImage(params: UploadImageParams): Promise<UploadImageResponse>

// Update metadata and/or replace image content
await client.updateImage(params: UpdateImageParams): Promise<UpdateImageResponse>
// params: { imageId, name?, description?, galleries?, formatOptions?, resizeOptions?, imageUrl?, ... }

// Delete an image
await client.deleteImage(params: DeleteImageParams): Promise<{ success: true }>
// params: { imageId }

Upload example - format + resize combinations, assign to gallery:

const result = await client.uploadImage({
  imageUrl: "https://example.com/photo.jpg",
  name: "my-photo",
  description: "A landscape photo",
  formatOptions: [{ format: "webp" }, { format: "avif" }],
  resizeOptions: [{ width: 1280 }, { width: 640 }],
  galleries: ["gallery-uuid"],
});
// Costs 4 credits (2 formats × 2 resizes)
console.log(result.simpleData); // [{ id, originalName, variants, info }, ...]

Update example - metadata only, or replace the image file:

// Metadata-only update
await client.updateImage({
  imageId: "image-uuid",
  name: "new-name",
  description: "Updated description",
  galleries: ["gallery-uuid"],
});

// Replace image content
await client.updateImage({
  imageId: "image-uuid",
  imageFilePath: "/tmp/new-version.png",
  formatOptions: [{ format: "webp" }],
});

Convert Methods

On-the-fly conversion - results are not stored in cloud storage. Accepts imageFilePath, imageBlob, imageBase64, or imageUrl. Costs 1 credit per call.

// Returns binary data as a Buffer
await client.convertImage(params: ConvertImageParams): Promise<Buffer>

// Converts and writes directly to disk
await client.convertImageToFile(params: ConvertImageToFileParams): Promise<void>
// params extends ConvertImageParams with { outputPath: string }
// From URL
const buffer = await client.convertImage({
  imageUrl: "https://example.com/photo.jpg",
  formatOptions: { format: "webp" },
  resizeOptions: { width: 400 },
});

// From file path
const buffer = await client.convertImage({
  imageFilePath: "/tmp/source.png",
  formatOptions: { format: "avif" },
});

// Write directly to disk
await client.convertImageToFile({
  imageFilePath: "/tmp/source.png",
  formatOptions: { format: "avif" },
  outputPath: "/tmp/output.avif",
});

Generate Method (AI)

Generate an image from a text prompt using AI. Requires a paid subscription.

await client.generateImage(params: GenerateImageParams): Promise<GenerateImageResponse>
// From text prompt only
const result = await client.generateImage({
  promptText: "A serene mountain lake at sunset",
  name: "mountain-lake",
  formatOptions: [{ format: "webp" }],
});
// Costs 40+ credits

// From text prompt + image template (image-to-image)
const result = await client.generateImage({
  promptText: "Transform into an oil painting style",
  imageUrl: "https://example.com/source-photo.jpg",
  name: "oil-painting",
  formatOptions: [{ format: "webp" }],
});
// Also accepts imageFilePath, imageBase64, or imageBlob as the template source

Gallery Methods

// Create a gallery (server-only)
await client.createGallery(params: CreateGalleryParams): Promise<CreateGalleryResponse>

// Update gallery name or visibility (server-only)
await client.updateGallery(params: UpdateGalleryParams): Promise<GalleryType>
// params: { galleryId, name?, isPublic? }

// Delete a gallery; pass deleteImages: true to also delete all its images (server-only)
await client.deleteGallery(params: DeleteGalleryParams): Promise<{ success: boolean }>
// params: { galleryId, deleteImages? }

// Inherited read methods from SnapixClientBasic:
await client.listGalleries(): Promise<ListGalleriesResponse>
await client.getGallery(params: GetGalleryParams): Promise<GetGalleryResponse>
await client.getImagesWithoutGallery(params?: GetImagesWithoutGalleryParams): Promise<GetGalleryResponse>
// Create
const { gallery } = await client.createGallery({ name: "My Portfolio", isPublic: true });

// Update
await client.updateGallery({ galleryId: gallery.id, isPublic: false });

// Delete gallery only (keep images)
await client.deleteGallery({ galleryId: gallery.id });

// Delete gallery and all its images
await client.deleteGallery({ galleryId: gallery.id, deleteImages: true });

Next.js Integration

Use SnapixClientServer in server actions or API routes - never in client components:

// app/actions/upload.ts
"use server";
import { SnapixClientServer } from "@metalevel/snapix-sdk-core";

const client = new SnapixClientServer(); // reads SNAPIX_API_KEY from env

export async function uploadProfileImage(formData: FormData) {
  const file = formData.get("image") as File;
  const base64 = Buffer.from(await file.arrayBuffer()).toString("base64");

  const result = await client.uploadImage({
    imageBase64: base64,
    imageContentType: file.type,
    name: "profile-image",
    formatOptions: [{ format: "webp" }],
    resizeOptions: [{ width: 256, height: 256 }],
  });

  return result.simpleData[0].variants["webp"];
}

Constants Reference

Some runtime constants are exported from every subpath alongside types. Import them from the same entry point as your client:

export {
  NEXT_PUBLIC_SNAPIX_BASE_URL as nextPublicSnapixBaseUrl,
  SNAPIX_BASE_URL as snapixBaseUrl,
  APP_SERVER_GALLERY_URI as snapixGalleryUri,
} from "./constants.js";

SNAPIX_BASE_URL and NEXT_PUBLIC_SNAPIX_BASE_URL are particularly useful when constructing image URLs or links to the {{ appName }} app without hard-coding the domain:

import { snapixBaseUrl, snapixGalleryUri } from "@metalevel/snapix-sdk-core";

const galleryPageUrl = `${snapixBaseUrl}${snapixGalleryUri}/${galleryId}`;

Links

License

MIT