Enterprise Application Example

A comprehensive enterprise-grade application built with MoroJS. Features modular architecture, authentication, database integration, and production-ready patterns.

Architecture Overview

This enterprise example demonstrates a real-world application with multiple modules, comprehensive testing, and production-ready configuration.

Project Structure (Functional Architecture)

typescript

1enterprise-app/
2├── src/
3│   ├── modules/
4│   │   ├── users/
5│   │   │   ├── index.ts        # Module definition
6│   │   │   ├── routes.ts       # Route handlers
7│   │   │   ├── sockets.ts      # WebSocket handlers
8│   │   │   ├── actions.ts      # Business logic
9│   │   │   └── types.ts        # Type definitions
10│   │   ├── orders/
11│   │   │   ├── index.ts
12│   │   │   ├── routes.ts
13│   │   │   ├── actions.ts
14│   │   │   └── types.ts
15│   │   ├── todos/
16│   │   │   ├── index.ts
17│   │   │   ├── routes.ts
18│   │   │   ├── actions.ts
19│   │   │   └── types.ts
20│   │   └── health/
21│   │       └── index.ts
22│   └── server.ts               # Main application
23├── package.json
24├── tsconfig.json
25└── README.md
26
27// Key Features Demonstrated:
28Functional modular architecture
29Event-driven communication
30In-memory data storage (easily replaceable)
31Comprehensive validation with Zod
32WebSocket support per module
33Versioned API endpoints (/api/v1.0.0/)
34Middleware system
35Type-safe request handling
36Clean separation of concerns
37Easy module loading/unloading
38Graceful shutdown handling
39Development-friendly logging

Enterprise Features

  • • Multi-tenant architecture
  • • Role-based access control
  • • Audit logging
  • • API versioning

Security

  • • JWT authentication
  • • Rate limiting
  • • Input validation
  • • CORS protection

Data Layer

  • • PostgreSQL with Prisma
  • • Redis caching
  • • Database migrations
  • • Connection pooling

Application Setup

Main Application Configuration (Functional Architecture)

typescript

1// src/server.ts - Enterprise Application with Functional Modules
2import { createApp } from '@morojs/moro';
3import UsersModule from './modules/users';
4import OrdersModule from './modules/orders';
5import TodosModule from './modules/todos';
6import HealthModule from './modules/health';
7
8async function createEnterpriseApp() {
9  // Use the functional createApp approach
10  const app = createApp({
11    cors: true,
12    compression: true,
13    helmet: true
14  });
15
16  // Simulated database (in real app, use MySQLAdapter)
17  const mockDatabase = {
18    users: [
19      { id: 1, name: 'John Doe', email: 'john@example.com', role: 'admin' },
20      { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'user' }
21    ],
22    orders: [
23      { id: 1, userId: 1, product: 'Laptop', amount: 999.99, status: 'completed' },
24      { id: 2, userId: 2, product: 'Mouse', amount: 29.99, status: 'pending' }
25    ],
26    todos: [
27      { id: 1, title: 'Learn MoroJS', description: 'Explore the functional module architecture', completed: false, priority: 'high' }
28    ]
29  };
30
31  // Register database
32  app.database(mockDatabase);
33
34  // Add enterprise middleware
35  app.use((req: any, res: any, next: () => void) => {
36    console.log(`[${new Date().toISOString()}] ${req.method} ${req.path}`);
37    next();
38  });
39
40  // Load enterprise modules using the functional module system
41  await app.loadModule(HealthModule);
42  await app.loadModule(UsersModule);
43  await app.loadModule(OrdersModule);
44  await app.loadModule(TodosModule);
45
46  // Root endpoint
47  app.get('/', (req, res) => {
48    return {
49      message: 'Enterprise API with Functional Modules',
50      timestamp: new Date().toISOString(),
51      modules: ['health', 'users', 'orders', 'todos'],
52      architecture: 'functional-event-driven'
53    };
54  });
55
56  // Health check endpoint
57  app.get('/health', (req, res) => {
58    return {
59      status: 'ok',
60      timestamp: new Date().toISOString(),
61      uptime: process.uptime(),
62      architecture: 'Functional Modules Active'
63    };
64  });
65
66  return app;
67}
68
69async function bootstrap() {
70  try {
71    const app = await createEnterpriseApp();
72    const port = parseInt(process.env.PORT || '3002');
73
74    app.listen(port, () => {
75      console.log('🏢 Enterprise Application Started');
76      console.log(`HTTP API: http://localhost:${port}`);
77      console.log(`WebSocket: ws://localhost:${port}`);
78      console.log('Available APIs:');
79      console.log(`  Root: http://localhost:${port}/`);
80      console.log(`  Health: http://localhost:${port}/health`);
81      console.log(`  Users:  http://localhost:${port}/api/v1.0.0/users/`);
82      console.log(`  Orders: http://localhost:${port}/api/v1.0.0/orders/`);
83      console.log(`  Todos:  http://localhost:${port}/api/v1.0.0/todos/`);
84    });
85
86    // Graceful shutdown
87    process.on('SIGTERM', () => {
88      console.log('🏢 Enterprise app shutting down gracefully...');
89      process.exit(0);
90    });
91
92  } catch (error) {
93    console.error('❌ Failed to start enterprise application:', error);
94    process.exit(1);
95  }
96}
97
98bootstrap();

Enterprise Module Example

Functional Users Module Implementation

typescript

1// modules/users/index.ts - Functional Module Architecture
2import { defineModule } from '@morojs/moro';
3import routes from './routes';
4import sockets from './sockets';
5import * as actions from './actions';
6import * as types from './types';
7
8export default defineModule({
9  name: 'users',
10  version: '1.0.0',
11  prefix: '/api/v1.0.0/users',
12  
13  // Register routes
14  routes,
15  
16  // Register WebSocket handlers
17  sockets,
18  
19  // Export module actions and types
20  actions,
21  types,
22  
23  // Module lifecycle hooks
24  onLoad: async (app) => {
25    console.log('👥 Users module loaded');
26    // Initialize any module-specific services here
27  },
28  
29  onUnload: async (app) => {
30    console.log('👥 Users module unloaded');
31  }
32});
33
34// modules/users/routes.ts - Route definitions
35import { z, validate } from '@morojs/moro';
36import * as actions from './actions';
37
38export default function registerRoutes(app: any) {
39  // GET /api/v1.0.0/users/ - List all users
40  app.get('/', (req: any, res: any) => {
41    const users = actions.getAllUsers(req.database);
42    return {
43      success: true,
44      data: users,
45      total: users.length
46    };
47  });
48
49  // GET /api/v1.0.0/users/:id - Get user by ID
50  app.get('/:id', 
51    validate({
52      params: z.object({
53        id: z.coerce.number()
54      })
55    }, (req: any, res: any) => {
56      const user = actions.getUserById(req.database, req.params.id);
57      if (!user) {
58        res.status(404);
59        return { error: 'User not found' };
60      }
61      return { success: true, data: user };
62    })
63  );
64
65  // POST /api/v1.0.0/users/ - Create new user
66  app.post('/',
67    validate({
68      body: z.object({
69        name: z.string().min(2).max(50),
70        email: z.string().email(),
71        role: z.enum(['admin', 'user']).default('user')
72      })
73    }, (req: any, res: any) => {
74      try {
75        const newUser = actions.createUser(req.database, req.body);
76        return { 
77          success: true, 
78          data: newUser,
79          message: 'User created successfully'
80        };
81      } catch (error: any) {
82        res.status(400);
83        return { error: error.message };
84      }
85    })
86  );
87
88  // PUT /api/v1.0.0/users/:id - Update user
89  app.put('/:id',
90    validate({
91      params: z.object({
92        id: z.coerce.number()
93      }),
94      body: z.object({
95        name: z.string().min(2).max(50).optional(),
96        email: z.string().email().optional(),
97        role: z.enum(['admin', 'user']).optional()
98      })
99    }, (req: any, res: any) => {
100      try {
101        const updatedUser = actions.updateUser(req.database, req.params.id, req.body);
102        if (!updatedUser) {
103          res.status(404);
104          return { error: 'User not found' };
105        }
106        return { 
107          success: true, 
108          data: updatedUser,
109          message: 'User updated successfully'
110        };
111      } catch (error: any) {
112        res.status(400);
113        return { error: error.message };
114      }
115    })
116  );
117}
118
119// modules/users/actions.ts - Business logic
120export function getAllUsers(database: any) {
121  return database.users || [];
122}
123
124export function getUserById(database: any, id: number) {
125  return database.users?.find((user: any) => user.id === id);
126}
127
128export function createUser(database: any, userData: any) {
129  // Check if email already exists
130  const existingUser = database.users?.find((u: any) => u.email === userData.email);
131  if (existingUser) {
132    throw new Error('User with this email already exists');
133  }
134
135  const newUser = {
136    id: Math.max(...database.users.map((u: any) => u.id), 0) + 1,
137    ...userData,
138    createdAt: new Date().toISOString(),
139    updatedAt: new Date().toISOString()
140  };
141
142  database.users.push(newUser);
143  return newUser;
144}
145
146export function updateUser(database: any, id: number, updateData: any) {
147  const userIndex = database.users?.findIndex((u: any) => u.id === id);
148  if (userIndex === -1) {
149    return null;
150  }
151
152  database.users[userIndex] = {
153    ...database.users[userIndex],
154    ...updateData,
155    updatedAt: new Date().toISOString()
156  };
157
158  return database.users[userIndex];
159}

Run the Example

Getting Started

typescript

1# Clone the repository
2git clone https://github.com/Moro-JS/examples.git
3cd examples/enterprise-app
4
5# Install dependencies
6npm install
7
8# Start development server (no database setup required)
9npm run dev
10
11# The application will be available at:
12# - API: http://localhost:3002
13# - Health Check: http://localhost:3002/health
14# - Users API: http://localhost:3002/api/v1.0.0/users/
15# - Orders API: http://localhost:3002/api/v1.0.0/orders/
16# - Todos API: http://localhost:3002/api/v1.0.0/todos/
17
18# Available scripts:
19npm run dev          # Start development server
20npm run build        # Build for production  
21npm run start        # Start production server
22
23# Note: This example uses functional modules with in-memory storage
24# No database setup required for basic functionality
25# Real enterprise apps would use database adapters (MySQL, PostgreSQL, etc.)

What You'll Learn

  • • Enterprise-grade application architecture
  • • Module-based code organization
  • • Authentication and authorization patterns
  • • Database design and optimization
  • • Event-driven communication
  • • Comprehensive testing strategies
  • • Production deployment patterns

Key API Endpoints

Example API Usage

typescript

1# Application Root
2GET /
3# Returns: Application info and available modules
4
5# Health Check
6GET /health
7# Returns: Application health status and uptime
8
9# User Management (Functional Module)
10GET /api/v1.0.0/users/
11# Returns: List of all users
12
13GET /api/v1.0.0/users/1
14# Returns: User details by ID
15
16POST /api/v1.0.0/users/
17{
18  "name": "John Doe",
19  "email": "john@company.com", 
20  "role": "admin"
21}
22
23PUT /api/v1.0.0/users/1
24{
25  "name": "Jane Doe",
26  "role": "user"
27}
28
29# Order Management (Functional Module)
30GET /api/v1.0.0/orders/
31# Returns: List of all orders
32
33GET /api/v1.0.0/orders/1
34# Returns: Order details by ID
35
36POST /api/v1.0.0/orders/
37{
38  "userId": 1,
39  "product": "Laptop",
40  "amount": 999.99,
41  "status": "pending"
42}
43
44# Todo Management (Functional Module)
45GET /api/v1.0.0/todos/
46# Returns: List of all todos
47
48POST /api/v1.0.0/todos/
49{
50  "title": "Learn MoroJS",
51  "description": "Explore functional modules",
52  "priority": "high"
53}
54
55# WebSocket Endpoints (per module)
56ws://localhost:3002/users     # User-related events
57ws://localhost:3002/orders    # Order-related events  
58ws://localhost:3002/todos     # Todo-related events

Next Steps