bro-framework 2.2.1 → 2.3.0
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/README.md +205 -190
- package/bin/bro.js +268 -259
- package/package.json +88 -88
- package/src/auth.js +33 -33
- package/src/index.d.ts +80 -66
- package/src/index.js +1 -0
- package/src/locale.js +118 -0
- package/src/logger.js +79 -79
- package/src/router.js +192 -187
- package/src/sdk.js +169 -160
- package/src/server.js +277 -243
- package/src/tasks.js +54 -54
package/README.md
CHANGED
|
@@ -1,190 +1,205 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="https://brojs.yessindevs.me/bro.js.png" alt="bro.js Logo" width="256" height="256">
|
|
3
|
-
<h1 align="center">bro.js</h1>
|
|
4
|
-
<p align="center">
|
|
5
|
-
<strong>The zero-boilerplate Node.js framework that actually has your back.</strong>
|
|
6
|
-
</p>
|
|
7
|
-
<p align="center">
|
|
8
|
-
<a href="https://www.npmjs.com/package/bro-framework"><img src="https://img.shields.io/npm/v/bro-framework.svg?style=flat-square&color=e11d48" alt="npm version"></a>
|
|
9
|
-
<img src="https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square" alt="License: MIT">
|
|
10
|
-
<img src="https://img.shields.io/badge/Node.js-%3E%3D%2018-green.svg?style=flat-square" alt="Node.js: >= 18">
|
|
11
|
-
<img src="https://img.shields.io/badge/Architecture-Pure%20ESM-orange.svg?style=flat-square" alt="Architecture: Pure ESM">
|
|
12
|
-
<img src="https://img.shields.io/badge/Validation-Zod-3068b7.svg?style=flat-square" alt="Validation: Zod">
|
|
13
|
-
<img src="https://img.shields.io/badge/Realtime-Socket.io-black.svg?style=flat-square" alt="Realtime: Socket.io">
|
|
14
|
-
<img src="https://img.shields.io/badge/Engine-Express-eeeeee.svg?style=flat-square" alt="Engine: Express">
|
|
15
|
-
</p>
|
|
16
|
-
<p align="center">
|
|
17
|
-
<a href="https://brojs.yessindevs.me">Documentation Website</a>
|
|
18
|
-
</p>
|
|
19
|
-
</p>
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
> "NestJS wants four decorators, three modules, and an existential crisis just to handle a GET request. Express makes you write the same 40 lines of CORS, JSON parsing, and auth middleware for every project. bro.js gives you file routing, auto-validation, JWT auth, WebSockets, and live docs out of the box. Be honest: you just want to return an object."
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## Table of Contents
|
|
28
|
-
|
|
29
|
-
- [Getting Started](#getting-started)
|
|
30
|
-
- [The Core Experience](#the-core-experience)
|
|
31
|
-
- [Deep-Dive Features](#deep-dive-features)
|
|
32
|
-
- [Architecture & Request Lifecycle](#architecture--request-lifecycle)
|
|
33
|
-
- [Tech Stack Breakdown](#tech-stack-breakdown)
|
|
34
|
-
- [CLI Reference](#cli-reference)
|
|
35
|
-
- [Author & License](#author--license)
|
|
36
|
-
|
|
37
|
-
---
|
|
38
|
-
|
|
39
|
-
## Getting Started
|
|
40
|
-
|
|
41
|
-
Bootstrapping a new `bro.js` project is incredibly simple. We recommend using our official scaffolding tool to set everything up instantly (with your choice of JavaScript or TypeScript):
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
npx create-bro-framework@latest my-api
|
|
45
|
-
cd my-api
|
|
46
|
-
npm run dev
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
That's it! Your zero-boilerplate backend is now running with hot-reloading enabled.
|
|
50
|
-
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
## The Core Experience
|
|
54
|
-
|
|
55
|
-
In `bro.js`, everything you need is handed to you instantly. No setup, no middleware wrangling, no manual `req/res` handling. You define your route, set your validation, and return an object.
|
|
56
|
-
|
|
57
|
-
`routes/posts/[id].post.js`:
|
|
58
|
-
|
|
59
|
-
```javascript
|
|
60
|
-
import { defineRoute, z } from 'bro-framework';
|
|
61
|
-
|
|
62
|
-
export default defineRoute({
|
|
63
|
-
auth: true,
|
|
64
|
-
params: z.object({
|
|
65
|
-
id: z.string().uuid()
|
|
66
|
-
}),
|
|
67
|
-
body: z.object({
|
|
68
|
-
title: z.string().min(5),
|
|
69
|
-
content: z.string()
|
|
70
|
-
}),
|
|
71
|
-
handler: async ({ body, params, user, db, io }) => {
|
|
72
|
-
// 1. Data is already validated. user is already authenticated.
|
|
73
|
-
|
|
74
|
-
// 2. Perform database operation using the injected Mongoose context
|
|
75
|
-
const post = await db.collection('posts').updateOne(
|
|
76
|
-
{ _id: params.id },
|
|
77
|
-
{ $set: { ...body, authorId: user.id } }
|
|
78
|
-
);
|
|
79
|
-
|
|
80
|
-
// 3. Broadcast to all clients instantly using injected Socket.io
|
|
81
|
-
io.emit('post_updated', { postId: params.id, title: body.title });
|
|
82
|
-
|
|
83
|
-
// 4. Return an object. bro.js handles the 200 JSON response.
|
|
84
|
-
return {
|
|
85
|
-
success: true,
|
|
86
|
-
updated: post.modifiedCount
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
---
|
|
93
|
-
|
|
94
|
-
## Deep-Dive Features
|
|
95
|
-
|
|
96
|
-
### File-Based Routing
|
|
97
|
-
Create a `.js` file in the `routes/` directory, and it automatically becomes an endpoint. We use Next.js-style bracket syntax for dynamic parameters. A file named `routes/users/[id].get.js` translates natively to a `GET /users/:id` Express route under the hood.
|
|
98
|
-
|
|
99
|
-
### Bouncer-Grade Validation
|
|
100
|
-
Powered by Zod. Attach a schema to `body`, `query`, or `params` in your route definition. If the client sends malformed data, `bro.js` automatically rejects the request with a structured `400 Bad Request` JSON payload *before* your handler ever executes. You never have to manually validate inputs again.
|
|
101
|
-
|
|
102
|
-
### Zero-Config JWTs
|
|
103
|
-
Add `auth: true` to your route config. `bro.js` will intercept the request, extract the `Authorization: Bearer <token>` header, verify the signature using your `jwtSecret`, and inject the decoded payload directly into `ctx.user`.
|
|
104
|
-
|
|
105
|
-
### Context Injection
|
|
106
|
-
Stop importing singleton database connections and socket instances into every file. Define your `db` and `sockets` setup once in `bro.config.js`. `bro.js` orchestrates the initialization and injects both instances directly into the `ctx` object for every request handler.
|
|
107
|
-
|
|
108
|
-
### Zero-YAML Live Documentation
|
|
109
|
-
If you've ever hand-written OpenAPI YAML, you know the pain. `bro.js` parses your Zod schemas and automatically serves a stunning, interactive [Scalar](https://scalar.com/) API playground at `/docs`. It's highly secure: by default, these internal docs are disabled in production mode.
|
|
110
|
-
|
|
111
|
-
### The Frontend SDK Generator
|
|
112
|
-
Tired of writing frontend `fetch` wrappers? Run `bro sdk`. The CLI will parse your backend routes and compile a `bro-sdk.js` file for your frontend. It features built-in token management, request stringification, and type-safe deep tree traversal (e.g., `api.users.id("123").post(data)`).
|
|
113
|
-
|
|
114
|
-
### Background Task Scheduler
|
|
115
|
-
Don't spin up a separate worker server. Drop a JavaScript file anywhere in the `tasks/` folder, export a cron string (e.g., `"0 0 * * *"`), and an async handler. `bro.js` natively schedules it as a background worker with full access to your injected database and WebSocket contexts.
|
|
116
|
-
|
|
117
|
-
### Zero-Boilerplate File Uploads
|
|
118
|
-
Add `upload: true` to a route. `bro.js` automatically hooks into `multer`, parses the `multipart/form-data` payload in memory, and injects the files directly into `ctx.files`.
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
│
|
|
142
|
-
▼
|
|
143
|
-
(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
|
180
|
-
|
|
|
181
|
-
|
|
|
182
|
-
|
|
|
183
|
-
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://brojs.yessindevs.me/bro.js.png" alt="bro.js Logo" width="256" height="256">
|
|
3
|
+
<h1 align="center">bro.js</h1>
|
|
4
|
+
<p align="center">
|
|
5
|
+
<strong>The zero-boilerplate Node.js framework that actually has your back.</strong>
|
|
6
|
+
</p>
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://www.npmjs.com/package/bro-framework"><img src="https://img.shields.io/npm/v/bro-framework.svg?style=flat-square&color=e11d48" alt="npm version"></a>
|
|
9
|
+
<img src="https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square" alt="License: MIT">
|
|
10
|
+
<img src="https://img.shields.io/badge/Node.js-%3E%3D%2018-green.svg?style=flat-square" alt="Node.js: >= 18">
|
|
11
|
+
<img src="https://img.shields.io/badge/Architecture-Pure%20ESM-orange.svg?style=flat-square" alt="Architecture: Pure ESM">
|
|
12
|
+
<img src="https://img.shields.io/badge/Validation-Zod-3068b7.svg?style=flat-square" alt="Validation: Zod">
|
|
13
|
+
<img src="https://img.shields.io/badge/Realtime-Socket.io-black.svg?style=flat-square" alt="Realtime: Socket.io">
|
|
14
|
+
<img src="https://img.shields.io/badge/Engine-Express-eeeeee.svg?style=flat-square" alt="Engine: Express">
|
|
15
|
+
</p>
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://brojs.yessindevs.me">Documentation Website</a>
|
|
18
|
+
</p>
|
|
19
|
+
</p>
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
> "NestJS wants four decorators, three modules, and an existential crisis just to handle a GET request. Express makes you write the same 40 lines of CORS, JSON parsing, and auth middleware for every project. bro.js gives you file routing, auto-validation, JWT auth, WebSockets, and live docs out of the box. Be honest: you just want to return an object."
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Table of Contents
|
|
28
|
+
|
|
29
|
+
- [Getting Started](#getting-started)
|
|
30
|
+
- [The Core Experience](#the-core-experience)
|
|
31
|
+
- [Deep-Dive Features](#deep-dive-features)
|
|
32
|
+
- [Architecture & Request Lifecycle](#architecture--request-lifecycle)
|
|
33
|
+
- [Tech Stack Breakdown](#tech-stack-breakdown)
|
|
34
|
+
- [CLI Reference](#cli-reference)
|
|
35
|
+
- [Author & License](#author--license)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Getting Started
|
|
40
|
+
|
|
41
|
+
Bootstrapping a new `bro.js` project is incredibly simple. We recommend using our official scaffolding tool to set everything up instantly (with your choice of JavaScript or TypeScript):
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx create-bro-framework@latest my-api
|
|
45
|
+
cd my-api
|
|
46
|
+
npm run dev
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
That's it! Your zero-boilerplate backend is now running with hot-reloading enabled.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## The Core Experience
|
|
54
|
+
|
|
55
|
+
In `bro.js`, everything you need is handed to you instantly. No setup, no middleware wrangling, no manual `req/res` handling. You define your route, set your validation, and return an object.
|
|
56
|
+
|
|
57
|
+
`routes/posts/[id].post.js`:
|
|
58
|
+
|
|
59
|
+
```javascript
|
|
60
|
+
import { defineRoute, z } from 'bro-framework';
|
|
61
|
+
|
|
62
|
+
export default defineRoute({
|
|
63
|
+
auth: true,
|
|
64
|
+
params: z.object({
|
|
65
|
+
id: z.string().uuid()
|
|
66
|
+
}),
|
|
67
|
+
body: z.object({
|
|
68
|
+
title: z.string().min(5),
|
|
69
|
+
content: z.string()
|
|
70
|
+
}),
|
|
71
|
+
handler: async ({ body, params, user, db, io }) => {
|
|
72
|
+
// 1. Data is already validated. user is already authenticated.
|
|
73
|
+
|
|
74
|
+
// 2. Perform database operation using the injected Mongoose context
|
|
75
|
+
const post = await db.collection('posts').updateOne(
|
|
76
|
+
{ _id: params.id },
|
|
77
|
+
{ $set: { ...body, authorId: user.id } }
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
// 3. Broadcast to all clients instantly using injected Socket.io
|
|
81
|
+
io.emit('post_updated', { postId: params.id, title: body.title });
|
|
82
|
+
|
|
83
|
+
// 4. Return an object. bro.js handles the 200 JSON response.
|
|
84
|
+
return {
|
|
85
|
+
success: true,
|
|
86
|
+
updated: post.modifiedCount
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Deep-Dive Features
|
|
95
|
+
|
|
96
|
+
### File-Based Routing
|
|
97
|
+
Create a `.js` file in the `routes/` directory, and it automatically becomes an endpoint. We use Next.js-style bracket syntax for dynamic parameters. A file named `routes/users/[id].get.js` translates natively to a `GET /users/:id` Express route under the hood.
|
|
98
|
+
|
|
99
|
+
### Bouncer-Grade Validation
|
|
100
|
+
Powered by Zod. Attach a schema to `body`, `query`, or `params` directly in your route definition. If the client sends malformed data, `bro.js` automatically rejects the request with a structured `400 Bad Request` JSON payload *before* your handler ever executes. You never have to manually validate inputs again. You can also define a `response` schema to strongly type your OpenAPI documentation (strictly opt-in; arbitrary 200s work out of the box).
|
|
101
|
+
|
|
102
|
+
### Zero-Config JWTs
|
|
103
|
+
Add `auth: true` to your route config. `bro.js` will intercept the request, extract the `Authorization: Bearer <token>` header, verify the signature using your `jwtSecret`, and inject the decoded payload directly into `ctx.user`.
|
|
104
|
+
|
|
105
|
+
### Context Injection
|
|
106
|
+
Stop importing singleton database connections and socket instances into every file. Define your `db` and `sockets` setup once in `bro.config.js`. `bro.js` orchestrates the initialization and injects both instances directly into the `ctx` object for every request handler.
|
|
107
|
+
|
|
108
|
+
### Zero-YAML Live Documentation
|
|
109
|
+
If you've ever hand-written OpenAPI YAML, you know the pain. `bro.js` parses your Zod schemas and automatically serves a stunning, interactive [Scalar](https://scalar.com/) API playground at `/docs`. It's highly secure: by default, these internal docs are disabled in production mode.
|
|
110
|
+
|
|
111
|
+
### The Frontend SDK Generator
|
|
112
|
+
Tired of writing frontend `fetch` wrappers? Run `bro sdk`. The CLI will parse your backend routes and compile a `bro-sdk.js` file for your frontend. It features built-in token management, request stringification, and type-safe deep tree traversal (e.g., `api.users.id("123").post(data)`).
|
|
113
|
+
|
|
114
|
+
### Background Task Scheduler
|
|
115
|
+
Don't spin up a separate worker server. Drop a JavaScript file anywhere in the `tasks/` folder, export a cron string (e.g., `"0 0 * * *"`), and an async handler. `bro.js` natively schedules it as a background worker with full access to your injected database and WebSocket contexts.
|
|
116
|
+
|
|
117
|
+
### Zero-Boilerplate File Uploads
|
|
118
|
+
Add `upload: true` to a route. `bro.js` automatically hooks into `multer`, parses the `multipart/form-data` payload in memory, and injects the files directly into `ctx.files`. It also natively supports granular file limits, restricting max sizes, parts, and fielding counts instantly to protect your RAM. (Note: Use the `storage` configuration for heavy production disk writing to prevent memory exhaustion).
|
|
119
|
+
|
|
120
|
+
### File-Based Locale
|
|
121
|
+
Create a `locale/` folder with one translation file per locale, such as `locale/en.js` and `locale/fr.js`. Export a plain object from each file, then use `t()` in any route:
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
// locale/fr.js
|
|
125
|
+
export default { welcome: 'Bienvenue, {name} !' };
|
|
126
|
+
|
|
127
|
+
// routes/welcome.get.js
|
|
128
|
+
export default defineRoute({
|
|
129
|
+
handler: async ({ t }) => ({ message: t('welcome', { name: 'Sam' }) })
|
|
130
|
+
});
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
The locale is negotiated dynamically using RFC 9110 `Accept-Language` headers, supporting full region fallback and custom defaults, and the generated SDK can securely set it via `setLocale('fr')`.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Architecture & Request Lifecycle
|
|
138
|
+
|
|
139
|
+
```text
|
|
140
|
+
[ Incoming HTTP Request ]
|
|
141
|
+
│
|
|
142
|
+
▼
|
|
143
|
+
( Express Engine )
|
|
144
|
+
│
|
|
145
|
+
▼
|
|
146
|
+
[ CORS / JSON Pre-flight ]
|
|
147
|
+
│
|
|
148
|
+
▼
|
|
149
|
+
( Dev Logger )
|
|
150
|
+
│
|
|
151
|
+
▼
|
|
152
|
+
[ Auth Guard (JWT Check) ] ──(Fail)──> 401 Unauthorized
|
|
153
|
+
│
|
|
154
|
+
▼
|
|
155
|
+
[ Zod Bouncer Validation ] ───(Fail)──> 400 Bad Request
|
|
156
|
+
│
|
|
157
|
+
▼
|
|
158
|
+
( Route Handler )
|
|
159
|
+
╭─────────────────────╮
|
|
160
|
+
│ Injects: │
|
|
161
|
+
│ - ctx.body / params │
|
|
162
|
+
│ - ctx.user │
|
|
163
|
+
│ - ctx.db │
|
|
164
|
+
│ - ctx.io │
|
|
165
|
+
│ - ctx.files │
|
|
166
|
+
╰─────────────────────╯
|
|
167
|
+
│
|
|
168
|
+
▼
|
|
169
|
+
[ Auto JSON Formatter ] ─────(Fail)──> 500 Internal Error
|
|
170
|
+
│
|
|
171
|
+
▼
|
|
172
|
+
[ Client JSON Response ]
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Tech Stack Breakdown
|
|
178
|
+
|
|
179
|
+
| Layer | Technology | Purpose |
|
|
180
|
+
| :--- | :--- | :--- |
|
|
181
|
+
| **Engine** | Node.js (Express) | High-performance, battle-tested HTTP abstraction layer. |
|
|
182
|
+
| **Validation** | Zod | Bouncer-grade, strictly typed schema validation for payloads. |
|
|
183
|
+
| **Authentication** | jsonwebtoken | Stateless, scalable security for protecting endpoints. |
|
|
184
|
+
| **Realtime** | Socket.io | Bi-directional, event-driven WebSocket communication. |
|
|
185
|
+
| **API Reference** | Scalar | Auto-generated, interactive Swagger/OpenAPI documentation. |
|
|
186
|
+
| **Task Scheduler** | node-cron | Reliable internal background task orchestration. |
|
|
187
|
+
| **File Parsing** | multer | Zero-boilerplate `multipart/form-data` file extraction. |
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## CLI Reference
|
|
192
|
+
|
|
193
|
+
| Command | Description |
|
|
194
|
+
| :--- | :--- |
|
|
195
|
+
| `bro dev` | Development server featuring instant boot, visual CLI banner, and `chokidar`-powered hot module remapping. |
|
|
196
|
+
| `bro start` | Production runner locked down for security. Features Graceful Shutdown APIs (with `onShutdown` DB teardown), suppressed internal logs, and isolated API docs. |
|
|
197
|
+
| `bro init` | Automated workspace scaffolder. Generates configuration files and forcefully ensures your `package.json` respects `"type": "module"`. |
|
|
198
|
+
| `bro sdk` | Route parser and browser client compiler. Generates your typed `bro-sdk.js` frontend SDK in one hit. |
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Author & License
|
|
203
|
+
|
|
204
|
+
- **Author**: Yessin (@medyass1ne)
|
|
205
|
+
- **License**: MIT
|