b-dashboard-plugin-cms
v1.0.1
Published
Headless CMS plugin for B-Dashboard with content modeling, multi-database support, and auto-generated APIs
Maintainers
Readme
@b-dashboard/plugin-cms
A headless content management system plugin for B-Dashboard with visual content modeling, multi-database support, and auto-generated APIs.
Features
Core Features (Free)
- 📋 Visual Content Modeling - Create and manage content types with drag-and-drop field configuration
- 📝 12+ Field Types - Text, Rich Text, Number, Boolean, Date, DateTime, JSON, Media, Relations, Enum, Slug, Email, URL
- 🗃️ SQLite Database - Zero-config embedded database
- 🔌 Auto-generated APIs - RESTful API endpoints for all content types
- 🖼️ Media Library - Upload and manage images, videos, and documents
- 🌍 Internationalization - Built-in i18n support with multiple locales
- 📊 Dashboard Widgets - Content statistics and recent entries
Pro Features (Paid License)
- 🐘 PostgreSQL Support - Enterprise-grade database
- 🐬 MySQL Support - Popular relational database
- 🔧 API Builder - Custom API endpoints and transformations
- 🔗 Webhooks - Event-driven integrations
- 📜 Content Versioning - Track content history
- ☁️ CDN Integration - Optimized media delivery
- 📦 Import/Export - Bulk data operations
- ♾️ Unlimited Content Types & Entries
Installation
npm install @b-dashboard/plugin-cms
# or
pnpm add @b-dashboard/plugin-cms
# or
yarn add @b-dashboard/plugin-cmsQuick Start
1. Register the Plugin
// app/plugins.ts
import { registerPlugin } from '@/lib/plugins';
import cmsPlugin from '@b-dashboard/plugin-cms';
registerPlugin(cmsPlugin);2. Initialize the CMS
import { initializeCMS } from '@b-dashboard/plugin-cms';
// With default SQLite configuration
await initializeCMS({});
// Or with custom configuration
await initializeCMS({
database: {
type: 'sqlite',
sqlite: { filename: './data/cms.db' }
},
media: {
basePath: './uploads',
baseUrl: '/uploads',
maxSize: 10 * 1024 * 1024, // 10MB
allowedTypes: ['image/*', 'video/*', 'application/pdf']
},
content: {
defaultLocale: 'en',
locales: ['en', 'ar', 'es'],
enableDrafts: true,
enableVersioning: false
}
});3. Create a Content Type
import { contentTypeService } from '@b-dashboard/plugin-cms';
const blogPost = await contentTypeService.create({
name: 'Blog Post',
slug: 'blog-posts',
description: 'Blog articles',
fields: [
{
id: 'title',
name: 'Title',
type: 'text',
required: true
},
{
id: 'content',
name: 'Content',
type: 'richtext',
required: true
},
{
id: 'featured_image',
name: 'Featured Image',
type: 'media'
},
{
id: 'published_date',
name: 'Published Date',
type: 'date'
}
],
titleField: 'title'
});4. Create Entries
import { entryService } from '@b-dashboard/plugin-cms';
const post = await entryService.create({
contentTypeId: blogPost.id,
status: 'draft',
data: {
title: 'My First Blog Post',
content: '<p>Hello, world!</p>',
published_date: '2024-01-15'
}
});
// Publish the entry
await entryService.publish('blog-posts', post.id);5. Query Entries via API
import { entryService } from '@b-dashboard/plugin-cms';
// Get all published posts
const posts = await entryService.getAll('blog-posts', {
status: 'published',
sort: 'published_date',
order: 'desc',
page: 1,
limit: 10
});API Reference
Content Type Service
import { contentTypeService } from '@b-dashboard/plugin-cms';
// Get all content types
const types = await contentTypeService.getAll();
// Get by ID or slug
const type = await contentTypeService.getById(id);
const type = await contentTypeService.getBySlug('blog-posts');
// Create
const newType = await contentTypeService.create({ ... });
// Update
const updated = await contentTypeService.update(id, { ... });
// Delete
await contentTypeService.delete(id);Entry Service
import { entryService } from '@b-dashboard/plugin-cms';
// List entries with pagination
const entries = await entryService.getAll('blog-posts', {
page: 1,
limit: 20,
status: 'published',
search: 'keyword',
sort: 'createdAt',
order: 'desc',
filters: { category: 'tech' }
});
// CRUD operations
const entry = await entryService.getById('blog-posts', id);
const created = await entryService.create({ ... });
const updated = await entryService.update('blog-posts', id, { ... });
await entryService.delete('blog-posts', id);
// Status operations
await entryService.publish('blog-posts', id);
await entryService.unpublish('blog-posts', id);
await entryService.archive('blog-posts', id);
// Bulk operations
await entryService.bulkDelete('blog-posts', [id1, id2, id3]);
await entryService.bulkUpdateStatus('blog-posts', [id1, id2], 'published');Media Service
import { mediaService } from '@b-dashboard/plugin-cms';
// Configure media service
mediaService.configure({
basePath: './uploads',
baseUrl: '/uploads',
maxSize: 10 * 1024 * 1024,
allowedTypes: ['image/*', 'video/*', 'application/pdf']
});
// Upload file
const result = await mediaService.upload(buffer, {
filename: 'image.jpg',
mimeType: 'image/jpeg',
size: buffer.length,
alt: 'My image',
folder: 'blog'
});
// List media
const media = await mediaService.getAll({
page: 1,
limit: 20,
folder: 'blog',
mimeType: 'image/*',
search: 'keyword'
});
// Update metadata
await mediaService.update(id, { alt: 'Updated alt text' });
// Delete
await mediaService.delete(id);Database Service
import { databaseService } from '@b-dashboard/plugin-cms';
// Initialize with configuration
await databaseService.initialize({
type: 'sqlite',
sqlite: { filename: './data/cms.db' }
});
// For MySQL (Pro)
await databaseService.initialize({
type: 'mysql',
mysql: {
host: 'localhost',
port: 3306,
database: 'cms',
user: 'root',
password: 'password'
}
});
// For PostgreSQL (Pro)
await databaseService.initialize({
type: 'postgresql',
postgresql: {
host: 'localhost',
port: 5432,
database: 'cms',
user: 'postgres',
password: 'password'
}
});
// Execute queries
const result = await databaseService.query('SELECT * FROM cms_content_types');
await databaseService.execute('UPDATE cms_media SET alt = ? WHERE id = ?', ['alt', id]);
// Transactions
await databaseService.transaction(async (tx) => {
await tx.execute('INSERT INTO ...');
await tx.execute('UPDATE ...');
});Field Types
| Type | Description | Options |
|------|-------------|---------|
| text | Single/multi-line text | minLength, maxLength, pattern, placeholder, multiline |
| richtext | HTML formatted text | minLength, maxLength, allowedFormats |
| number | Integer or decimal | min, max, step, precision, format |
| boolean | True/false toggle | defaultValue, trueLabel, falseLabel |
| date | Date without time | minDate, maxDate, format |
| datetime | Date with time | minDate, maxDate, format, timezone |
| json | Structured JSON data | schema |
| media | Files, images, videos | allowedTypes, maxSize, multiple, maxFiles |
| relation | Link to other entries | targetType, relationType, displayField, cascade |
| enum | Select from options | options, multiple |
| slug | URL-friendly text | sourceField, prefix, suffix |
| email | Email address | allowedDomains |
| url | Web URL | allowedProtocols |
License Verification
The CMS plugin uses the B-Dashboard license server for premium features:
// Check license status
const licenseStatus = await checkLicense('@b-dashboard/plugin-cms');
if (licenseStatus.valid && licenseStatus.features.includes('postgresql_database')) {
// Enable PostgreSQL support
}Directory Structure
plugins/cms/
├── src/
│ ├── index.ts # Main exports
│ ├── manifest.ts # Plugin manifest
│ ├── types.ts # TypeScript types
│ ├── schemas.ts # Zod validation schemas
│ └── services/
│ ├── index.ts
│ ├── database.service.ts
│ ├── content-type.service.ts
│ ├── entry.service.ts
│ ├── media.service.ts
│ └── migration.service.ts
├── locales/
│ ├── en.json
│ └── ar.json
├── package.json
├── tsconfig.json
├── tsup.config.ts
└── README.mdContributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT License - see LICENSE for details.
