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

@powerit/cms-client

v1.1.0

Published

JavaScript client library for PowerIT CMS public API

Readme

@powerit/cms-client

A pure JavaScript client library for the PowerIT CMS public API. Works in browsers, Node.js, and any JavaScript runtime.

Installation

npm install @powerit/cms-client

Quick Start

import { createClient } from '@powerit/cms-client';

const cms = createClient({
  baseUrl: 'https://your-cms.example.com',
  apiKey: 'your-api-key',
  locale: 'en' // Optional default locale
});

// Get all published content
const { data: contents } = await cms.getContents();

// Get a specific page by slug
const page = await cms.getContentBySlug('home');
console.log(page.translation.title);

Configuration

const cms = createClient({
  // Required
  baseUrl: 'https://your-cms.example.com',
  apiKey: 'your-api-key',

  // Optional
  locale: 'en',              // Default locale for content
  timeout: 30000,            // Request timeout in ms
  headers: {                 // Additional headers
    'X-Custom-Header': 'value'
  },
  fetch: customFetch         // Custom fetch implementation
});

Node.js Usage

For Node.js versions without native fetch, provide a fetch implementation:

import { createClient } from '@powerit/cms-client';
import fetch from 'node-fetch';

const cms = createClient({
  baseUrl: 'https://your-cms.example.com',
  apiKey: 'your-api-key',
  fetch: fetch
});

API Reference

Content

// List published contents
const { data, meta } = await cms.getContents({
  type: 'page',        // Filter by content type
  locale: 'en',        // Filter by locale
  page: 1,             // Pagination
  per_page: 10
});

// Get content by ID or slug
const content = await cms.getContent('home');
const content = await cms.getContent(123);

// Get content by slug (explicit)
const page = await cms.getContentBySlug('about-us', { locale: 'en' });

// Get contents by type
const { data: blogs } = await cms.getContentsByType('blog');

// Get available content types
const { types } = await cms.getContentTypes();
// ['page', 'blog', 'news']

// Get available locales
const { locales } = await cms.getContentLocales();
// ['en', 'ro', 'fr']

Menus

Requires read_menus permission on API key.

// List all menus
const { menus } = await cms.getMenus();

// Get menu by ID or location
const menu = await cms.getMenu('header');
const menu = await cms.getMenu(1);

// Get menu by location name
const footer = await cms.getMenuByLocation('footer');

Redirects

Requires read_redirects permission on API key.

// List all redirects
const { redirects } = await cms.getRedirects();

// Check if a path has a redirect
const redirect = await cms.checkRedirect('/old-page');
if (redirect) {
  console.log(`Redirect to ${redirect.target_path} (${redirect.status_code})`);
}

// Resolve a path through redirect chains
const resolved = await cms.resolvePath('/old-page');
if (resolved) {
  console.log(`Final destination: ${resolved.finalPath}`);
  console.log(`Hops taken: ${resolved.hops}`);
}

Languages

// Get active languages
const { languages } = await cms.getLanguages();

// Get language codes only
const codes = await cms.getLanguageCodes();
// ['en', 'ro', 'fr']

// Check if a language is supported
const supported = await cms.isLanguageSupported('de');

Search

// Search content
const { data: results, meta } = await cms.search('keyword', {
  page: 1,
  per_page: 20,
  type: 'blog',        // Filter by content type
  locale: 'en'         // Filter by locale
});

// Get search suggestions
const { suggestions } = await cms.getSuggestions('key');

// Track click analytics
await cms.trackClick({
  query: 'search term',
  content_id: 123,
  position: 1
});

Locale Management

// Set default locale
cms.setLocale('ro');

// Get current locale
const locale = cms.getLocale();

// Override locale per request
const content = await cms.getContent('home', { locale: 'fr' });

Content Structure

Content responses include the following structure:

interface Content {
  id: number;
  type: string;            // 'page', 'blog', etc.
  slug: string;
  status: 'draft' | 'published' | 'archived';
  published_at: string;
  created_at: string;
  updated_at: string;
  author?: {
    id: number;
    name: string;
  };
  translation: {
    locale: string;
    title: string;
    body: ContentBlock[];  // Array of content blocks
    excerpt?: string;
    seo?: {
      meta_description?: string;
      meta_keywords?: string;
    };
  };
  available_locales: string[];
}

Content Block Types

The body field contains an array of typed content blocks:

  • hero: Hero sections with title, subtitle, CTA buttons
  • text: Rich text content (HTML, Markdown, or plain text)
  • gallery: Image galleries with various layouts
  • faq: FAQ sections with expandable items
  • collections: Dynamic collection data with entities

Error Handling

The client throws CMSError for API errors:

import { createClient, CMSError } from '@powerit/cms-client';

try {
  const content = await cms.getContent('non-existent');
} catch (error) {
  if (error instanceof CMSError) {
    console.log(error.status);   // HTTP status code
    console.log(error.message);  // Error message
    console.log(error.data);     // Additional error data
  }
}

TypeScript Support

The package includes TypeScript definitions:

import { createClient, Content, Menu, CMSClientConfig } from '@powerit/cms-client';

const config: CMSClientConfig = {
  baseUrl: 'https://cms.example.com',
  apiKey: 'your-api-key'
};

const cms = createClient(config);

const content: Content = await cms.getContent('home');

Examples

Static Site Generation

import { createClient } from '@powerit/cms-client';

const cms = createClient({
  baseUrl: process.env.CMS_URL,
  apiKey: process.env.CMS_API_KEY
});

// Generate pages for all content
async function generatePages() {
  const { types } = await cms.getContentTypes();

  for (const type of types) {
    const { data: contents } = await cms.getContentsByType(type);

    for (const content of contents) {
      await generatePage(content);
    }
  }
}

Multi-language Site

const cms = createClient({
  baseUrl: 'https://cms.example.com',
  apiKey: 'your-api-key'
});

// Get content in user's language with fallback
async function getLocalizedContent(slug, preferredLocale) {
  const locales = await cms.getLanguageCodes();

  // Try preferred locale first
  if (locales.includes(preferredLocale)) {
    try {
      return await cms.getContentBySlug(slug, { locale: preferredLocale });
    } catch (e) {
      // Fall through to default
    }
  }

  // Fallback to default (no locale = API default)
  return cms.getContentBySlug(slug);
}

Middleware for Redirects

// Express.js example
import { createClient } from '@powerit/cms-client';

const cms = createClient({
  baseUrl: process.env.CMS_URL,
  apiKey: process.env.CMS_API_KEY
});

app.use(async (req, res, next) => {
  const redirect = await cms.checkRedirect(req.path);

  if (redirect) {
    return res.redirect(redirect.status_code, redirect.target_path);
  }

  next();
});

License

MIT