bootifyjs 0.0.3 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +321 -465
- package/dist/api.d.ts +32 -0
- package/dist/api.js +149 -0
- package/dist/api.js.map +1 -0
- package/dist/config/app.config.d.ts +29 -0
- package/dist/config/app.config.js +55 -0
- package/dist/config/app.config.js.map +1 -0
- package/dist/controllers/config.controller.d.ts +16 -0
- package/dist/controllers/config.controller.js +66 -0
- package/dist/controllers/config.controller.js.map +1 -0
- package/dist/controllers/events.controller.d.ts +66 -0
- package/dist/controllers/events.controller.js +145 -0
- package/dist/controllers/events.controller.js.map +1 -0
- package/dist/controllers/health.controller.d.ts +20 -0
- package/dist/controllers/health.controller.js +92 -0
- package/dist/controllers/health.controller.js.map +1 -0
- package/dist/controllers/user.controller.d.ts +13 -0
- package/dist/controllers/user.controller.js +209 -0
- package/dist/controllers/user.controller.js.map +1 -0
- package/dist/core/application.d.ts +21 -0
- package/dist/core/application.js +90 -0
- package/dist/core/application.js.map +1 -0
- package/dist/core/config.d.ts +3 -0
- package/dist/core/config.js +78 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/container.d.ts +17 -0
- package/dist/core/container.js +92 -0
- package/dist/core/container.js.map +1 -0
- package/dist/core/decorators.d.ts +28 -0
- package/dist/core/decorators.js +204 -0
- package/dist/core/decorators.js.map +1 -0
- package/dist/core/errors.d.ts +18 -0
- package/dist/core/errors.js +74 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/middleware.d.ts +8 -0
- package/dist/core/middleware.js +23 -0
- package/dist/core/middleware.js.map +1 -0
- package/dist/core/openapi.d.ts +80 -0
- package/dist/core/openapi.js +189 -0
- package/dist/core/openapi.js.map +1 -0
- package/dist/core/router.d.ts +32 -0
- package/dist/core/router.js +266 -0
- package/dist/core/router.js.map +1 -0
- package/dist/core/utils.d.ts +7 -0
- package/dist/core/utils.js +75 -0
- package/dist/core/utils.js.map +1 -0
- package/dist/core/validation.d.ts +15 -0
- package/dist/core/validation.js +161 -0
- package/dist/core/validation.js.map +1 -0
- package/dist/events/core/event-bus.d.ts +26 -0
- package/dist/events/core/event-bus.js +253 -0
- package/dist/events/core/event-bus.js.map +1 -0
- package/dist/events/core/event-registry.d.ts +31 -0
- package/dist/events/core/event-registry.js +170 -0
- package/dist/events/core/event-registry.js.map +1 -0
- package/dist/events/decorators/event.decorators.d.ts +11 -0
- package/dist/events/decorators/event.decorators.js +123 -0
- package/dist/events/decorators/event.decorators.js.map +1 -0
- package/dist/events/examples/system.events.d.ts +15 -0
- package/dist/events/examples/system.events.js +28 -0
- package/dist/events/examples/system.events.js.map +1 -0
- package/dist/events/examples/user.events.d.ts +68 -0
- package/dist/events/examples/user.events.js +73 -0
- package/dist/events/examples/user.events.js.map +1 -0
- package/dist/events/examples/user.handlers.d.ts +20 -0
- package/dist/events/examples/user.handlers.js +157 -0
- package/dist/events/examples/user.handlers.js.map +1 -0
- package/dist/events/index.d.ts +13 -0
- package/dist/events/index.js +71 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/middleware/logging.middleware.d.ts +7 -0
- package/dist/events/middleware/logging.middleware.js +44 -0
- package/dist/events/middleware/logging.middleware.js.map +1 -0
- package/dist/events/middleware/metrics.middleware.d.ts +11 -0
- package/dist/events/middleware/metrics.middleware.js +87 -0
- package/dist/events/middleware/metrics.middleware.js.map +1 -0
- package/dist/events/middleware/validation.middleware.d.ts +8 -0
- package/dist/events/middleware/validation.middleware.js +63 -0
- package/dist/events/middleware/validation.middleware.js.map +1 -0
- package/dist/events/store/memory-event-store.d.ts +21 -0
- package/dist/events/store/memory-event-store.js +81 -0
- package/dist/events/store/memory-event-store.js.map +1 -0
- package/dist/events/types/event.types.d.ts +57 -0
- package/dist/{decorators/cache/ICacheClient.js → events/types/event.types.js} +1 -1
- package/dist/events/types/event.types.js.map +1 -0
- package/dist/examples/basic-api.d.ts +1 -0
- package/dist/examples/basic-api.js +120 -0
- package/dist/examples/basic-api.js.map +1 -0
- package/dist/index.d.ts +17 -11
- package/dist/index.js +95 -31
- package/dist/index.js.map +1 -1
- package/dist/logging/config/logging.config.d.ts +5 -0
- package/dist/logging/config/logging.config.js +101 -0
- package/dist/logging/config/logging.config.js.map +1 -0
- package/dist/logging/core/log-context.service.d.ts +11 -0
- package/dist/logging/core/log-context.service.js +40 -0
- package/dist/logging/core/log-context.service.js.map +1 -0
- package/dist/logging/core/logger.service.d.ts +29 -0
- package/dist/logging/core/logger.service.js +178 -0
- package/dist/logging/core/logger.service.js.map +1 -0
- package/dist/logging/core/startup-logger.service.d.ts +17 -0
- package/dist/logging/core/startup-logger.service.js +156 -0
- package/dist/logging/core/startup-logger.service.js.map +1 -0
- package/dist/logging/decorators/log.decorator.d.ts +11 -0
- package/dist/logging/decorators/log.decorator.js +80 -0
- package/dist/logging/decorators/log.decorator.js.map +1 -0
- package/dist/logging/index.d.ts +15 -0
- package/dist/logging/index.js +46 -0
- package/dist/logging/index.js.map +1 -0
- package/dist/logging/middleware/context.middleware.d.ts +2 -0
- package/dist/logging/middleware/context.middleware.js +29 -0
- package/dist/logging/middleware/context.middleware.js.map +1 -0
- package/dist/logging/middleware/request-logging.middleware.d.ts +3 -0
- package/dist/logging/middleware/request-logging.middleware.js +78 -0
- package/dist/logging/middleware/request-logging.middleware.js.map +1 -0
- package/dist/logging/types/logging.types.d.ts +79 -0
- package/dist/{decorators/transaction/IDatabaseClient.js → logging/types/logging.types.js} +1 -1
- package/dist/logging/types/logging.types.js.map +1 -0
- package/dist/middlewares/auth.middleware.d.ts +2 -0
- package/dist/middlewares/auth.middleware.js +20 -0
- package/dist/middlewares/auth.middleware.js.map +1 -0
- package/dist/middlewares/cors.middleware.d.ts +2 -0
- package/dist/middlewares/cors.middleware.js +16 -0
- package/dist/middlewares/cors.middleware.js.map +1 -0
- package/dist/middlewares/swagger.middleware.d.ts +6 -0
- package/dist/middlewares/swagger.middleware.js +84 -0
- package/dist/middlewares/swagger.middleware.js.map +1 -0
- package/dist/repositories/user.repository.d.ts +16 -0
- package/dist/repositories/user.repository.js +110 -0
- package/dist/repositories/user.repository.js.map +1 -0
- package/dist/schemas/user.schemas.d.ts +214 -0
- package/dist/schemas/user.schemas.js +71 -0
- package/dist/schemas/user.schemas.js.map +1 -0
- package/dist/services/config-demo.service.d.ts +10 -0
- package/dist/services/config-demo.service.js +88 -0
- package/dist/services/config-demo.service.js.map +1 -0
- package/dist/services/user.service.d.ts +21 -0
- package/dist/services/user.service.js +201 -0
- package/dist/services/user.service.js.map +1 -0
- package/package.json +49 -14
- package/dist/application/Application.d.ts +0 -43
- package/dist/application/Application.d.ts.map +0 -1
- package/dist/application/Application.js +0 -283
- package/dist/application/Application.js.map +0 -1
- package/dist/container/container.d.ts +0 -9
- package/dist/container/container.d.ts.map +0 -1
- package/dist/container/container.js +0 -23
- package/dist/container/container.js.map +0 -1
- package/dist/decorators/cache/ICacheClient.d.ts +0 -6
- package/dist/decorators/cache/ICacheClient.d.ts.map +0 -1
- package/dist/decorators/cache/ICacheClient.js.map +0 -1
- package/dist/decorators/cache/cache.decorator.d.ts +0 -2
- package/dist/decorators/cache/cache.decorator.d.ts.map +0 -1
- package/dist/decorators/cache/cache.decorator.js +0 -38
- package/dist/decorators/cache/cache.decorator.js.map +0 -1
- package/dist/decorators/controller.decorator.d.ts +0 -9
- package/dist/decorators/controller.decorator.d.ts.map +0 -1
- package/dist/decorators/controller.decorator.js +0 -99
- package/dist/decorators/controller.decorator.js.map +0 -1
- package/dist/decorators/http.decorator.d.ts +0 -7
- package/dist/decorators/http.decorator.d.ts.map +0 -1
- package/dist/decorators/http.decorator.js +0 -26
- package/dist/decorators/http.decorator.js.map +0 -1
- package/dist/decorators/timing.decorator.d.ts +0 -2
- package/dist/decorators/timing.decorator.d.ts.map +0 -1
- package/dist/decorators/timing.decorator.js +0 -26
- package/dist/decorators/timing.decorator.js.map +0 -1
- package/dist/decorators/transaction/IDatabaseClient.d.ts +0 -9
- package/dist/decorators/transaction/IDatabaseClient.d.ts.map +0 -1
- package/dist/decorators/transaction/IDatabaseClient.js.map +0 -1
- package/dist/decorators/transaction/transactional.decorator.d.ts +0 -2
- package/dist/decorators/transaction/transactional.decorator.d.ts.map +0 -1
- package/dist/decorators/transaction/transactional.decorator.js +0 -27
- package/dist/decorators/transaction/transactional.decorator.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/logger/Logger.d.ts +0 -37
- package/dist/logger/Logger.d.ts.map +0 -1
- package/dist/logger/Logger.js +0 -142
- package/dist/logger/Logger.js.map +0 -1
- package/dist/middleware/http.d.ts +0 -2
- package/dist/middleware/http.d.ts.map +0 -1
- package/dist/middleware/http.js +0 -80
- package/dist/middleware/http.js.map +0 -1
- package/dist/middleware/requestcontext.d.ts +0 -12
- package/dist/middleware/requestcontext.d.ts.map +0 -1
- package/dist/middleware/requestcontext.js +0 -6
- package/dist/middleware/requestcontext.js.map +0 -1
package/README.md
CHANGED
@@ -1,567 +1,423 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
A production-ready, Spring Boot-inspired TypeScript framework built on top of Fastify and express, designed for building scalable enterprise applications with modern development practices.
|
4
|
-
|
5
|
-
## 🎯 Why This Framework?
|
6
|
-
|
7
|
-
### The Problem
|
8
|
-
Building enterprise-grade Node.js applications often involves:
|
9
|
-
- ⚡ Repetitive boilerplate code for common patterns
|
10
|
-
- 🔧 Manual setup of logging, caching, validation, and error handling
|
11
|
-
- 📦 Inconsistent project structure across teams
|
12
|
-
- 🏗️ Lack of standardized dependency injection
|
13
|
-
- 🔄 Manual configuration of database connections and migrations
|
14
|
-
- 📊 Missing observability and monitoring out-of-the-box
|
15
|
-
|
16
|
-
### The Solution
|
17
|
-
Our framework provides:
|
18
|
-
- 🎨 **Spring Boot-style decorators** (`@Controller`, `@Service`, `@Repository`)
|
19
|
-
- 🏗️ **Dependency Injection** with Inversify
|
20
|
-
- 🚀 **High-performance** Fastify web server
|
21
|
-
- 📊 **Built-in observability** (logging, metrics, tracing)
|
22
|
-
- 💾 **Integrated caching** with Redis
|
23
|
-
- 🗄️ **Database abstraction** with Sequelize ORM
|
24
|
-
- 🔧 **Zero-config setup** for common enterprise patterns
|
25
|
-
- 📦 **Monorepo structure** for scalable team development
|
26
|
-
|
27
|
-
## 🏗️ Architecture Overview
|
1
|
+
# BootifyJS
|
28
2
|
|
29
|
-
|
30
|
-
┌─────────────────────────────────────────────────────────────┐
|
31
|
-
│ Application Layer │
|
32
|
-
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
|
33
|
-
│ │ CMS APIs │ │ Consumer APIs │ │ Admin APIs │ │
|
34
|
-
│ │ @Controller │ │ @Controller │ │ @Controller │ │
|
35
|
-
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
|
36
|
-
└─────────────────────────────────────────────────────────────┘
|
37
|
-
┌─────────────────────────────────────────────────────────────┐
|
38
|
-
│ Service Layer │
|
39
|
-
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
|
40
|
-
│ │ UserService │ │ OrderService │ │ EmailService │ │
|
41
|
-
│ │ @Service │ │ @Service │ │ @Service │ │
|
42
|
-
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
|
43
|
-
└─────────────────────────────────────────────────────────────┘
|
44
|
-
┌─────────────────────────────────────────────────────────────┐
|
45
|
-
│ Repository Layer │
|
46
|
-
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
|
47
|
-
│ │ UserRepository │ │ OrderRepository │ │EmailTemplate │ │
|
48
|
-
│ │ @Repository │ │ @Repository │ │ @Repository │ │
|
49
|
-
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
|
50
|
-
└─────────────────────────────────────────────────────────────┘
|
51
|
-
┌─────────────────────────────────────────────────────────────┐
|
52
|
-
│ Core Framework │
|
53
|
-
│ Fastify + Decorators + DI + Caching + Logging │
|
54
|
-
└─────────────────────────────────────────────────────────────┘
|
55
|
-
```
|
56
|
-
|
57
|
-
## 📦 Package Structure
|
58
|
-
|
59
|
-
### `core` - Framework Foundation
|
60
|
-
- 🎯 **Application bootstrapping** with configurable features
|
61
|
-
- 🏗️ **Dependency injection** container with decorators
|
62
|
-
- 🌐 **HTTP decorators** (`@Get`, `@Post`, `@Put`, `@Delete`)
|
63
|
-
- ⚡ **Performance decorators** (`@Timed`, `@Cache`)
|
64
|
-
- 📊 **Structured logging** (Application, Audit, Event logs)
|
65
|
-
- 🔄 **Transaction management** with `@Transactional`
|
66
|
-
|
67
|
-
### `commons` - Shared Components
|
68
|
-
- 🗄️ **Database clients** (Sequelize, Redis)
|
69
|
-
- 📋 **Base repository** with caching and pagination
|
70
|
-
- 🔧 **Database migrations** and seeders
|
71
|
-
- 🏷️ **Shared models** and interfaces
|
72
|
-
|
73
|
-
### `@monorepo/cms-apis` - Example Application
|
74
|
-
- 🎮 **Controllers** using framework decorators
|
75
|
-
- 💼 **Business logic** with service layer
|
76
|
-
- 📊 **Complete CRUD** operations with caching
|
77
|
-
|
78
|
-
## 🚀 Quick Start
|
79
|
-
|
80
|
-
### Prerequisites
|
81
|
-
- Node.js 18+
|
82
|
-
- PostgreSQL 12+
|
83
|
-
- Redis 6+ (optional, for caching)
|
84
|
-
|
85
|
-
### Installation
|
3
|
+
A Spring Boot inspired Node.js framework with TypeScript, Dependency Injection, and Validation.
|
86
4
|
|
87
|
-
|
88
|
-
# Clone the repository
|
89
|
-
git clone <repository-url>
|
90
|
-
cd typescript-fastify-framework
|
91
|
-
|
92
|
-
# Install dependencies for all packages
|
93
|
-
npm install
|
5
|
+
## Features
|
94
6
|
|
95
|
-
|
96
|
-
|
97
|
-
|
7
|
+
- **Dependency Injection**: Automatic constructor injection with `@Injectable`, `@Service`, and `@Repository` decorators
|
8
|
+
- **REST API**: Easy controller definition with `@Controller`, `@Get`, `@Post`, etc.
|
9
|
+
- **Validation**: Request validation with Zod schemas
|
10
|
+
- **Configuration**: Environment-based configuration with automatic mapping
|
11
|
+
- **OpenAPI**: Automatic OpenAPI documentation generation
|
12
|
+
- **Logging**: Comprehensive logging system with context tracking
|
13
|
+
- **Event System**: Type-safe event system with middleware support
|
98
14
|
|
99
|
-
|
15
|
+
## Installation
|
100
16
|
|
101
17
|
```bash
|
102
|
-
|
103
|
-
cp packages/cms-apis/.env.example packages/cms-apis/.env
|
104
|
-
|
105
|
-
# Edit with your configuration
|
106
|
-
nano packages/cms-apis/.env
|
18
|
+
npm install bootifyjs
|
107
19
|
```
|
108
20
|
|
109
|
-
|
21
|
+
## Quick Start
|
110
22
|
|
111
|
-
```
|
112
|
-
|
113
|
-
cd packages/commons
|
114
|
-
|
115
|
-
# Create database
|
116
|
-
npm run db:create
|
23
|
+
```typescript
|
24
|
+
import { createBootifyApp, Controller, Get, Service } from 'bootifyjs';
|
117
25
|
|
118
|
-
|
119
|
-
|
26
|
+
@Service()
|
27
|
+
class GreetingService {
|
28
|
+
getGreeting(name: string) {
|
29
|
+
return `Hello, ${name}!`;
|
30
|
+
}
|
31
|
+
}
|
120
32
|
|
121
|
-
|
122
|
-
|
123
|
-
|
33
|
+
@Controller('/api')
|
34
|
+
class GreetingController {
|
35
|
+
constructor(private greetingService: GreetingService) {}
|
36
|
+
|
37
|
+
@Get('/hello')
|
38
|
+
sayHello() {
|
39
|
+
return { message: this.greetingService.getGreeting('World') };
|
40
|
+
}
|
41
|
+
}
|
124
42
|
|
125
|
-
|
43
|
+
async function main() {
|
44
|
+
const { start } = await createBootifyApp({
|
45
|
+
port: 3000,
|
46
|
+
controllers: [GreetingController],
|
47
|
+
enableSwagger: true
|
48
|
+
});
|
49
|
+
|
50
|
+
await start();
|
51
|
+
console.log('Server running at http://localhost:3000');
|
52
|
+
}
|
126
53
|
|
127
|
-
|
128
|
-
# From root directory
|
129
|
-
npm run dev
|
54
|
+
main().catch(console.error);
|
130
55
|
```
|
131
56
|
|
132
|
-
|
57
|
+
## Core Concepts
|
133
58
|
|
134
|
-
|
59
|
+
### Controllers
|
135
60
|
|
136
|
-
|
61
|
+
Controllers handle HTTP requests and define your API endpoints.
|
137
62
|
|
138
63
|
```typescript
|
139
|
-
import { Controller, Get, Post, Put, Delete } from '
|
140
|
-
import { inject } from 'inversify';
|
64
|
+
import { Controller, Get, Post, Put, Delete, Param, Body, Query } from 'bootifyjs';
|
141
65
|
|
142
|
-
@Controller('/
|
66
|
+
@Controller('/users')
|
143
67
|
export class UserController {
|
144
|
-
constructor(
|
145
|
-
|
146
|
-
) {}
|
147
|
-
|
68
|
+
constructor(private userService: UserService) {}
|
69
|
+
|
148
70
|
@Get('/')
|
149
|
-
|
150
|
-
return this.userService.
|
71
|
+
getAllUsers(@Query('limit') limit?: string) {
|
72
|
+
return this.userService.getAllUsers(limit ? parseInt(limit) : undefined);
|
151
73
|
}
|
152
|
-
|
153
|
-
@
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
74
|
+
|
75
|
+
@Get('/:id')
|
76
|
+
getUserById(@Param('id') id: string) {
|
77
|
+
return this.userService.getUserById(id);
|
78
|
+
}
|
79
|
+
|
80
|
+
@Post('/')
|
81
|
+
createUser(@Body() userData: CreateUserDto) {
|
82
|
+
return this.userService.createUser(userData);
|
83
|
+
}
|
84
|
+
|
85
|
+
@Put('/:id')
|
86
|
+
updateUser(@Param('id') id: string, @Body() userData: UpdateUserDto) {
|
87
|
+
return this.userService.updateUser(id, userData);
|
88
|
+
}
|
89
|
+
|
90
|
+
@Delete('/:id')
|
91
|
+
deleteUser(@Param('id') id: string) {
|
92
|
+
return this.userService.deleteUser(id);
|
168
93
|
}
|
169
94
|
}
|
170
95
|
```
|
171
96
|
|
172
|
-
###
|
97
|
+
### Services
|
98
|
+
|
99
|
+
Services contain your business logic and can be injected into controllers or other services.
|
173
100
|
|
174
101
|
```typescript
|
175
|
-
import { Service
|
176
|
-
import { inject } from 'inversify';
|
102
|
+
import { Service } from 'bootifyjs';
|
177
103
|
|
178
|
-
@Service(
|
104
|
+
@Service()
|
179
105
|
export class UserService {
|
180
|
-
constructor(
|
181
|
-
|
182
|
-
) {
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
// Business logic here
|
189
|
-
const user = await this.userRepository.create(userData);
|
190
|
-
|
191
|
-
// Audit logging
|
192
|
-
AuditLogger.info({
|
193
|
-
userId: 'system',
|
194
|
-
action: 'CREATE_USER',
|
195
|
-
resources: ['users'],
|
196
|
-
data: { userId: user.id, email: user.email }
|
197
|
-
});
|
198
|
-
|
199
|
-
return user;
|
106
|
+
constructor(private userRepository: UserRepository) {}
|
107
|
+
|
108
|
+
getAllUsers(limit?: number) {
|
109
|
+
return this.userRepository.findAll(limit);
|
110
|
+
}
|
111
|
+
|
112
|
+
getUserById(id: string) {
|
113
|
+
return this.userRepository.findById(id);
|
200
114
|
}
|
115
|
+
|
116
|
+
// More methods...
|
201
117
|
}
|
202
118
|
```
|
203
119
|
|
204
|
-
###
|
120
|
+
### Repositories
|
205
121
|
|
206
|
-
|
207
|
-
import { Repository, AppRepository } from '@monorepo/core';
|
208
|
-
|
209
|
-
@Repository('singleton')
|
210
|
-
export class UserRepository extends AppRepository<User> {
|
211
|
-
constructor() {
|
212
|
-
super(User, {
|
213
|
-
cacheTTL: 3600, // 1 hour cache
|
214
|
-
defaultFields: ['id', 'email', 'firstName', 'lastName', 'isActive']
|
215
|
-
});
|
216
|
-
}
|
122
|
+
Repositories handle data access and can be injected into services.
|
217
123
|
|
218
|
-
|
219
|
-
|
220
|
-
|
124
|
+
```typescript
|
125
|
+
import { Repository } from 'bootifyjs';
|
126
|
+
|
127
|
+
@Repository()
|
128
|
+
export class UserRepository {
|
129
|
+
private users = []; // In a real app, this would be a database connection
|
130
|
+
|
131
|
+
findAll(limit?: number) {
|
132
|
+
if (limit) {
|
133
|
+
return this.users.slice(0, limit);
|
134
|
+
}
|
135
|
+
return this.users;
|
221
136
|
}
|
222
|
-
|
223
|
-
|
224
|
-
return this.
|
137
|
+
|
138
|
+
findById(id: string) {
|
139
|
+
return this.users.find(user => user.id === id);
|
225
140
|
}
|
141
|
+
|
142
|
+
// More methods...
|
226
143
|
}
|
227
144
|
```
|
228
145
|
|
229
|
-
###
|
146
|
+
### Validation
|
147
|
+
|
148
|
+
Use Zod schemas to validate request data.
|
230
149
|
|
231
150
|
```typescript
|
232
|
-
import {
|
233
|
-
|
234
|
-
const app = new Application({
|
235
|
-
port: 3000,
|
236
|
-
enableCors: true,
|
237
|
-
enableSwagger: true,
|
238
|
-
enableMetrics: true,
|
239
|
-
corsOptions: {
|
240
|
-
origin: ['http://localhost:3000', 'https://yourdomain.com'],
|
241
|
-
credentials: true
|
242
|
-
}
|
243
|
-
});
|
151
|
+
import { z } from 'zod';
|
152
|
+
import { Controller, Post, Body, ValidateBody } from 'bootifyjs';
|
244
153
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
]);
|
154
|
+
const createUserSchema = z.object({
|
155
|
+
email: z.string().email(),
|
156
|
+
name: z.string().min(2).max(100),
|
157
|
+
age: z.number().min(18).optional()
|
158
|
+
});
|
251
159
|
|
252
|
-
|
160
|
+
@Controller('/users')
|
161
|
+
export class UserController {
|
162
|
+
@Post('/')
|
163
|
+
@ValidateBody(createUserSchema)
|
164
|
+
createUser(@Body() userData: z.infer<typeof createUserSchema>) {
|
165
|
+
// userData is now validated and typed
|
166
|
+
return this.userService.createUser(userData);
|
167
|
+
}
|
168
|
+
}
|
253
169
|
```
|
254
170
|
|
255
|
-
|
171
|
+
### Configuration
|
256
172
|
|
257
|
-
|
173
|
+
Define your configuration structure and automatically map environment variables.
|
258
174
|
|
259
175
|
```typescript
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
176
|
+
import { Config, getConfigInstance } from 'bootifyjs';
|
177
|
+
|
178
|
+
@Config('APP')
|
179
|
+
export class AppConfig {
|
180
|
+
SERVICE_NAME: string = 'my-service';
|
181
|
+
|
182
|
+
server: {
|
183
|
+
port: number;
|
184
|
+
host: string;
|
185
|
+
} = {
|
186
|
+
port: 3000,
|
187
|
+
host: 'localhost'
|
188
|
+
};
|
189
|
+
|
190
|
+
database: {
|
191
|
+
url: string;
|
192
|
+
poolSize: number;
|
193
|
+
} = {
|
194
|
+
url: 'postgres://localhost:5432/mydb',
|
195
|
+
poolSize: 10
|
196
|
+
};
|
272
197
|
}
|
273
|
-
```
|
274
|
-
|
275
|
-
### Environment Variables
|
276
198
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
DB_USER=postgres
|
281
|
-
DB_PASS=password
|
282
|
-
DB_HOST=localhost
|
283
|
-
DB_PORT=5432
|
284
|
-
DB_DIALECT=postgres
|
285
|
-
|
286
|
-
# Redis Configuration (optional)
|
287
|
-
REDIS_HOST=localhost
|
288
|
-
REDIS_PORT=6379
|
289
|
-
REDIS_PASSWORD=
|
290
|
-
|
291
|
-
# Application Configuration
|
292
|
-
APP_PORT=3000
|
293
|
-
NODE_ENV=development
|
294
|
-
LOG_LEVEL=info
|
199
|
+
// Environment variables like APP_SERVER_PORT=8080 will be automatically mapped
|
200
|
+
const config = getConfigInstance(AppConfig);
|
201
|
+
console.log(config.server.port); // 8080
|
295
202
|
```
|
296
203
|
|
297
|
-
|
298
|
-
|
299
|
-
### Automatic API Documentation
|
300
|
-
Visit `http://localhost:3000/docs` when `enableSwagger: true`
|
204
|
+
### Event System
|
301
205
|
|
302
|
-
|
303
|
-
- `GET /health` - Application health
|
304
|
-
- `GET /health/ready` - Readiness probe
|
206
|
+
Create a type-safe event system for decoupled communication.
|
305
207
|
|
306
|
-
### Metrics & Monitoring
|
307
|
-
- `GET /metrics` - Prometheus metrics (when enabled)
|
308
|
-
- Automatic request timing and counting
|
309
|
-
- Error rate monitoring
|
310
|
-
|
311
|
-
### Structured Logging
|
312
208
|
```typescript
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
data: { orderId: 'order456' }
|
322
|
-
});
|
323
|
-
|
324
|
-
// Event logs
|
325
|
-
EventLogger.info({
|
326
|
-
eventName: 'USER_SIGNUP',
|
327
|
-
status: 'SUCCESS',
|
328
|
-
metadata: { source: 'web', campaign: 'summer2024' }
|
329
|
-
});
|
330
|
-
```
|
331
|
-
|
332
|
-
## 🎯 Available APIs (CMS Example)
|
333
|
-
|
334
|
-
### User Management
|
335
|
-
```bash
|
336
|
-
# Get all users
|
337
|
-
GET /api/users
|
338
|
-
|
339
|
-
# Get user by ID
|
340
|
-
GET /api/users/:id
|
341
|
-
|
342
|
-
# Get user by email
|
343
|
-
GET /api/users/email/:email
|
344
|
-
|
345
|
-
# Create user
|
346
|
-
POST /api/users
|
347
|
-
{
|
348
|
-
"email": "john@example.com",
|
349
|
-
"firstName": "John",
|
350
|
-
"lastName": "Doe"
|
209
|
+
import { Event, EventEmitter, EventListener, EventHandler } from 'bootifyjs';
|
210
|
+
|
211
|
+
// Define an event
|
212
|
+
@Event('user.created')
|
213
|
+
class UserCreatedEvent {
|
214
|
+
id: string;
|
215
|
+
email: string;
|
216
|
+
timestamp: Date = new Date();
|
351
217
|
}
|
352
218
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
219
|
+
// Emit events from services
|
220
|
+
@Service()
|
221
|
+
@EventEmitter()
|
222
|
+
class UserService {
|
223
|
+
private eventBus; // Injected by @EventEmitter
|
224
|
+
|
225
|
+
async createUser(userData) {
|
226
|
+
const user = await this.userRepository.create(userData);
|
227
|
+
|
228
|
+
// Emit event
|
229
|
+
await this.eventBus.emit('user.created', {
|
230
|
+
id: user.id,
|
231
|
+
email: user.email
|
232
|
+
});
|
233
|
+
|
234
|
+
return user;
|
235
|
+
}
|
357
236
|
}
|
358
237
|
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
### System Health
|
370
|
-
```bash
|
371
|
-
# Health check
|
372
|
-
GET /health
|
373
|
-
|
374
|
-
# Readiness check
|
375
|
-
GET /health/ready
|
376
|
-
|
377
|
-
# Metrics (if enabled)
|
378
|
-
GET /metrics
|
238
|
+
// Handle events
|
239
|
+
@EventListener()
|
240
|
+
class UserEventHandlers {
|
241
|
+
@EventHandler('user.created')
|
242
|
+
async onUserCreated(event: UserCreatedEvent) {
|
243
|
+
console.log(`User created: ${event.email}`);
|
244
|
+
// Send welcome email, update analytics, etc.
|
245
|
+
}
|
246
|
+
}
|
379
247
|
```
|
380
248
|
|
381
|
-
|
249
|
+
### Logging
|
382
250
|
|
383
|
-
|
251
|
+
Comprehensive logging system with context tracking.
|
384
252
|
|
385
|
-
1. **Create Model** (if needed)
|
386
253
|
```typescript
|
387
|
-
|
388
|
-
export class Product extends Model {
|
389
|
-
public id!: number;
|
390
|
-
public name!: string;
|
391
|
-
public price!: number;
|
392
|
-
}
|
393
|
-
```
|
254
|
+
import { Logger, Log } from 'bootifyjs';
|
394
255
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
@
|
399
|
-
|
400
|
-
|
401
|
-
|
256
|
+
@Service()
|
257
|
+
@Logger('UserService')
|
258
|
+
export class UserService {
|
259
|
+
private logger; // Injected by @Logger
|
260
|
+
|
261
|
+
@Log({ logArgs: true, logDuration: true })
|
262
|
+
async createUser(userData) {
|
263
|
+
this.logger.info('Creating new user', { email: userData.email });
|
264
|
+
|
265
|
+
// Business logic...
|
266
|
+
|
267
|
+
this.logger.info('User created successfully');
|
268
|
+
return user;
|
402
269
|
}
|
403
270
|
}
|
404
271
|
```
|
405
272
|
|
406
|
-
|
407
|
-
```typescript
|
408
|
-
// packages/commons/src/services/ProductService.ts
|
409
|
-
@Service('singleton')
|
410
|
-
export class ProductService {
|
411
|
-
constructor(
|
412
|
-
@inject(ProductRepository) private productRepo: ProductRepository
|
413
|
-
) {}
|
414
|
-
|
415
|
-
@Timed()
|
416
|
-
async createProduct(data: CreateProductData): Promise<Product> {
|
417
|
-
return this.productRepo.create(data);
|
418
|
-
}
|
419
|
-
}
|
420
|
-
```
|
273
|
+
## Bootstrapping Your Application
|
421
274
|
|
422
|
-
|
423
|
-
```typescript
|
424
|
-
// packages/cms-apis/src/controllers/ProductController.ts
|
425
|
-
@Controller('/api/products')
|
426
|
-
export class ProductController {
|
427
|
-
constructor(
|
428
|
-
@inject(ProductService) private productService: ProductService
|
429
|
-
) {}
|
275
|
+
There are two ways to bootstrap your application:
|
430
276
|
|
431
|
-
|
432
|
-
async createProduct(request: FastifyRequest) {
|
433
|
-
return this.productService.createProduct(request.body);
|
434
|
-
}
|
435
|
-
}
|
436
|
-
```
|
277
|
+
### 1. Using createBootifyApp (Recommended)
|
437
278
|
|
438
|
-
5. **Register Controller**
|
439
279
|
```typescript
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
280
|
+
import { createBootifyApp } from 'bootifyjs';
|
281
|
+
import { UserController } from './controllers/user.controller';
|
282
|
+
|
283
|
+
async function main() {
|
284
|
+
const { app, start, stop } = await createBootifyApp({
|
285
|
+
port: 3000,
|
286
|
+
controllers: [UserController],
|
287
|
+
enableSwagger: true,
|
288
|
+
enableCors: true
|
289
|
+
});
|
290
|
+
|
291
|
+
await start();
|
292
|
+
console.log('Server running at http://localhost:3000');
|
293
|
+
console.log('API docs available at http://localhost:3000/api-docs');
|
294
|
+
}
|
295
|
+
|
296
|
+
main().catch(console.error);
|
446
297
|
```
|
447
298
|
|
448
|
-
|
299
|
+
### 2. Manual Bootstrap
|
449
300
|
|
450
|
-
```
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
301
|
+
```typescript
|
302
|
+
import {
|
303
|
+
Application,
|
304
|
+
configureLogging,
|
305
|
+
configureEventSystem,
|
306
|
+
corsMiddleware,
|
307
|
+
contextMiddleware,
|
308
|
+
createRequestLoggingMiddleware,
|
309
|
+
swaggerMiddleware,
|
310
|
+
OpenAPIGenerator
|
311
|
+
} from 'bootifyjs';
|
312
|
+
import { UserController } from './controllers/user.controller';
|
313
|
+
|
314
|
+
async function bootstrap() {
|
315
|
+
// Initialize logging
|
316
|
+
const { logger, startupLogger } = configureLogging();
|
317
|
+
|
318
|
+
// Initialize event system
|
319
|
+
const eventBus = configureEventSystem();
|
320
|
+
|
321
|
+
// Generate OpenAPI documentation
|
322
|
+
const openApiGenerator = new OpenAPIGenerator({
|
323
|
+
title: 'My API',
|
324
|
+
version: '1.0.0',
|
325
|
+
description: 'My API description'
|
326
|
+
});
|
327
|
+
|
328
|
+
const controllers = [UserController];
|
329
|
+
openApiGenerator.addControllers(controllers);
|
330
|
+
const openApiSpec = openApiGenerator.getSpec();
|
331
|
+
|
332
|
+
// Create application
|
333
|
+
const app = new Application({
|
334
|
+
controllers,
|
335
|
+
middlewares: [
|
336
|
+
contextMiddleware,
|
337
|
+
corsMiddleware,
|
338
|
+
createRequestLoggingMiddleware(),
|
339
|
+
swaggerMiddleware(openApiSpec)
|
340
|
+
],
|
341
|
+
port: 3000,
|
342
|
+
hostname: 'localhost'
|
343
|
+
});
|
344
|
+
|
345
|
+
await app.start();
|
346
|
+
logger.info('Server started');
|
347
|
+
}
|
456
348
|
|
457
|
-
|
458
|
-
npm run test:watch
|
349
|
+
bootstrap().catch(console.error);
|
459
350
|
```
|
460
351
|
|
461
|
-
##
|
352
|
+
## Middleware
|
462
353
|
|
463
|
-
|
464
|
-
```bash
|
465
|
-
npm run dev
|
466
|
-
```
|
354
|
+
Create custom middleware to handle cross-cutting concerns.
|
467
355
|
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
356
|
+
```typescript
|
357
|
+
import { Middleware } from 'bootifyjs';
|
358
|
+
|
359
|
+
export const loggingMiddleware: Middleware = async (req, res, next) => {
|
360
|
+
const start = Date.now();
|
361
|
+
console.log(`${req.method} ${req.url} - Request started`);
|
362
|
+
|
363
|
+
await next();
|
364
|
+
|
365
|
+
const duration = Date.now() - start;
|
366
|
+
console.log(`${req.method} ${req.url} - Request completed in ${duration}ms`);
|
367
|
+
};
|
472
368
|
```
|
473
369
|
|
474
|
-
|
475
|
-
```dockerfile
|
476
|
-
FROM node:18-alpine
|
477
|
-
WORKDIR /app
|
478
|
-
COPY package*.json ./
|
479
|
-
RUN npm ci --only=production
|
480
|
-
COPY dist/ ./dist/
|
481
|
-
EXPOSE 3000
|
482
|
-
CMD ["npm", "start"]
|
483
|
-
```
|
370
|
+
## OpenAPI Documentation
|
484
371
|
|
485
|
-
|
372
|
+
BootifyJS automatically generates OpenAPI documentation for your API.
|
486
373
|
|
487
|
-
### Custom Decorators
|
488
374
|
```typescript
|
489
|
-
|
490
|
-
export function ValidateUser(): MethodDecorator {
|
491
|
-
return (target, propertyKey, descriptor) => {
|
492
|
-
// Custom validation logic
|
493
|
-
};
|
494
|
-
}
|
375
|
+
import { Controller, Get, ApiTags, ApiOperation, ApiResponse } from 'bootifyjs';
|
495
376
|
|
496
|
-
|
497
|
-
@
|
498
|
-
export class
|
499
|
-
@
|
500
|
-
@
|
501
|
-
|
502
|
-
|
377
|
+
@Controller('/health')
|
378
|
+
@ApiTags('Health')
|
379
|
+
export class HealthController {
|
380
|
+
@Get('/')
|
381
|
+
@ApiOperation({
|
382
|
+
summary: 'Health check',
|
383
|
+
description: 'Check if the API is running'
|
384
|
+
})
|
385
|
+
@ApiResponse(200, {
|
386
|
+
description: 'API is healthy',
|
387
|
+
schema: healthResponseSchema
|
388
|
+
})
|
389
|
+
health() {
|
390
|
+
return { status: 'OK', timestamp: new Date().toISOString() };
|
503
391
|
}
|
504
392
|
}
|
505
393
|
```
|
506
394
|
|
507
|
-
|
508
|
-
```typescript
|
509
|
-
const app = new Application({
|
510
|
-
// ... other config
|
511
|
-
});
|
395
|
+
## Error Handling
|
512
396
|
|
513
|
-
|
514
|
-
app.getServer().addHook('preHandler', async (request, reply) => {
|
515
|
-
// Custom logic before request handling
|
516
|
-
});
|
517
|
-
```
|
397
|
+
BootifyJS provides built-in error classes for common HTTP errors.
|
518
398
|
|
519
|
-
### Database Transactions
|
520
399
|
```typescript
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
const
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
400
|
+
import { NotFoundError, ValidationError } from 'bootifyjs';
|
401
|
+
|
402
|
+
@Service()
|
403
|
+
export class UserService {
|
404
|
+
getUserById(id: string) {
|
405
|
+
const user = this.userRepository.findById(id);
|
406
|
+
if (!user) {
|
407
|
+
throw new NotFoundError(`User with id ${id} not found`);
|
408
|
+
}
|
409
|
+
return user;
|
410
|
+
}
|
411
|
+
|
412
|
+
createUser(userData) {
|
413
|
+
if (!userData.email) {
|
414
|
+
throw new ValidationError('Email is required');
|
415
|
+
}
|
416
|
+
// ...
|
532
417
|
}
|
533
418
|
}
|
534
419
|
```
|
535
420
|
|
536
|
-
##
|
537
|
-
|
538
|
-
1. Fork the repository
|
539
|
-
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
540
|
-
3. Commit your changes (`git commit -m 'Add amazing feature'`)
|
541
|
-
4. Push to the branch (`git push origin feature/amazing-feature`)
|
542
|
-
5. Open a Pull Request
|
543
|
-
|
544
|
-
## 📄 License
|
545
|
-
|
546
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
547
|
-
|
548
|
-
## 🆘 Support
|
549
|
-
|
550
|
-
- 📖 **Documentation**: [Link to full docs]
|
551
|
-
- 💬 **Discord**: [Community chat]
|
552
|
-
- 🐛 **Issues**: [GitHub Issues]
|
553
|
-
- 📧 **Email**: support@yourframework.com
|
554
|
-
|
555
|
-
## 🗺️ Roadmap
|
556
|
-
|
557
|
-
- [ ] GraphQL support
|
558
|
-
- [ ] WebSocket integration
|
559
|
-
- [ ] Message queue integration (RabbitMQ, Kafka)
|
560
|
-
- [ ] Microservices communication patterns
|
561
|
-
- [ ] Advanced caching strategies
|
562
|
-
- [ ] Performance optimization tools
|
563
|
-
- [ ] CLI for scaffolding
|
564
|
-
|
565
|
-
---
|
421
|
+
## License
|
566
422
|
|
567
|
-
|
423
|
+
MIT
|