balda-js 0.0.1 → 0.0.3
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/package.json +1 -6
- package/.husky/pre-commit +0 -19
- package/.nvmrc +0 -1
- package/docs/README.md +0 -135
- package/docs/blog/authors.yml +0 -6
- package/docs/blog/tags.yml +0 -4
- package/docs/cli.md +0 -109
- package/docs/docs/core-concepts/controllers.md +0 -393
- package/docs/docs/core-concepts/middleware.md +0 -302
- package/docs/docs/core-concepts/request-response.md +0 -486
- package/docs/docs/core-concepts/routing.md +0 -388
- package/docs/docs/core-concepts/server.md +0 -332
- package/docs/docs/cron/overview.md +0 -70
- package/docs/docs/examples/rest-api.md +0 -595
- package/docs/docs/getting-started/configuration.md +0 -168
- package/docs/docs/getting-started/installation.md +0 -125
- package/docs/docs/getting-started/quick-start.md +0 -273
- package/docs/docs/intro.md +0 -46
- package/docs/docs/plugins/cookie.md +0 -424
- package/docs/docs/plugins/cors.md +0 -295
- package/docs/docs/plugins/file.md +0 -382
- package/docs/docs/plugins/helmet.md +0 -388
- package/docs/docs/plugins/json.md +0 -338
- package/docs/docs/plugins/log.md +0 -592
- package/docs/docs/plugins/overview.md +0 -390
- package/docs/docs/plugins/rate-limiter.md +0 -347
- package/docs/docs/plugins/static.md +0 -352
- package/docs/docs/plugins/swagger.md +0 -411
- package/docs/docs/plugins/urlencoded.md +0 -76
- package/docs/docs/testing/examples.md +0 -384
- package/docs/docs/testing/mock-server.md +0 -311
- package/docs/docs/testing/overview.md +0 -76
- package/docs/docusaurus.config.ts +0 -144
- package/docs/intro.md +0 -78
- package/docs/package.json +0 -46
- package/docs/sidebars.ts +0 -72
- package/docs/static/.nojekyll +0 -0
- package/docs/static/img/docusaurus-social-card.jpg +0 -0
- package/docs/static/img/docusaurus.png +0 -0
- package/docs/static/img/favicon.ico +0 -0
- package/docs/static/img/logo.svg +0 -1
- package/docs/static/img/undraw_docusaurus_mountain.svg +0 -37
- package/docs/static/img/undraw_docusaurus_react.svg +0 -170
- package/docs/static/img/undraw_docusaurus_tree.svg +0 -40
- package/docs/tsconfig.json +0 -8
- package/speed_test.sh +0 -3
- package/test/benchmark/index.ts +0 -17
- package/test/cli/cli.ts +0 -7
- package/test/commands/test.ts +0 -42
- package/test/controllers/file_upload.ts +0 -29
- package/test/controllers/urlencoded.ts +0 -13
- package/test/controllers/users.ts +0 -111
- package/test/cron/index.ts +0 -6
- package/test/cron/test_cron.ts +0 -8
- package/test/cron/test_cron_imported.ts +0 -8
- package/test/native_env.ts +0 -16
- package/test/resources/test.txt +0 -1
- package/test/server/index.ts +0 -3
- package/test/server/instance.ts +0 -63
- package/test/suite/upload.test.ts +0 -23
- package/test/suite/urlencoded.test.ts +0 -23
- package/test/suite/users.test.ts +0 -76
- package/todo.md +0 -9
- package/tsconfig.json +0 -24
- package/vitest.config.ts +0 -17
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "balda-js",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.3",
|
4
4
|
"type": "module",
|
5
5
|
"main": "./lib/index.cjs",
|
6
6
|
"module": "./lib/index.js",
|
@@ -74,11 +74,6 @@
|
|
74
74
|
"peerDependencies": {
|
75
75
|
"node-cron": "^4.1.0"
|
76
76
|
},
|
77
|
-
"peerDependenciesMeta": {
|
78
|
-
"ioredis": {
|
79
|
-
"node-cron": true
|
80
|
-
}
|
81
|
-
},
|
82
77
|
"tags": [
|
83
78
|
"framework",
|
84
79
|
"http",
|
package/.husky/pre-commit
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
#!/usr/bin/env sh
|
2
|
-
. "$(dirname -- "$0")/_/husky.sh"
|
3
|
-
|
4
|
-
yarn format
|
5
|
-
yarn build:test
|
6
|
-
|
7
|
-
echo "Running tests..."
|
8
|
-
|
9
|
-
echo "Running tests for Node..."
|
10
|
-
yarn test
|
11
|
-
|
12
|
-
echo "Running tests for Bun..."
|
13
|
-
yarn test:bun
|
14
|
-
|
15
|
-
echo "Running tests for Deno..."
|
16
|
-
yarn test:deno
|
17
|
-
|
18
|
-
echo "Adding changes..."
|
19
|
-
git add .
|
package/.nvmrc
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
v22.14.0
|
package/docs/README.md
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
# Balda.js Documentation
|
2
|
-
|
3
|
-
This directory contains the documentation for Balda.js, built with Docusaurus.
|
4
|
-
|
5
|
-
## Getting Started
|
6
|
-
|
7
|
-
### Prerequisites
|
8
|
-
|
9
|
-
- Node.js 18+ or Bun
|
10
|
-
- Yarn (recommended) or npm
|
11
|
-
|
12
|
-
### Installation
|
13
|
-
|
14
|
-
```bash
|
15
|
-
# Install dependencies
|
16
|
-
yarn install
|
17
|
-
|
18
|
-
# Start development server
|
19
|
-
yarn start
|
20
|
-
```
|
21
|
-
|
22
|
-
### Available Scripts
|
23
|
-
|
24
|
-
- `yarn start` - Start the development server
|
25
|
-
- `yarn build` - Build the documentation for production
|
26
|
-
- `yarn serve` - Serve the built documentation locally
|
27
|
-
|
28
|
-
## Documentation Structure
|
29
|
-
|
30
|
-
```
|
31
|
-
docs/
|
32
|
-
├── intro.md # Main introduction page
|
33
|
-
├── getting-started/ # Getting started guides
|
34
|
-
│ ├── installation.md
|
35
|
-
│ ├── quick-start.md
|
36
|
-
│ └── configuration.md
|
37
|
-
├── core-concepts/ # Core framework concepts
|
38
|
-
│ ├── server.md
|
39
|
-
│ ├── controllers.md
|
40
|
-
│ ├── routing.md
|
41
|
-
│ ├── middleware.md
|
42
|
-
│ └── request-response.md
|
43
|
-
├── api/ # API reference
|
44
|
-
│ ├── server.md
|
45
|
-
│ ├── controllers.md
|
46
|
-
│ ├── decorators.md
|
47
|
-
│ ├── plugins.md
|
48
|
-
│ ├── cli.md
|
49
|
-
│ └── cron.md
|
50
|
-
├── plugins/ # Plugin documentation
|
51
|
-
│ ├── overview.md
|
52
|
-
│ ├── cors.md
|
53
|
-
│ ├── json.md
|
54
|
-
│ ├── static.md
|
55
|
-
│ ├── cookie.md
|
56
|
-
│ ├── helmet.md
|
57
|
-
│ ├── rate-limiter.md
|
58
|
-
│ ├── log.md
|
59
|
-
│ ├── file.md
|
60
|
-
│ ├── urlencoded.md
|
61
|
-
│ └── swagger.md
|
62
|
-
├── advanced/ # Advanced topics
|
63
|
-
│ ├── validation.md
|
64
|
-
│ ├── serialization.md
|
65
|
-
│ ├── error-handling.md
|
66
|
-
│ ├── testing.md
|
67
|
-
│ └── deployment.md
|
68
|
-
├── examples/ # Example applications
|
69
|
-
│ ├── rest-api.md
|
70
|
-
│ ├── file-upload.md
|
71
|
-
│ ├── authentication.md
|
72
|
-
│ ├── cron-jobs.md
|
73
|
-
│ └── cli-commands.md
|
74
|
-
└── runtime/ # Runtime-specific guides
|
75
|
-
├── node.md
|
76
|
-
├── bun.md
|
77
|
-
└── deno.md
|
78
|
-
```
|
79
|
-
|
80
|
-
## Contributing
|
81
|
-
|
82
|
-
When adding or updating documentation:
|
83
|
-
|
84
|
-
1. Follow the existing structure and naming conventions
|
85
|
-
2. Use TypeScript code examples
|
86
|
-
3. Include practical examples and use cases
|
87
|
-
4. Keep content clear and concise
|
88
|
-
5. Test all code examples
|
89
|
-
|
90
|
-
## Building for Production
|
91
|
-
|
92
|
-
```bash
|
93
|
-
# Build the documentation
|
94
|
-
yarn build
|
95
|
-
|
96
|
-
# The built files will be in the `build` directory
|
97
|
-
```
|
98
|
-
|
99
|
-
## Deployment
|
100
|
-
|
101
|
-
The documentation can be deployed to various platforms:
|
102
|
-
|
103
|
-
- **GitHub Pages**: Use the `yarn deploy` command
|
104
|
-
- **Netlify**: Connect your repository and set build command to `yarn build`
|
105
|
-
- **Vercel**: Connect your repository and set build command to `yarn build`
|
106
|
-
|
107
|
-
## Configuration
|
108
|
-
|
109
|
-
The documentation is configured in `docusaurus.config.ts`. Key settings:
|
110
|
-
|
111
|
-
- Site title and description
|
112
|
-
- Navigation and sidebar structure
|
113
|
-
- Theme customization
|
114
|
-
- Plugin configuration
|
115
|
-
|
116
|
-
## Customization
|
117
|
-
|
118
|
-
### Styling
|
119
|
-
|
120
|
-
Custom CSS can be added to `src/css/custom.css`.
|
121
|
-
|
122
|
-
### Components
|
123
|
-
|
124
|
-
Custom React components can be added to `src/components/`.
|
125
|
-
|
126
|
-
### Pages
|
127
|
-
|
128
|
-
Custom pages can be added to `src/pages/`.
|
129
|
-
|
130
|
-
## Support
|
131
|
-
|
132
|
-
For questions about the documentation or Balda.js:
|
133
|
-
|
134
|
-
- [GitHub Issues](https://github.com/Frasan00/balda-js/issues)
|
135
|
-
- [GitHub Discussions](https://github.com/Frasan00/balda-js/discussions)
|
package/docs/blog/authors.yml
DELETED
package/docs/blog/tags.yml
DELETED
package/docs/cli.md
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
---
|
2
|
-
id: cli
|
3
|
-
title: Command-Line Interface
|
4
|
-
sidebar_position: 1
|
5
|
-
---
|
6
|
-
|
7
|
-
import Tabs from '@theme/Tabs';
|
8
|
-
import TabItem from '@theme/TabItem';
|
9
|
-
|
10
|
-
# `@cli/` overview
|
11
|
-
|
12
|
-
Balda ships with an opinionated, TypeScript-first CLI—think of it as a meta-toolbox. It scaffolds new commands, plugins, and cron jobs so you can stay focused on application logic.
|
13
|
-
|
14
|
-
```bash title="General syntax"
|
15
|
-
npx balda <command> [options] [arguments]
|
16
|
-
```
|
17
|
-
|
18
|
-
Need help?
|
19
|
-
|
20
|
-
```bash title="Global & command help"
|
21
|
-
npx balda # access the cli
|
22
|
-
npx balda <command> -h # command-specific help
|
23
|
-
```
|
24
|
-
|
25
|
-
---
|
26
|
-
|
27
|
-
## Built-in generators
|
28
|
-
|
29
|
-
### 1. `generate-command`
|
30
|
-
|
31
|
-
Scaffolds a new CLI command file.
|
32
|
-
|
33
|
-
| Argument / Flag | Type | Default | Description |
|
34
|
-
| --------------- | ------ | ---------------- | ---------------------------------------- |
|
35
|
-
| `<name>` | string | — (required) | File (and class) name of the new command |
|
36
|
-
| `-p`, `--path` | string | `src/commands` | Target directory |
|
37
|
-
|
38
|
-
```bash title="Example"
|
39
|
-
npx balda generate-command hello-world -p tools/cli
|
40
|
-
```
|
41
|
-
|
42
|
-
---
|
43
|
-
|
44
|
-
### 2. `generate-plugin`
|
45
|
-
|
46
|
-
Creates a plugin skeleton.
|
47
|
-
|
48
|
-
| Argument / Flag | Type | Default | Description |
|
49
|
-
| --------------- | ------ | ------------- | ------------------------------------ |
|
50
|
-
| `<pluginName>` | string | — (required) | Plugin filename & class name |
|
51
|
-
| `-p`, `--path` | string | `src/plugins` | Directory where the file is written |
|
52
|
-
|
53
|
-
```bash title="Example"
|
54
|
-
npx balda generate-plugin auth -p src/plugins/security
|
55
|
-
```
|
56
|
-
|
57
|
-
---
|
58
|
-
|
59
|
-
### 3. `generate-cron`
|
60
|
-
|
61
|
-
Bootstraps a cron-job class adorned with the `@cron()` decorator.
|
62
|
-
|
63
|
-
| Argument / Flag | Type | Default | Description |
|
64
|
-
| --------------- | ------ | --------- | ------------------------- |
|
65
|
-
| `<fileName>` | string | — | Cron job filename |
|
66
|
-
| `-p`, `--path` | string | `src/cron`| Where to create the file |
|
67
|
-
|
68
|
-
```bash title="Example"
|
69
|
-
npx balda generate-cron clean-sessions -p src/maintenance/cron
|
70
|
-
```
|
71
|
-
|
72
|
-
---
|
73
|
-
|
74
|
-
## Extending the CLI
|
75
|
-
|
76
|
-
Declare your own commands and tell Balda where to find them:
|
77
|
-
|
78
|
-
```ts title="Custom command discovery"
|
79
|
-
import { CommandRegistry } from '@cli/';
|
80
|
-
|
81
|
-
CommandRegistry.setCommandsPattern('./my/commands/**/*.ts');
|
82
|
-
```
|
83
|
-
|
84
|
-
At startup the CLI loads:
|
85
|
-
|
86
|
-
1. Anything matching the pattern above.
|
87
|
-
2. The built-in generators described earlier.
|
88
|
-
|
89
|
-
> **Tip:** Use decorators (`@arg`, `@flag`) in your command classes for self-documenting, runtime-validated definitions.
|
90
|
-
|
91
|
-
---
|
92
|
-
|
93
|
-
## Help & validation
|
94
|
-
|
95
|
-
Each command inherits colourised `--help` output **and** validation for missing/invalid flags. Introduce an error:
|
96
|
-
|
97
|
-
```bash
|
98
|
-
npx balda generate-plugin
|
99
|
-
```
|
100
|
-
|
101
|
-
You’ll get a detailed, friendly validation report and a non-zero exit code.
|
102
|
-
|
103
|
-
---
|
104
|
-
|
105
|
-
## Next steps
|
106
|
-
|
107
|
-
• Install globally with `npm i -g balda` if you prefer the shorter `balda` binary.
|
108
|
-
• Peek at `src/commands/base_command.ts` for advanced goodies like `keepAlive`.
|
109
|
-
• Curious about decorators? Check **Docs → Decorators** (coming soon).
|
@@ -1,393 +0,0 @@
|
|
1
|
-
---
|
2
|
-
sidebar_position: 2
|
3
|
-
---
|
4
|
-
|
5
|
-
# Controllers
|
6
|
-
|
7
|
-
Controllers are the heart of your Balda.js application. They organize your route handlers into logical groups and provide a clean, decorator-based API for defining HTTP endpoints.
|
8
|
-
|
9
|
-
## Basic Controller
|
10
|
-
|
11
|
-
```typescript
|
12
|
-
import { controller, get, post } from 'balda-js';
|
13
|
-
import { Request, Response } from 'balda-js';
|
14
|
-
|
15
|
-
@controller('/users')
|
16
|
-
export class UsersController {
|
17
|
-
@get('/')
|
18
|
-
async getAllUsers(req: Request, res: Response) {
|
19
|
-
res.json({ users: [] });
|
20
|
-
}
|
21
|
-
|
22
|
-
@post('/')
|
23
|
-
async createUser(req: Request, res: Response) {
|
24
|
-
res.created(req.body);
|
25
|
-
}
|
26
|
-
}
|
27
|
-
```
|
28
|
-
|
29
|
-
## Controller Decorator
|
30
|
-
|
31
|
-
The `@controller()` decorator marks a class as a controller and defines the base path for all routes within that controller.
|
32
|
-
|
33
|
-
```typescript
|
34
|
-
@controller(path?: string, swaggerOptions?: SwaggerRouteOptions)
|
35
|
-
```
|
36
|
-
|
37
|
-
### Parameters
|
38
|
-
|
39
|
-
- `path` (optional): Base path for all routes in the controller
|
40
|
-
- `swaggerOptions` (optional): Swagger documentation options for the controller
|
41
|
-
|
42
|
-
### Examples
|
43
|
-
|
44
|
-
```typescript
|
45
|
-
// Simple controller
|
46
|
-
@controller('/users')
|
47
|
-
export class UsersController {}
|
48
|
-
|
49
|
-
// Controller with Swagger options
|
50
|
-
@controller('/users', {
|
51
|
-
tags: ['Users'],
|
52
|
-
summary: 'User management endpoints'
|
53
|
-
})
|
54
|
-
export class UsersController {}
|
55
|
-
```
|
56
|
-
|
57
|
-
## HTTP Method Decorators
|
58
|
-
|
59
|
-
Balda.js provides decorators for all HTTP methods:
|
60
|
-
|
61
|
-
### GET Requests
|
62
|
-
|
63
|
-
```typescript
|
64
|
-
@get('/')
|
65
|
-
async getAllUsers(req: Request, res: Response) {
|
66
|
-
res.json({ users: [] });
|
67
|
-
}
|
68
|
-
|
69
|
-
@get('/:id')
|
70
|
-
async getUserById(req: Request, res: Response) {
|
71
|
-
const id = req.params.id;
|
72
|
-
res.json({ user: { id } });
|
73
|
-
}
|
74
|
-
```
|
75
|
-
|
76
|
-
### POST Requests
|
77
|
-
|
78
|
-
```typescript
|
79
|
-
@post('/')
|
80
|
-
async createUser(req: Request, res: Response) {
|
81
|
-
const user = req.body;
|
82
|
-
res.created(user);
|
83
|
-
}
|
84
|
-
```
|
85
|
-
|
86
|
-
### PUT Requests
|
87
|
-
|
88
|
-
```typescript
|
89
|
-
@put('/:id')
|
90
|
-
async updateUser(req: Request, res: Response) {
|
91
|
-
const id = req.params.id;
|
92
|
-
const updates = req.body;
|
93
|
-
res.json({ id, ...updates });
|
94
|
-
}
|
95
|
-
```
|
96
|
-
|
97
|
-
### PATCH Requests
|
98
|
-
|
99
|
-
```typescript
|
100
|
-
@patch('/:id')
|
101
|
-
async partialUpdateUser(req: Request, res: Response) {
|
102
|
-
const id = req.params.id;
|
103
|
-
const updates = req.body;
|
104
|
-
res.json({ id, ...updates });
|
105
|
-
}
|
106
|
-
```
|
107
|
-
|
108
|
-
### DELETE Requests
|
109
|
-
|
110
|
-
```typescript
|
111
|
-
@del('/:id')
|
112
|
-
async deleteUser(req: Request, res: Response) {
|
113
|
-
const id = req.params.id;
|
114
|
-
res.noContent();
|
115
|
-
}
|
116
|
-
```
|
117
|
-
|
118
|
-
## Route Options
|
119
|
-
|
120
|
-
Each HTTP method decorator can accept route options:
|
121
|
-
|
122
|
-
```typescript
|
123
|
-
@get('/', {
|
124
|
-
middleware: [authMiddleware],
|
125
|
-
swagger: {
|
126
|
-
summary: 'Get all users',
|
127
|
-
description: 'Retrieve a list of all users'
|
128
|
-
}
|
129
|
-
})
|
130
|
-
async getAllUsers(req: Request, res: Response) {
|
131
|
-
res.json({ users: [] });
|
132
|
-
}
|
133
|
-
```
|
134
|
-
|
135
|
-
## Controller-Level Middleware
|
136
|
-
|
137
|
-
You can apply middleware to all routes in a controller:
|
138
|
-
|
139
|
-
```typescript
|
140
|
-
@controller('/users')
|
141
|
-
@middleware(authMiddleware)
|
142
|
-
export class UsersController {
|
143
|
-
@get('/')
|
144
|
-
async getAllUsers(req: Request, res: Response) {
|
145
|
-
// This route will use authMiddleware
|
146
|
-
res.json({ users: [] });
|
147
|
-
}
|
148
|
-
|
149
|
-
@get('/public')
|
150
|
-
@middleware(publicMiddleware) // Override controller middleware
|
151
|
-
async getPublicUsers(req: Request, res: Response) {
|
152
|
-
// This route will use publicMiddleware instead
|
153
|
-
res.json({ users: [] });
|
154
|
-
}
|
155
|
-
}
|
156
|
-
```
|
157
|
-
|
158
|
-
## Complete Controller Example
|
159
|
-
|
160
|
-
```typescript
|
161
|
-
import {
|
162
|
-
controller,
|
163
|
-
get,
|
164
|
-
post,
|
165
|
-
put,
|
166
|
-
del,
|
167
|
-
middleware,
|
168
|
-
validate,
|
169
|
-
serialize
|
170
|
-
} from 'balda-js';
|
171
|
-
import { Request, Response } from 'balda-js';
|
172
|
-
import { Type, Static } from '@sinclair/typebox';
|
173
|
-
|
174
|
-
const UserSchema = Type.Object({
|
175
|
-
id: Type.Number(),
|
176
|
-
name: Type.String(),
|
177
|
-
email: Type.String()
|
178
|
-
});
|
179
|
-
|
180
|
-
const CreateUserSchema = Type.Object({
|
181
|
-
name: Type.String(),
|
182
|
-
email: Type.String({ format: 'email' })
|
183
|
-
});
|
184
|
-
|
185
|
-
@controller('/users', {
|
186
|
-
tags: ['Users'],
|
187
|
-
summary: 'User management endpoints'
|
188
|
-
})
|
189
|
-
@middleware(loggerMiddleware)
|
190
|
-
export class UsersController {
|
191
|
-
private users = [
|
192
|
-
{ id: 1, name: 'John Doe', email: 'john@example.com' },
|
193
|
-
{ id: 2, name: 'Jane Smith', email: 'jane@example.com' }
|
194
|
-
];
|
195
|
-
|
196
|
-
@get('/')
|
197
|
-
@serialize(Type.Array(UserSchema))
|
198
|
-
async getAllUsers(req: Request, res: Response) {
|
199
|
-
res.json(this.users);
|
200
|
-
}
|
201
|
-
|
202
|
-
@get('/:id')
|
203
|
-
@serialize(UserSchema)
|
204
|
-
async getUserById(req: Request, res: Response) {
|
205
|
-
const id = parseInt(req.params.id);
|
206
|
-
const user = this.users.find(u => u.id === id);
|
207
|
-
|
208
|
-
if (!user) {
|
209
|
-
return res.notFound({ error: 'User not found' });
|
210
|
-
}
|
211
|
-
|
212
|
-
res.json(user);
|
213
|
-
}
|
214
|
-
|
215
|
-
@post('/')
|
216
|
-
@validate.body(CreateUserSchema)
|
217
|
-
@serialize(UserSchema)
|
218
|
-
async createUser(req: Request, res: Response, body: Static<typeof CreateUserSchema>) {
|
219
|
-
const newUser = {
|
220
|
-
id: this.users.length + 1,
|
221
|
-
...body
|
222
|
-
};
|
223
|
-
|
224
|
-
this.users.push(newUser);
|
225
|
-
res.created(newUser);
|
226
|
-
}
|
227
|
-
|
228
|
-
@put('/:id')
|
229
|
-
@middleware(authMiddleware)
|
230
|
-
@validate.body(CreateUserSchema)
|
231
|
-
@serialize(UserSchema)
|
232
|
-
async updateUser(req: Request, res: Response, body: Static<typeof CreateUserSchema>) {
|
233
|
-
const id = parseInt(req.params.id);
|
234
|
-
const userIndex = this.users.findIndex(u => u.id === id);
|
235
|
-
|
236
|
-
if (userIndex === -1) {
|
237
|
-
return res.notFound({ error: 'User not found' });
|
238
|
-
}
|
239
|
-
|
240
|
-
this.users[userIndex] = { ...this.users[userIndex], ...body };
|
241
|
-
res.json(this.users[userIndex]);
|
242
|
-
}
|
243
|
-
|
244
|
-
@del('/:id')
|
245
|
-
@middleware(authMiddleware)
|
246
|
-
async deleteUser(req: Request, res: Response) {
|
247
|
-
const id = parseInt(req.params.id);
|
248
|
-
const userIndex = this.users.findIndex(u => u.id === id);
|
249
|
-
|
250
|
-
if (userIndex === -1) {
|
251
|
-
return res.notFound({ error: 'User not found' });
|
252
|
-
}
|
253
|
-
|
254
|
-
this.users.splice(userIndex, 1);
|
255
|
-
res.noContent();
|
256
|
-
}
|
257
|
-
}
|
258
|
-
```
|
259
|
-
|
260
|
-
## Controller Organization
|
261
|
-
|
262
|
-
### File Structure
|
263
|
-
|
264
|
-
```
|
265
|
-
src/
|
266
|
-
├── controllers/
|
267
|
-
│ ├── users.controller.ts
|
268
|
-
│ ├── posts.controller.ts
|
269
|
-
│ ├── auth.controller.ts
|
270
|
-
│ └── index.ts
|
271
|
-
```
|
272
|
-
|
273
|
-
### Controller Registration
|
274
|
-
|
275
|
-
Controllers are automatically registered when the server starts. Make sure your controller files match the patterns specified in your server configuration:
|
276
|
-
|
277
|
-
```typescript
|
278
|
-
const server = new Server({
|
279
|
-
controllerPatterns: ['./src/controllers/**/*.ts']
|
280
|
-
});
|
281
|
-
```
|
282
|
-
|
283
|
-
### Controller Index
|
284
|
-
|
285
|
-
You can create an index file to export all controllers:
|
286
|
-
|
287
|
-
```typescript
|
288
|
-
// src/controllers/index.ts
|
289
|
-
export * from './users.controller';
|
290
|
-
export * from './posts.controller';
|
291
|
-
export * from './auth.controller';
|
292
|
-
```
|
293
|
-
|
294
|
-
## Best Practices
|
295
|
-
|
296
|
-
### 1. Single Responsibility
|
297
|
-
|
298
|
-
Each controller should handle a single resource or feature:
|
299
|
-
|
300
|
-
```typescript
|
301
|
-
// Good: Focused on users
|
302
|
-
@controller('/users')
|
303
|
-
export class UsersController {}
|
304
|
-
|
305
|
-
// Good: Focused on authentication
|
306
|
-
@controller('/auth')
|
307
|
-
export class AuthController {}
|
308
|
-
|
309
|
-
// Avoid: Mixed responsibilities
|
310
|
-
@controller('/api')
|
311
|
-
export class ApiController {} // Too broad
|
312
|
-
```
|
313
|
-
|
314
|
-
### 2. Consistent Naming
|
315
|
-
|
316
|
-
Use consistent naming conventions:
|
317
|
-
|
318
|
-
```typescript
|
319
|
-
// Good: Clear and descriptive
|
320
|
-
@controller('/users')
|
321
|
-
export class UsersController {}
|
322
|
-
|
323
|
-
@controller('/blog-posts')
|
324
|
-
export class BlogPostsController {}
|
325
|
-
|
326
|
-
// Avoid: Unclear names
|
327
|
-
@controller('/u')
|
328
|
-
export class UController {}
|
329
|
-
```
|
330
|
-
|
331
|
-
### 3. Error Handling
|
332
|
-
|
333
|
-
Handle errors consistently within controllers:
|
334
|
-
|
335
|
-
```typescript
|
336
|
-
@controller('/users')
|
337
|
-
export class UsersController {
|
338
|
-
@get('/:id')
|
339
|
-
async getUserById(req: Request, res: Response) {
|
340
|
-
try {
|
341
|
-
const id = parseInt(req.params.id);
|
342
|
-
const user = await userService.findById(id);
|
343
|
-
|
344
|
-
if (!user) {
|
345
|
-
return res.notFound({ error: 'User not found' });
|
346
|
-
}
|
347
|
-
|
348
|
-
res.json(user);
|
349
|
-
} catch (error) {
|
350
|
-
console.error('Error fetching user:', error);
|
351
|
-
res.internalServerError({ error: 'Failed to fetch user' });
|
352
|
-
}
|
353
|
-
}
|
354
|
-
}
|
355
|
-
```
|
356
|
-
|
357
|
-
### 4. Validation and Serialization
|
358
|
-
|
359
|
-
Use validation and serialization decorators for type safety:
|
360
|
-
|
361
|
-
```typescript
|
362
|
-
@controller('/users')
|
363
|
-
export class UsersController {
|
364
|
-
@post('/')
|
365
|
-
@validate.body(CreateUserSchema)
|
366
|
-
@serialize(UserSchema)
|
367
|
-
async createUser(req: Request, res: Response, body: Static<typeof CreateUserSchema>) {
|
368
|
-
// body is now typed as CreateUser
|
369
|
-
const user = await userService.create(body);
|
370
|
-
res.created(user);
|
371
|
-
}
|
372
|
-
}
|
373
|
-
```
|
374
|
-
|
375
|
-
### 5. Middleware Organization
|
376
|
-
|
377
|
-
Group related middleware and apply them at the appropriate level:
|
378
|
-
|
379
|
-
```typescript
|
380
|
-
// Apply to all routes in controller
|
381
|
-
@controller('/users')
|
382
|
-
@middleware(authMiddleware)
|
383
|
-
export class UsersController {
|
384
|
-
// Apply to specific routes
|
385
|
-
@get('/admin')
|
386
|
-
@middleware(adminMiddleware)
|
387
|
-
async getAdminUsers(req: Request, res: Response) {
|
388
|
-
// Uses both authMiddleware and adminMiddleware
|
389
|
-
}
|
390
|
-
}
|
391
|
-
```
|
392
|
-
|
393
|
-
Controllers provide a clean, organized way to structure your Balda.js application's route handlers.
|