Modular architecture support for CanxJS applications
npm install @canxjs/blocks
Modular Architecture for CanxJS Applications
Enable HMVC (Hierarchical Model-View-Controller) patterns in your CanxJS apps.
Organize large applications into reusable, self-contained modules.
bash
npm install @canxjs/blocks
or
bun add @canxjs/blocks
`
---
🚀 Quick Start
$3
`typescript
// src/providers.ts
import { BlocksServiceProvider } from "@canxjs/blocks";
export const providers = [
// ... other providers
BlocksServiceProvider,
];
`
$3
`bash
node canx make:module Blog
`
This creates the following structure:
`
/modules
/Blog
module.json
/src
BlogServiceProvider.ts
/controllers
/models
/routes
api.ts
web.ts
`
---
📖 Usage
$3
Each module must have a module.json file:
`json
{
"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) |
$3
`typescript
// modules/Blog/src/BlogServiceProvider.ts
import { ServiceProvider } from "canxjs";
export class BlogServiceProvider extends ServiceProvider {
register(): void {
// Register bindings
}
async boot(): Promise {
// Bootstrap module (register routes, etc.)
}
}
`
$3
`typescript
// 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"]);
});
`
$3
`typescript
// 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
$3
When your application boots:
1. ModuleManager scans the /modules directory
2. Each folder with a valid module.json is registered
3. Modules are sorted by their order property
4. Only enabled: true modules are booted
`typescript
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");
`
$3
Each discovered module is represented by a Module instance:
`typescript
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; // Boot the module
}
`
$3
`
/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
$3
| 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 |
$3
| 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
$3
Keep related features together. All blog-related code lives in /modules/Blog.
$3
Copy a module folder to another project. With minimal configuration, it's ready to use.
$3
Different teams can work on different modules without conflicts.
$3
Test modules in isolation. Each module can have its own test suite.
$3
Disable modules in production by setting enabled: false`.