@nexera/management
v0.1.0
Published
Nexera CMS Management SDK — full CRUD for entries, content models, assets, and more
Maintainers
Readme
@nexera/management
Nexera CMS Management SDK — full CRUD for entries, content models, assets, environments, locales, and branches.
Installation
npm install @nexera/managementRequirements: Node.js 18+ (uses the global fetch API). Works in browsers, edge runtimes, and Node.js.
Quick Start
import { createManagementClient } from '@nexera/management';
const mgmt = createManagementClient({
baseUrl: 'https://api.yourcms.com',
stackId: 'your-stack-uuid',
tenantId: 'your-tenant-uuid',
branchId: 'your-branch-uuid',
apiKey: 'cms_mgmt_abc123...', // or use `token` for JWT
});
// Create and publish an entry
const entry = await mgmt.entries.create('content-model-id', {
data: { title: 'Hello World', body: 'My first post' },
locale: 'en',
});
await mgmt.entries.publish('content-model-id', entry.id);Configuration
createManagementClient({
baseUrl: string; // BFF API base URL
stackId: string; // Stack UUID
tenantId: string; // Tenant UUID
branchId: string; // Branch UUID
token?: string; // JWT token (mutually exclusive with apiKey)
apiKey?: string; // API key (mutually exclusive with token)
defaultLocale?: string; // Default locale for entry operations
fetch?: typeof fetch; // Custom fetch
fetchOptions?: RequestInit; // Default fetch options
})Either
tokenorapiKeymust be provided.
Entries
Full CRUD with publish workflow and version management.
// List
const entries = await mgmt.entries.list('model-id', {
page: 1, limit: 20, locale: 'en', status: 'published',
});
// Get
const entry = await mgmt.entries.get('model-id', 'entry-id');
// Create
const newEntry = await mgmt.entries.create('model-id', {
data: { title: 'New Post', body: 'Content here' },
locale: 'en',
});
// Update
await mgmt.entries.update('model-id', 'entry-id', {
data: { title: 'Updated Title' },
});
// Delete
await mgmt.entries.delete('model-id', 'entry-id');Publishing:
await mgmt.entries.publish('model-id', 'entry-id');
await mgmt.entries.unpublish('model-id', 'entry-id');
await mgmt.entries.schedule('model-id', 'entry-id', {
publishAt: '2026-04-01T09:00:00Z',
unpublishAt: '2026-05-01T09:00:00Z',
});Version history:
const versions = await mgmt.entries.listVersions('model-id', 'entry-id');
await mgmt.entries.restoreVersion('model-id', 'entry-id', 'version-id');Content Models
// List all
const models = await mgmt.contentModels.list();
// Get
const model = await mgmt.contentModels.get('model-id');
// Create
const newModel = await mgmt.contentModels.create({
name: 'Blog Post',
key: 'blog-post',
description: 'Blog articles',
});
// Update
await mgmt.contentModels.update('model-id', { description: 'Updated' });
// Delete
await mgmt.contentModels.delete('model-id');Field management:
import { FieldType } from '@nexera/management';
const fields = await mgmt.contentModels.listFields('model-id');
await mgmt.contentModels.addField('model-id', {
key: 'author',
name: 'Author',
type: FieldType.SingleLineText,
required: true,
});
await mgmt.contentModels.updateField('model-id', 'field-id', {
required: false,
});Assets
// List
const assets = await mgmt.assets.list({ page: 1, limit: 20 });
// Search
const results = await mgmt.assets.search('hero image');
// Upload (Node.js)
import fs from 'node:fs';
const file = new Blob([fs.readFileSync('./photo.jpg')], { type: 'image/jpeg' });
const uploaded = await mgmt.assets.upload(file, { description: 'Team photo' });
// Upload (Browser)
const inputFile = document.querySelector('input[type="file"]').files[0];
const uploaded = await mgmt.assets.upload(inputFile);
// Update metadata
await mgmt.assets.update('asset-id', { title: 'New title' });
// Delete
await mgmt.assets.delete('asset-id');Environments
Tenant-scoped (not branch-scoped).
const environments = await mgmt.environments.list();
await mgmt.environments.create({ name: 'staging' });
await mgmt.environments.update('env-id', { name: 'production' });
await mgmt.environments.delete('env-id');Locales
Branch-scoped.
const locales = await mgmt.locales.list();
await mgmt.locales.create({ code: 'fr', name: 'French' });
await mgmt.locales.update('locale-id', { isDefault: true });
await mgmt.locales.delete('locale-id');Branches
Tenant-scoped.
const branches = await mgmt.branches.list();
await mgmt.branches.create({ name: 'feature/redesign' });
await mgmt.branches.update('branch-id', { name: 'feature/v2' });
await mgmt.branches.delete('branch-id');Error Handling
import {
CmsError,
CmsAuthenticationError,
CmsNotFoundError,
CmsRateLimitError,
} from '@nexera/management';
try {
await mgmt.entries.get('model-id', 'entry-id');
} catch (error) {
if (error instanceof CmsNotFoundError) {
console.log(`${error.resourceType} not found: ${error.resourceId}`);
} else if (error instanceof CmsAuthenticationError) {
console.log('Check your API key or JWT token');
} else if (error instanceof CmsRateLimitError) {
console.log(`Retry after ${error.retryAfterMs}ms`);
} else if (error instanceof CmsError) {
console.log(`HTTP ${error.statusCode}:`, error.responseBody);
}
}Enums
import { EntryState, ContentModelType, FieldType } from '@nexera/management';
EntryState.Draft // 0
EntryState.Published // 3
ContentModelType.Standard // 0
ContentModelType.PageTemplate // 1
ContentModelType.Component // 2
FieldType.SingleLineText // 0
FieldType.Reference // 11
FieldType.ModularBlock // 7Node.js Script Example
import { createManagementClient } from '@nexera/management';
const mgmt = createManagementClient({
baseUrl: process.env.API_URL!,
stackId: process.env.STACK_ID!,
tenantId: process.env.TENANT_ID!,
branchId: process.env.BRANCH_ID!,
apiKey: process.env.MANAGEMENT_API_KEY!,
});
// Bulk publish all draft entries
const drafts = await mgmt.entries.list('blog-model-id', { status: 'draft' });
for (const entry of drafts.items) {
await mgmt.entries.publish('blog-model-id', entry.id);
console.log(`Published: ${entry.id}`);
}Related
- @nexera/delivery — Read published content and query via GraphQL.
License
MIT
