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

@modulacms/admin-sdk

v0.1.6

Published

TypeScript SDK for the ModulaCMS admin API

Readme

@modulacms/admin-sdk

TypeScript SDK for the ModulaCMS admin API. Provides fully typed CRUD operations for all admin resources, authentication, media uploads, content tree retrieval, plugin management, server configuration, and bulk imports from external CMS platforms.

Features

  • Zero runtime dependencies -- built on native fetch
  • Dual ESM + CJS builds via tsup
  • Branded ID types prevent mixing incompatible identifiers at compile time
  • HTTPS enforced by default; allowInsecure flag for local development
  • 30s default timeout with per-request AbortSignal support
  • Targets Node.js 18+ and modern browsers

Install

npm install @modulacms/admin-sdk
# or
pnpm add @modulacms/admin-sdk

Quick Start

import { createAdminClient, isApiError } from '@modulacms/admin-sdk'

const client = createAdminClient({
  baseUrl: 'https://cms.example.com',
  apiKey: process.env.CMS_API_KEY,
})

// Authentication
const me = await client.auth.me()

// CRUD operations
const users = await client.users.list()
const route = await client.adminRoutes.get(slug)

// Paginated listing
const page = await client.contentData.listPaginated({ limit: 20, offset: 0 })
console.log(page.data, page.total)

// Count
const total = await client.users.count()

// Media upload
const media = await client.mediaUpload.upload(file)

// Content tree
const tree = await client.adminTree.get(slug)

// Plugin management
const plugins = await client.plugins.list()

// Bulk import
const result = await client.import.contentful(exportData)

Configuration

import type { ClientConfig } from '@modulacms/admin-sdk'

const config: ClientConfig = {
  baseUrl: 'https://cms.example.com', // Required. HTTPS enforced unless allowInsecure is set.
  apiKey: 'sk_live_abc123',           // Optional. Bearer token for server-side auth.
  defaultTimeout: 15000,              // Optional. Default: 30000ms.
  credentials: 'include',            // Optional. Default: 'include'. Controls fetch credentials mode.
  allowInsecure: false,               // Optional. Set true for http:// in development.
}

Error Handling

The SDK throws ApiError for non-2xx responses and native TypeError for network failures.

import { isApiError } from '@modulacms/admin-sdk'

try {
  await client.users.get(userId)
} catch (err) {
  if (isApiError(err)) {
    console.error(`API ${err.status}: ${err.message}`, err.body)
  } else {
    console.error('Network error:', err)
  }
}

For media uploads, additional error guards are available:

import { isDuplicateMedia, isFileTooLarge, isInvalidMediaPath } from '@modulacms/admin-sdk'

try {
  await client.mediaUpload.upload(file, { path: 'products/shoes' })
} catch (err) {
  if (isDuplicateMedia(err)) { /* 409 conflict */ }
  if (isFileTooLarge(err)) { /* 400 size limit */ }
  if (isInvalidMediaPath(err)) { /* 400 bad path */ }
}

Available Resources

Standard CRUD Resources

Each resource provides list(), get(id), create(params), update(params), remove(id), listPaginated({ limit, offset }), and count():

| Property | Entity | ID Type | |---|---|---| | adminRoutes | Admin routes | Slug (get/list) / AdminRouteID (remove) | | adminContentData | Admin content nodes | AdminContentID | | adminContentFields | Admin content field values | AdminContentFieldID | | adminDatatypes | Admin datatype definitions | AdminDatatypeID | | adminFields | Admin field definitions | AdminFieldID | | adminDatatypeFields | Admin datatype-field mappings | string | | contentData | Public content nodes | ContentID | | contentFields | Public content field values | ContentFieldID | | datatypes | Datatype schemas | DatatypeID | | fields | Field schemas | FieldID | | datatypeFields | Datatype-field mappings | string | | routes | Public routes | RouteID | | media | Media assets | MediaID | | mediaDimensions | Media dimension presets | string | | users | User accounts | UserID | | roles | Permission roles | RoleID | | permissions | Permissions | PermissionID | | rolePermissions | Role-permission mappings | RolePermissionID | | tokens | API tokens | string | | usersOauth | OAuth connections | UserOauthID | | tables | Custom tables | string |

adminRoutes also provides listOrdered() which returns routes sorted by position.

rolePermissions additionally provides listByRole(roleId) to get all permissions for a specific role.

Authentication

// Login with email + password
const session = await client.auth.login({ email, password })

// Get current user
const me = await client.auth.me()

// Register new user
const user = await client.auth.register({ name, email, password })

// Reset password
await client.auth.reset({ user_id, password })

// Logout
await client.auth.logout()

Content Tree

Retrieve the full content tree for a route, optionally in a specific CMS format:

// Raw format (default)
const tree = await client.adminTree.get('my-page')

// Formatted for a specific CMS structure
const formatted = await client.adminTree.get('my-page', 'contentful')
// Supported formats: 'raw' | 'contentful' | 'sanity' | 'strapi' | 'wordpress' | 'clean'

Returns AdminTreeResponse with { route, tree } where tree is an array of ContentTreeNode with recursive children and resolved fields.

Media Upload

const media = await client.mediaUpload.upload(file)

// With custom path prefix
const media = await client.mediaUpload.upload(file, { path: 'products/shoes' })

The returned Media object's srcset field may be null initially while async image processing completes.

Sessions

await client.sessions.update({ session_id, ...params })
await client.sessions.remove(sessionId)

Sessions are created implicitly via login -- there is no create method.

SSH Keys

// List keys (public_key omitted for security)
const keys = await client.sshKeys.list()

// Create a key (returns full key including public_key)
const key = await client.sshKeys.create({ name, public_key })

// Remove a key
await client.sshKeys.remove(keyId)

Plugins

// List all plugins
const plugins = await client.plugins.list()

// Get detailed info (circuit breaker state, schema drift, etc.)
const info = await client.plugins.get('my-plugin')

// Lifecycle management
await client.plugins.enable('my-plugin')
await client.plugins.disable('my-plugin')
await client.plugins.reload('my-plugin')

// Orphaned table cleanup
const dryRun = await client.plugins.cleanupDryRun()
const result = await client.plugins.cleanupDrop({ tables: ['orphaned_table'] })

Plugin Routes and Hooks

// List plugin-registered routes
const routes = await client.pluginRoutes.list()

// Approve or revoke route registrations
await client.pluginRoutes.approve([{ plugin: 'my-plugin', method: 'GET', path: '/custom' }])
await client.pluginRoutes.revoke([{ plugin: 'my-plugin', method: 'GET', path: '/custom' }])

// Same pattern for hooks
const hooks = await client.pluginHooks.list()
await client.pluginHooks.approve([{ plugin: 'my-plugin', event: 'content:create' }])
await client.pluginHooks.revoke([{ plugin: 'my-plugin', event: 'content:create' }])

Server Configuration

// Get current config (sensitive values redacted)
const config = await client.config.get()

// Get a specific category
const dbConfig = await client.config.get('database')

// Update config
const result = await client.config.update({ port: 9090 })
if (result.restart_required) {
  console.log('Server restart needed')
}

// Get field metadata (labels, categories, sensitivity flags)
const meta = await client.config.meta()

Bulk Import

Import content from external CMS platforms:

const result = await client.import.contentful(exportData)
const result = await client.import.sanity(exportData)
const result = await client.import.strapi(exportData)
const result = await client.import.wordpress(exportData)
const result = await client.import.clean(exportData)

// Generic bulk import with format parameter
const result = await client.import.bulk('contentful', exportData)

Returns ImportResponse with { success, datatypes_created, fields_created, content_created, message, errors }.

Request Options

All methods accept an optional RequestOptions parameter for per-request control:

const controller = new AbortController()

const users = await client.users.list({ signal: controller.signal })

// Cancel the request
controller.abort()

Types

All types are exported from the package entry point:

import type {
  // Client
  ClientConfig,
  ModulaCMSAdminClient,
  CrudResource,

  // Branded IDs
  UserID, ContentID, MediaID, RoleID, DatatypeID, FieldID, RouteID,
  AdminContentID, AdminRouteID, AdminDatatypeID, AdminFieldID,
  PermissionID, RolePermissionID, SessionID, UserOauthID,
  Slug, Email, URL,

  // Enums
  ContentStatus, // 'draft' | 'published' | 'archived' | 'pending'
  FieldType,     // 'text' | 'textarea' | 'number' | 'date' | 'boolean' | 'media' | ...

  // Pagination
  PaginationParams,
  PaginatedResponse,

  // Errors
  ApiError,
  RequestOptions,
} from '@modulacms/admin-sdk'

Development

This package is part of the sdks/typescript/ pnpm workspace monorepo. From the repository root:

just sdk-install    # pnpm install (workspace root)
just sdk-build      # Build all packages (types first, then SDKs)
just sdk-test       # Run all SDK tests (Vitest)
just sdk-typecheck  # Typecheck all packages

Or within this package directly:

pnpm run build       # Compile to dist/
pnpm run typecheck   # Type-check without emitting
pnpm test            # Run tests

License

MIT