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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@elmapicms/js-sdk

v0.4.1

Published

JavaScript SDK for ElmapiCMS Content API

Downloads

224

Readme

ElmapiCMS JavaScript SDK

A JavaScript SDK for interacting with the ElmapiCMS Content API. This SDK provides type-safe access to all API endpoints for managing content, assets, and collections in your ElmapiCMS instance.

Installation

npm install @elmapicms/js-sdk

Quick Start

import { createClient } from '@elmapicms/js-sdk';

// Create a client instance
const client = createClient(
  'https://your-instance.elmapi.com/api',
  'your-api-token',
  '550e8400-e29b-41d4-a716-446655440000' // Your project UUID
);

// Get project 
const project = await client.getProject();
console.log('Project Info:', projectInfo);

// Get collections for the project
const collections = await client.getCollections();
console.log('Collections:', collections);

// Get entries for a collection
const entries = await client.getEntries('blog-posts');
console.log('Entries:', entries);

Features

  • Type Safety: Full TypeScript support with comprehensive type definitions
  • Promise-based: Modern async/await support
  • Comprehensive: Covers all API endpoints in a single client
  • Well-documented: JSDoc comments for all methods
  • Simplified API: All methods available directly on the client instance

Error Handling

The SDK provides comprehensive error handling with specific error types, detailed error messages, and debugging information. All errors extend from the base ElmapiError class.

Error Types

The SDK throws specific error types based on the HTTP status code or error condition:

  • AuthenticationError (401): Invalid or missing API token
  • AuthorizationError (403): Insufficient permissions
  • NotFoundError (404): Resource not found
  • ValidationError (422): Invalid request data
  • RateLimitError (429): Rate limit exceeded
  • ServerError (5xx): Server-side errors
  • NetworkError: Network connectivity issues
  • TimeoutError: Request timeout

Basic Error Handling

import { 
  createClient, 
  AuthenticationError,
  NotFoundError,
  ValidationError 
} from '@elmapicms/js-sdk';

const client = createClient(
  'https://your-instance.elmapi.com/api',
  'your-api-token',
  'your-project-id'
);

try {
  const project = await client.getProject();
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Authentication failed:', error.message);
    console.log('Please check your API token');
  } else if (error instanceof NotFoundError) {
    console.error('Resource not found:', error.message);
  } else if (error instanceof ValidationError) {
    console.error('Validation failed:', error.message);
    console.error('Details:', error.details);
  } else {
    console.error('Unexpected error:', error.message);
  }
}

Advanced Error Handling

Each error includes detailed information for debugging:

try {
  const collection = await client.getCollection('non-existent');
} catch (error) {
  console.error('Error details:', {
    name: error.name,
    message: error.message,
    statusCode: error.statusCode,
    code: error.code,
    details: error.details
  });
  
  // Request information for debugging
  if (error.requestInfo) {
    console.error('Request details:', {
      method: error.requestInfo.method,
      url: error.requestInfo.url,
      params: error.requestInfo.params
    });
  }
}

Retry Logic with Error Handling

async function retryWithBackoff(operation, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error) {
      // Don't retry on certain errors
      if (error instanceof AuthenticationError || 
          error instanceof NotFoundError || 
          error instanceof ValidationError) {
        throw error;
      }
      
      // Retry on rate limit, server errors, and network errors
      if (attempt === maxRetries) {
        throw error;
      }
      
      const delay = Math.pow(2, attempt) * 1000;
      console.log(`Attempt ${attempt} failed, retrying in ${delay}ms...`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// Usage
try {
  const result = await retryWithBackoff(() => client.getCollections());
  console.log('Success:', result);
} catch (error) {
  console.error('All retry attempts failed:', error.message);
}

Client Configuration Validation

// Validate client configuration
try {
  client.validateConfiguration();
  console.log('✓ Configuration is valid');
} catch (error) {
  console.error('Configuration Error:', error.message);
}

// Get debug information
const debugInfo = client.getDebugInfo();
console.log('Client Configuration:', debugInfo);

See the error handling examples for more detailed patterns.

API Reference

Client Methods

getProject(params?)

Get project including name, description, default locale, and available locales. Optional params:

  • with: Comma-separated list for collections and fields (e.g. with=collections,fields)
const project = await client.getProject();
// Returns: { uuid, name, description, default_locale, locales }

getCollections()

Get all collections for the current project.

const collections = await client.getCollections();
// Returns: Array of collection objects

getCollection(collectionSlug)

Get detailed information about a specific collection including its fields.

const collection = await client.getCollection('blog-posts');
// Returns: Collection object with fields array

getEntries(collectionSlug, params?)

Get entries for a collection with optional filtering and pagination.

const posts = await client.getEntries('blog-posts', {
  state: 'with_draft',        // 'only_draft' | 'with_draft'
  locale: 'en',              // Filter by locale
  exclude: 'content,excerpt', // Comma-separated fields to exclude
  where: { state: 'published' }, // Advanced filtering
  sort: 'created_at:desc',  // Sorting
  limit: 20,                 // Number of items
  offset: 0,                 // Pagination offset
  timestamps: true           // Include created_at/updated_at
});

getEntry(collectionSlug, uuid, params?)

Get a specific entry by UUID with optional query parameters.

// Basic usage
const post = await client.getEntry('blog-posts', '550e8400-e29b-41d4-a716-446655440000');

// Get entry for a specific locale
const post = await client.getEntry('blog-posts', 'uuid', {
  locale: 'en'
});

// Get translation of an entry
const translation = await client.getEntry('blog-posts', 'uuid', {
  translation_locale: 'fr'
});

// Get entry with additional options
const post = await client.getEntry('blog-posts', 'uuid', {
  locale: 'en',
  state: 'published',           // 'only_draft' | 'with_draft' | 'published'
  exclude: ['content', 'excerpt'], // Array of field names to exclude
  timestamps: true              // Include created_at and updated_at
});

Parameters:

  • collectionSlug (string, required): The collection slug
  • uuid (string, required): The entry UUID
  • params (object, optional): Query parameters
    • locale (string): Fetch entry for a specific locale code (e.g., 'en-US')
    • translation_locale (string): Get the translation of this entry in the specified locale. Returns the linked translation entry instead of the original.
    • state (string): Controls the publication state. Options: 'only_draft', 'with_draft', 'published'
    • exclude (string[]): An array of field names to exclude from the response
    • timestamps (boolean): If true, includes created_at and updated_at in the response

createEntry(collectionSlug, data)

Create a new entry.

const newPost = await client.createEntry('blog-posts', {
  locale: 'en',
  state: 'draft',
  published_at: '2024-01-01T00:00:00Z',
  data: {
    title: 'My New Post',
    content: 'Post content here...'
  }
});

updateEntry(collectionSlug, uuid, data)

Update an existing entry (PUT).

const updatedPost = await client.updateEntry('blog-posts', 'uuid', {
  state: 'published',
  data: { title: 'Updated Title' }
});

patchEntry(collectionSlug, uuid, data)

Partially update an entry (PATCH).

const patchedPost = await client.patchEntry('blog-posts', 'uuid', {
  data: { title: 'Patched Title' }
});

deleteEntry(collectionSlug, uuid, force?)

Delete an entry. If force is set to true or 1, the entry is permanently deleted. If not set, the entry is moved to trash.

await client.deleteEntry('blog-posts', 'uuid');           // Move to trash
await client.deleteEntry('blog-posts', 'uuid', true);     // Permanently delete

getAssets(params?)

Get all assets for the current project with optional filtering.

const assets = await client.getAssets({
  search: 'image',           // Search by filename, original filename, or mime type
  type: 'image',             // 'image' | 'video' | 'audio' | 'document'
  paginate: 20               // Number of items per page
});

getAsset(identifier)

Get a specific asset by ID or UUID.

const asset = await client.getAsset('550e8400-e29b-41d4-a716-446655440000');

getAssetByFilename(filename)

Get a specific asset by original filename.

const asset = await client.getAssetByFilename('my-image.jpg');

uploadAsset(file, metadata?)

Upload a new file asset.

const uploadedAsset = await client.uploadAsset(file, {
  alt: 'Image description',
  category: 'blog'
});

deleteAsset(identifier, force?)

Delete an asset (soft delete by default, or permanent with force parameter).

await client.deleteAsset('uuid');           // Soft delete
await client.deleteAsset('uuid', true);     // Permanent delete

License

See LICENSE file for details.

Support

For support, please contact [email protected] or visit our documentation at https://docs.elmapicms.com.