@tspvivek/baasix
v0.0.9-7.alpha-64
Published
A flexible headless CMS with dynamic schema management and CRUD API creation
Downloads
810
Readme
Baasix
A flexible, feature-rich headless CMS with dynamic schema management and comprehensive API capabilities.
Overview
Baasix is a powerful backend-as-a-service platform that enables rapid development of web and mobile applications. It provides a dynamic schema management system, built-in authentication and authorization, file handling capabilities, and much more.
Core Features
- 🔄 Dynamic Schema Management - Create, modify, and delete data models on-the-fly
- 🔐 Authentication & Authorization - Built-in user management with JWT, session-based auth, and magic links
- 👥 Multi-tenant Support - Isolate data across different tenants in the same application
- 📁 File Handling & Storage - Support for local and S3-compatible storage providers
- 🔍 Full-text Search - Automatic indexing and search capabilities across your data
- 🗺️ PostGIS Support - Geospatial data types and operations
- 💾 Redis Caching - High-performance caching for improved response times
- 📧 Email Services - Integrated email capabilities for user notifications
- ⚙️ Workflow Automation - Visual workflow builder with 17 node types and real-time execution monitoring
- 🎣 Extensible Hook System - Add custom logic at various points in the request lifecycle
- 📅 Scheduled Tasks - Run background processes and cron jobs
- 🔌 REST API - Comprehensive API endpoints for all operations
- 🔄 Real-time Updates - Optional Socket.IO integration
- 🧪 Comprehensive Testing Suite - Ensures reliability and stability
Installation
Using NPM Package
npm install @tspvivek/baasixQuick Start
Create a server.js file:
import { startServer } from "@tspvivek/baasix";
if (require.main === module) {
const app = startServer();
}Run your server:
node server.jsPrerequisites
- Node.js (v14+)
- PostgreSQL (v11+)
- Redis (optional, for caching)
Configuration
Environment Variables
Create a .env file in your project root with the following options:
# Server Configuration
PORT=8056
NODE_ENV=development
# Database
DB_CLIENT=postgres
DB_HOST=localhost
DB_PORT=5432
DB_NAME=baasix
DB_USER=postgres
DB_PASSWORD=postgres
DB_POSTGIS=true
# Authentication
SECRET_KEY=your-secret-key
COOKIE_SECRET=your-cookie-secret
ACCESS_TOKEN_EXPIRES_IN=3600
REFRESH_TOKEN_EXPIRES_IN=604800
PUBLIC_REGISTRATION=true
DEFAULT_ROLE_REGISTERED=user
AUTH_APP_URL=http://localhost:3000
# Multi-tenant Support
MULTI_TENANT=false
TENANT_FIELD=tenant_Id
ALLOWED_ROLES_MULTI_TENANT=owner,admin,user
# Cache Configuration
CACHE_ENABLED=true
CACHE_TTL=30000
CACHE_REDIS_URL=redis://localhost:6379
CACHE_SIZE_GB=1
# Rate Limiting
RATE_LIMIT=100
RATE_LIMIT_INTERVAL=5000
# Storage Services
STORAGE_SERVICES_ENABLED=local,s3
STORAGE_DEFAULT_SERVICE=local
LOCAL_STORAGE_PATH=./uploads
LOCAL_STORAGE_DRIVER=LOCAL
# S3 Configuration
S3_STORAGE_ACCESS_KEY_ID=your-access-key
S3_STORAGE_SECRET_ACCESS_KEY=your-secret-key
S3_STORAGE_REGION=your-region
S3_STORAGE_BUCKET=your-bucket
S3_STORAGE_ENDPOINT=your-endpoint
# Email Configuration
MAIL_SENDERS_ENABLED=smtp
MAIL_DEFAULT_SENDER=smtp
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-email
SMTP_PASS=your-password
[email protected]
# Real-time Support
SOCKET_ENABLED=false
SOCKET_PATH=/socket.ioDocker Deployment
You can also run Baasix using Docker:
docker build -t baasix .
docker run -p 8056:8056 --env-file .env baasixOr with docker-compose:
version: '3'
services:
baasix:
build: .
ports:
- "8056:8056"
env_file: .env
depends_on:
- postgres
- redis
postgres:
image: postgis/postgis:13-3.1
ports:
- "5432:5432"
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: baasix
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:6
ports:
- "6379:6379"
volumes:
postgres_data:API Reference
Authentication
Baasix provides multiple authentication methods:
Registration
POST /auth/register
Content-Type: application/json
{
"firstName": "John",
"lastName": "Doe",
"email": "[email protected]",
"password": "securePassword123",
"authMode": "jwt" // Optional: "jwt" (default) or "cookie"
}Login
POST /auth/login
Content-Type: application/json
{
"email": "[email protected]",
"password": "securePassword123",
"authMode": "jwt" // Optional: "jwt" (default) or "cookie"
}Magic Link Authentication
POST /auth/magiclink
Content-Type: application/json
{
"email": "[email protected]",
"link": "http://localhost:3000", // The app URL where user will be redirected
"mode": "link" // "link" or "code"
}Get Current User
GET /auth/me
Authorization: Bearer <token>Logout
GET /auth/logout
Authorization: Bearer <token>Dynamic Schema Management
Create or update a schema:
POST /schemas
Authorization: Bearer <token>
Content-Type: application/json
{
"collectionName": "products",
"schema": {
"name": "Product",
"timestamps": true,
"paranoid": true,
"fields": {
"id": {
"type": "UUID",
"primaryKey": true,
"defaultValue": { "type": "UUIDV4" }
},
"name": {
"type": "String",
"allowNull": false
},
"price": {
"type": "Double",
"allowNull": false
},
"description": {
"type": "Text"
},
"category_id": {
"type": "UUID"
},
"category": {
"relType": "BelongsTo",
"target": "categories",
"foreignKey": "category_id"
}
},
"indexes": [
{
"fields": ["name"],
"unique": true,
"name": "product_name_unique"
}
]
}
}Item Management
Baasix provides a standardized CRUD API for all collections:
Create Item
POST /items/:collection
Authorization: Bearer <token>
Content-Type: application/json
{
"field1": "value1",
"field2": "value2"
}Get Items
GET /items/:collection?filter[field]=value&sort=field&page=1&limit=10
Authorization: Bearer <token>Get One Item
GET /items/:collection/:id
Authorization: Bearer <token>Update Item
PATCH /items/:collection/:id
Authorization: Bearer <token>
Content-Type: application/json
{
"field1": "updated value"
}Delete Item
DELETE /items/:collection/:id
Authorization: Bearer <token>Reports and Analytics
Generate detailed reports with aggregation:
POST /reports/products
Authorization: Bearer <token>
Content-Type: application/json
{
"groupBy": ["categoryId"],
"aggregate": {
"avg_price": { "function": "avg", "field": "price" },
"product_count": { "function": "count", "field": "id" }
},
"fields": ["categoryId", "category.name", "category.description"]
}Generate multiple statistics:
POST /reports/stats
Authorization: Bearer <token>
Content-Type: application/json
{
"stats": [
{
"name": "total_products",
"collection": "products",
"query": {
"aggregate": { "count": { "function": "count", "field": "*" } }
}
},
{
"name": "orders_by_month",
"collection": "orders",
"query": {
"groupBy": ["date:month:createdAt"],
"aggregate": { "monthly_total": { "function": "sum", "field": "amount" } }
}
}
]
}File Management
Upload a file:
POST /files
Authorization: Bearer <token>
Content-Type: multipart/form-data
file: [binary data]
title: File Title
description: File descriptionGet file metadata:
GET /files/:id
Authorization: Bearer <token>Download a file:
GET /assets/:id
Authorization: Bearer <token>Tenant-Based Settings & White Labelling
Baasix supports comprehensive tenant-based settings for complete white labelling capabilities. Each tenant can have their own branding, SMTP configuration, and application settings while falling back to global defaults.
Get Settings (Public Access)
Get global settings or tenant-specific settings with automatic fallback:
GET /settingsGet settings for a specific tenant:
GET /settings?tenant_id=<tenant-uuid>For authenticated users, the system automatically detects the tenant context from the user's session.
Response Structure:
{
"data": {
"project_name": "Custom Tenant App",
"project_url": "https://tenant.example.com",
"project_color": "#ff6600",
"secondary_color": "#00ff00",
"description": "Custom tenant description",
"keywords": "tenant, custom, branding",
"from_email_name": "Tenant Mailer",
"smtp_enabled": true,
"timezone": "America/New_York",
"language": "en",
"currency": "USD",
"date_format": "MM/DD/YYYY"
}
}Note: SMTP credentials (smtp_user, smtp_pass, smtp_host, etc.) are filtered for security and not returned in API responses.
Update Settings (Admin Only)
Update global settings:
PATCH /settings
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"project_name": "My Global App",
"project_color": "#663399",
"description": "Global application description"
}Update tenant-specific settings:
PATCH /settings?tenant_id=<tenant-uuid>
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"project_name": "Custom Tenant Brand",
"project_color": "#ff0000",
"smtp_enabled": true,
"smtp_host": "smtp.tenant.com",
"smtp_user": "[email protected]",
"smtp_pass": "tenant-smtp-password",
"from_email_name": "Tenant Support"
}Tenant Branding (Public Access)
Get branding-specific information for a tenant:
GET /settings/branding?tenant_id=<tenant-uuid>Response:
{
"data": {
"project_name": "Custom Tenant Brand",
"project_color": "#ff0000",
"secondary_color": "#f0f0f0",
"description": "Tenant description",
"timezone": "UTC",
"language": "en",
"currency": "USD"
}
}Admin Tools
Test Email Configuration:
POST /settings/test-email?tenant_id=<tenant-uuid>
Authorization: Bearer <admin-token>
Content-Type: application/json
{
"email": "[email protected]"
}Reload Settings Cache:
POST /settings/reload?tenant_id=<tenant-uuid>
Authorization: Bearer <admin-token>Delete Tenant Settings:
DELETE /settings/tenant?tenant_id=<tenant-uuid>
Authorization: Bearer <admin-token>Settings Inheritance Hierarchy
The system follows a clear inheritance pattern:
- Global Settings - Base configuration for the entire application
- Tenant Overrides - Specific settings that override global values
- Automatic Fallback - Missing tenant settings automatically fall back to global values
Available Settings Fields
Core Branding:
project_name- Application/tenant nameproject_url- Primary URL for the applicationproject_color- Primary brand color (hex)secondary_color- Secondary brand color (hex)description- SEO and branding descriptionkeywords- SEO keywords
Email Configuration:
from_email_name- Display name for outgoing emailssmtp_enabled- Enable/disable tenant-specific SMTPsmtp_host- SMTP server hostnamesmtp_port- SMTP server portsmtp_secure- Use SSL/TLSsmtp_user- SMTP usernamesmtp_pass- SMTP passwordsmtp_from_address- From email address
Localization:
timezone- Default timezonelanguage- Default language codecurrency- Default currency codedate_format- Default date format
Multi-Tenant Email Configuration
Each tenant can have their own SMTP configuration:
// Mail service automatically uses tenant-specific SMTP when available
await mailService.sendMail({
to: "[email protected]",
subject: "Welcome to our platform",
templateName: "welcome",
context: { name: "John Doe" },
tenantId: "tenant-uuid-here" // Optional: specify tenant context
});The system automatically:
- Uses tenant-specific SMTP if configured and enabled
- Falls back to global SMTP configuration if tenant SMTP is not available
- Applies tenant branding to email templates
- Handles transporter caching for performance
Workflow Automation
Baasix provides a powerful visual workflow automation system with 17 node types and real-time execution monitoring.
Execute a Workflow
POST /workflows/:id/execute
Authorization: Bearer <token>
Content-Type: application/json
{
"userId": "user-id",
"data": {
"email": "[email protected]",
"action": "process"
}
}Get Workflow Execution History
GET /workflows/:id/executions?status=completed&limit=10
Authorization: Bearer <token>Trigger Workflow via Webhook
POST /workflows/webhook/:webhookId
Content-Type: application/json
{
"event": "user.created",
"data": {
"email": "[email protected]"
}
}Key Features:
- 17 Node Types: HTTP, Transform, Condition, Service, Loop, Filter, Aggregate, Delay, Notification, Email, Workflow, Stats, File, Variable, Script, Try-Catch, Trigger
- 4 Trigger Types: Manual, Webhook, Schedule (cron), Hook (on data changes)
- Template Variables: Use
{{trigger.field}},{{outputs.node-id.data}},{{variables.name}}syntax - Real-time Monitoring: Track execution progress via Socket.IO with node-level status updates
For complete workflow documentation, see Workflow Routes.
Permissions
Baasix has a robust permissions system:
POST /permissions
Authorization: Bearer <token>
Content-Type: application/json
{
"role_Id": "user-role-id",
"collection": "products",
"action": "read", // create, read, update, delete
"fields": "*", // "*" for all fields or ["field1", "field2"]
"conditions": { // Optional filtering conditions
"owner_id": {"$CURRENT_USER": "id"}
}
}Advanced Features
Data Types
Baasix supports a wide range of field types:
- Basic: String, Integer, BigInt, Decimal, Real, Double, Boolean, Text
- Date/Time: DateTime, Date
- JSON: JSON, JSONB
- IDs: UUID, TOKEN
- Special: ENUM, VIRTUAL, CiText (case-insensitive text)
- Arrays: Arrays of any primitive type
- Ranges: Integer, DateTime, Double, Decimal, and Date ranges
- Geospatial: Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection, Geography
Extensions System
Baasix has three types of extensions:
1. Hook Extensions
// extensions/baasix-hook-my-hook/index.js
export default {
id: 'my-product-hooks',
name: 'My Product Hooks',
description: 'Custom hooks for products',
events: [
{
collection: 'products',
action: 'items.create.before',
handler: async (data, context) => {
// Modify data before creation
data.createdBy = context.accountability.user?.id;
return data;
}
}
]
};2. Endpoint Extensions
// extensions/baasix-endpoint-my-api/index.js
export default {
id: 'my-custom-api',
name: 'My Custom API',
register: ({ app, services, database }) => {
app.get('/custom-endpoint', async (req, res) => {
try {
// Your custom logic
res.json({ data: { message: 'Custom endpoint response' } });
} catch (error) {
res.status(500).json({ error: { message: error.message } });
}
});
}
};3. Schedule Extensions
// extensions/baasix-schedule-my-task/index.js
export default {
id: 'daily-cleanup',
name: 'Daily Cleanup Task',
schedules: [
{
id: 'cleanup-files',
schedule: '0 0 * * *', // Run at midnight every day
handler: async (context) => {
const { database } = context;
const { Op } = database.Sequelize;
// Delete temporary files older than 7 days
const cutoffDate = new Date();
cutoffDate.setDate(cutoffDate.getDate() - 7);
await database.models.baasix_Files.destroy({
where: {
temporary: true,
createdAt: { [Op.lt]: cutoffDate }
}
});
}
}
]
};Testing
Baasix includes a comprehensive test suite. To run tests:
npm testTo run a specific test file:
npm test -- auth.test.jsDocumentation
For more comprehensive documentation, see the /documentation folder in the project root:
- Schema Reference Guide
- Item Query Reference Guide
- Authentication Routes
- Reports Routes
- Workflow Routes
- Socket.IO Integration
- Multi-tenant Guide
License
See the LICENSE file for details.
