@canxjs/blocks
v1.0.0
Published
Modular architecture support for CanxJS applications
Maintainers
Readme
@canxjs/blocks
✨ Features
- 📦 Modular Structure - Organize code into self-contained modules
- 🔄 Auto-Discovery - Automatically scan and load modules
- ⚙️ Module Configuration - Enable/disable modules via JSON config
- 🎯 Ordered Loading - Control module boot order
- 🧩 Reusable Components - Share modules across projects
📦 Installation
npm install @canxjs/blocks
# or
bun add @canxjs/blocks🚀 Quick Start
1. Register the Service Provider
// src/providers.ts
import { BlocksServiceProvider } from "@canxjs/blocks";
export const providers = [
// ... other providers
BlocksServiceProvider,
];2. Create Your First Module
node canx make:module BlogThis creates the following structure:
/modules
/Blog
module.json
/src
BlogServiceProvider.ts
/controllers
/models
/routes
api.ts
web.ts📖 Usage
Module Configuration
Each module must have a module.json file:
{
"name": "Blog",
"description": "Blog module for managing posts and comments",
"enabled": true,
"order": 1
}| Field | Type | Description |
| ------------- | ------- | ---------------------------- |
| name | string | Module identifier |
| description | string | Human-readable description |
| enabled | boolean | Whether to load this module |
| order | number | Boot order (lower = earlier) |
Module Service Provider
// modules/Blog/src/BlogServiceProvider.ts
import { ServiceProvider } from "canxjs";
export class BlogServiceProvider extends ServiceProvider {
register(): void {
// Register bindings
}
async boot(): Promise<void> {
// Bootstrap module (register routes, etc.)
}
}Module Routes
// modules/Blog/routes/api.ts
import { router } from "canxjs";
import { PostController } from "../src/controllers/PostController";
router.group({ prefix: "/api/blog" }, () => {
router.get("/posts", [PostController, "index"]);
router.post("/posts", [PostController, "store"]);
router.get("/posts/:id", [PostController, "show"]);
});Module Controllers
// modules/Blog/src/controllers/PostController.ts
import { BaseController, Controller } from "canxjs";
import { Post } from "../models/Post";
@Controller("/posts")
export class PostController extends BaseController {
async index() {
return await Post.all();
}
async store() {
const data = this.request.body;
return await Post.create(data);
}
}🔧 How It Works
Module Discovery
When your application boots:
ModuleManagerscans the/modulesdirectory- Each folder with a valid
module.jsonis registered - Modules are sorted by their
orderproperty - Only
enabled: truemodules are booted
import { ModuleManager } from "@canxjs/blocks";
const manager = new ModuleManager();
// Scan and load all modules
manager.scan();
// Boot all enabled modules
await manager.boot();
// Get all modules
const modules = manager.all();
// Find a specific module
const blogModule = manager.find("Blog");Module Class
Each discovered module is represented by a Module instance:
class Module {
name: string; // Module name
path: string; // Absolute path to module
description: string; // From module.json
enabled: boolean; // Whether active
order: number; // Boot priority
getPath(file?: string): string; // Get path within module
async boot(): Promise<void>; // Boot the module
}Folder Structure Best Practice
/modules
/Blog
module.json
/src
BlogServiceProvider.ts
/controllers
PostController.ts
CommentController.ts
/models
Post.ts
Comment.ts
/services
PostService.ts
/routes
api.ts
web.ts
/resources
/views
index.tsx
show.tsx
/tests
PostController.test.ts
/Shop
module.json
/src
...📚 API Reference
ModuleManager
| Method | Description |
| ------------ | ---------------------------------------------- |
| scan() | Scan /modules directory and register modules |
| all() | Get all registered modules (sorted by order) |
| find(name) | Get a specific module by name |
| boot() | Boot all enabled modules |
Module
| Property | Type | Description |
| ------------- | ------- | ------------------ |
| name | string | Module identifier |
| path | string | Absolute file path |
| description | string | Module description |
| enabled | boolean | Is module active |
| order | number | Boot priority |
| Method | Description |
| ---------------- | ----------------------------------- |
| getPath(file?) | Get absolute path to file in module |
| boot() | Boot this module |
💡 Benefits
1. Separation of Concerns
Keep related features together. All blog-related code lives in /modules/Blog.
2. Reusability
Copy a module folder to another project. With minimal configuration, it's ready to use.
3. Team Scalability
Different teams can work on different modules without conflicts.
4. Easy Testing
Test modules in isolation. Each module can have its own test suite.
5. Feature Flags
Disable modules in production by setting enabled: false.
📄 License
MIT © CanxJS Team
