@increase21/simplenodejs 1.1.1 → 2.0.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 +39 -32
- package/dist/index.d.ts +1 -1
- package/dist/router.js +10 -0
- package/dist/typings/general.d.ts +4 -4
- package/dist/typings/simpletypes.d.ts +5 -2
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -97,39 +97,44 @@ Controllers are auto-loaded from `controllersDir` at startup. The file path maps
|
|
|
97
97
|
|
|
98
98
|
```
|
|
99
99
|
controllers/
|
|
100
|
-
users/
|
|
101
|
-
auth.ts → /users/auth
|
|
102
|
-
profile.ts → /users/profile
|
|
103
100
|
drivers/
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
auths.ts → /users/auths
|
|
102
|
+
|
|
103
|
+
customers/
|
|
104
|
+
auths.ts → /customers/auths
|
|
105
|
+
accounts → /customers/accounts
|
|
106
106
|
```
|
|
107
107
|
|
|
108
|
-
Controllers are plain classes — no base class required. Each method represents an endpoint and returns an array of `SimpleJsEndpointDescriptor` objects that
|
|
108
|
+
Controllers are plain classes — no base class required. Each method represents an endpoint and returns a `SimpleJsEndpoint` (an array of `SimpleJsEndpointDescriptor` objects) that declares which HTTP methods are supported and which handler to call.
|
|
109
|
+
|
|
110
|
+
Every controller receives the request context (`SimpleJsCtx`) via its constructor and it is also available as `this.ctx` anywhere inside the class — in endpoint methods, descriptor handlers, and private helpers.
|
|
109
111
|
|
|
110
112
|
```ts
|
|
111
113
|
// controllers/drivers/auths.ts
|
|
112
|
-
import { SimpleJsCtx,
|
|
114
|
+
import { SimpleJsCtx, SimpleJsEndpoint } from "@increase21/simplenodejs";
|
|
113
115
|
|
|
114
116
|
export default class AuthController {
|
|
117
|
+
ctx: SimpleJsCtx;
|
|
115
118
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
];
|
|
119
|
+
// single HTTP method — access this.ctx directly, no descriptor needed
|
|
120
|
+
async login(): Promise<void> {
|
|
121
|
+
if (this.ctx.method !== "post") return this.ctx.res.status(405).json({ error: "Method Not Allowed" });
|
|
122
|
+
// handler logic...
|
|
121
123
|
}
|
|
122
124
|
|
|
123
|
-
|
|
125
|
+
// multiple HTTP methods — return a SimpleJsEndpoint array
|
|
126
|
+
async vehicleList(id?: string): Promise<SimpleJsEndpoint> {
|
|
124
127
|
return [
|
|
125
|
-
{ method: "get", id: "optional",
|
|
126
|
-
{ method: "put", id: "required",
|
|
127
|
-
{ method: "delete", id: "required",
|
|
128
|
+
{ method: "get", id: "optional", handler: getVehicles },
|
|
129
|
+
{ method: "put", id: "required", handler: updateVehicle },
|
|
130
|
+
{ method: "delete", id: "required", handler: deleteVehicle },
|
|
128
131
|
];
|
|
129
132
|
}
|
|
130
133
|
}
|
|
131
134
|
```
|
|
132
135
|
|
|
136
|
+
> `this.ctx` is injected automatically by the router on every request. You do not need to pass it around manually — it is always available anywhere in the class.
|
|
137
|
+
|
|
133
138
|
### Endpoint Naming
|
|
134
139
|
|
|
135
140
|
Controller methods use **camelCase** and are exposed as **kebab-case** URLs.
|
|
@@ -145,22 +150,17 @@ Controller methods use **camelCase** and are exposed as **kebab-case** URLs.
|
|
|
145
150
|
Declare `id` in the endpoint method signature to indicate it accepts an ID segment. Use the descriptor's `id` field to enforce whether it is required or optional at the routing level.
|
|
146
151
|
|
|
147
152
|
```ts
|
|
148
|
-
// GET /drivers/auths/
|
|
149
|
-
// GET /drivers/auths/
|
|
150
|
-
// PUT /drivers/auths/
|
|
151
|
-
|
|
152
|
-
return [
|
|
153
|
-
{ method: "get", id: "optional", handler: getAccount },
|
|
154
|
-
{ method: "put", id: "required", handler: updateAccount },
|
|
155
|
-
];
|
|
156
|
-
}
|
|
153
|
+
// GET /drivers/auths/vehicle-list → id is optional
|
|
154
|
+
// GET /drivers/auths/vehicle-list/123 → id = "123"
|
|
155
|
+
// PUT /drivers/auths/vehicle-list/123 → required, 404 if missing
|
|
156
|
+
// DELETE /drivers/auths/vehicle-list/123 → required, 404 if missing
|
|
157
157
|
```
|
|
158
158
|
|
|
159
159
|
---
|
|
160
160
|
|
|
161
161
|
## SimpleJsCtx
|
|
162
162
|
|
|
163
|
-
The context object passed to every endpoint method and handler.
|
|
163
|
+
The context object passed to every endpoint method and handler. Accepts an optional generic type `T` for `customData`.
|
|
164
164
|
|
|
165
165
|
| Property | Type | Description |
|
|
166
166
|
|---|---|---|
|
|
@@ -168,18 +168,28 @@ The context object passed to every endpoint method and handler.
|
|
|
168
168
|
| `res` | `ResponseObject` | Raw response object |
|
|
169
169
|
| `body` | `object` | Parsed request body |
|
|
170
170
|
| `query` | `object` | Parsed query string |
|
|
171
|
-
| `
|
|
171
|
+
| `method` | `HttpMethod` | HTTP method of the request (`"get"`, `"post"`, etc.) |
|
|
172
|
+
| `customData` | `T` (default `any`) | Data attached by plugins/middlewares via `req._custom_data` |
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
// Typed customData
|
|
176
|
+
const cookies = (ctx as SimpleJsCtx<{ cookies: Record<string, string> }>).customData.cookies;
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## SimpleJsEndpoint
|
|
180
|
+
|
|
181
|
+
`SimpleJsEndpoint` is the return type for controller endpoint methods. It is equivalent to `SimpleJsEndpointDescriptor[]`.
|
|
172
182
|
|
|
173
183
|
## SimpleJsEndpointDescriptor
|
|
174
184
|
|
|
175
|
-
|
|
185
|
+
Each object in the `SimpleJsEndpoint` array describes one HTTP verb handler.
|
|
176
186
|
|
|
177
187
|
| Property | Type | Required | Description |
|
|
178
188
|
|---|---|---|---|
|
|
179
189
|
| `method` | `HttpMethod` | ✅ | HTTP verb: `"get"`, `"post"`, `"put"`, `"patch"`, `"delete"` |
|
|
180
190
|
| `handler` | `(ctx, id?) => any` | ✅ | Method reference to call for this HTTP verb |
|
|
181
191
|
| `id` | `"required" \| "optional"` | ❌ | ID routing rule. Omit if the endpoint never uses an ID |
|
|
182
|
-
| `middleware` | `
|
|
192
|
+
| `middleware` | `Middleware[]` | ❌ | Array of middlewares to run before the handler |
|
|
183
193
|
|
|
184
194
|
---
|
|
185
195
|
|
|
@@ -189,9 +199,6 @@ Extends Node's `IncomingMessage` with additional properties.
|
|
|
189
199
|
|
|
190
200
|
| Property | Type | Description |
|
|
191
201
|
|---|---|---|
|
|
192
|
-
| `req.url` | `string` | Full request URL |
|
|
193
|
-
| `req.method` | `string` | HTTP method |
|
|
194
|
-
| `req.headers` | `object` | Request headers |
|
|
195
202
|
| `req.query` | `object` | Parsed query string parameters |
|
|
196
203
|
| `req.body` | `any` | Parsed request body (set by `SetBodyParser`) |
|
|
197
204
|
| `req.id` | `string` | Auto-generated UUID for the request (also sent as `X-Request-Id` header) |
|
package/dist/index.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ export { CreateSimpleJsHttpServer, CreateSimpleJsHttpsServer } from "./server";
|
|
|
2
2
|
export { SetCORS, SetHSTS, SetCSP, SetFrameGuard, SetNoSniff, SetReferrerPolicy, SetPermissionsPolicy, SetCOEP, SetCOOP, SetHelmet, SetRateLimiter, SetBodyParser, } from "./utils/simpleMiddleware";
|
|
3
3
|
export * from "./utils/simplePlugins";
|
|
4
4
|
export type { RequestObject, ResponseObject } from "./typings/general";
|
|
5
|
-
export type { SimpleJsCtx,
|
|
5
|
+
export type { SimpleJsCtx, SimpleJsEndpoint, SimpleJsHttpsServer, Middleware as SimpleJsMiddleware, ErrorMiddleware as SimpleJsErrorMiddleware } from "./typings/simpletypes";
|
package/dist/router.js
CHANGED
|
@@ -23,6 +23,7 @@ async function route(req, res) {
|
|
|
23
23
|
req, res,
|
|
24
24
|
body: req.body,
|
|
25
25
|
query: req.query,
|
|
26
|
+
method: httpMethod,
|
|
26
27
|
customData: req._custom_data,
|
|
27
28
|
};
|
|
28
29
|
const ControllerClass = meta.Controller;
|
|
@@ -50,6 +51,8 @@ async function route(req, res) {
|
|
|
50
51
|
if (id.length && (!controller[methodName].length || controller[methodName].length === 1)) {
|
|
51
52
|
return (0, helpers_1.throwHttpError)(404, "Resource not found");
|
|
52
53
|
}
|
|
54
|
+
//also add the context to the controller instance so that it can be accessed in the methods without passing it as a parameter
|
|
55
|
+
controller.ctx = ctx;
|
|
53
56
|
const descriptors = await controller[methodName](ctx, ...id);
|
|
54
57
|
// If the controller method has already sent a response, do not proceed
|
|
55
58
|
if (res.writableEnded)
|
|
@@ -66,6 +69,13 @@ async function route(req, res) {
|
|
|
66
69
|
return (0, helpers_1.throwHttpError)(404, "Resource not found");
|
|
67
70
|
if (descriptor.id === "required" && !id.length)
|
|
68
71
|
return (0, helpers_1.throwHttpError)(404, "Resource not found");
|
|
72
|
+
// Run endpoint-level middlewares before the handler
|
|
73
|
+
if (descriptor.middleware?.length) {
|
|
74
|
+
await (0, helpers_1.composeMiddleware)(descriptor.middleware)(req, res);
|
|
75
|
+
}
|
|
76
|
+
// If the handler has already sent a response, do not proceed
|
|
77
|
+
if (res.writableEnded)
|
|
78
|
+
return;
|
|
69
79
|
// bind to controller so `this` works in regular methods too
|
|
70
80
|
await descriptor.handler.bind(controller)(ctx, ...id);
|
|
71
81
|
if (!res.writableEnded)
|
|
@@ -3,15 +3,15 @@ export type HttpMethod = "get" | "post" | "put" | "patch" | "delete";
|
|
|
3
3
|
export type ObjectPayload = {
|
|
4
4
|
[key: string]: any;
|
|
5
5
|
};
|
|
6
|
-
export
|
|
6
|
+
export interface RequestObject extends IncomingMessage {
|
|
7
7
|
body?: any;
|
|
8
8
|
query?: any;
|
|
9
9
|
id?: string;
|
|
10
10
|
_end_point_path?: string[];
|
|
11
11
|
_custom_data?: ObjectPayload;
|
|
12
|
-
}
|
|
13
|
-
export
|
|
12
|
+
}
|
|
13
|
+
export interface ResponseObject extends ServerResponse {
|
|
14
14
|
status: (value: number) => ResponseObject;
|
|
15
15
|
json: (value: object) => void;
|
|
16
16
|
text: (value?: string) => void;
|
|
17
|
-
}
|
|
17
|
+
}
|
|
@@ -39,15 +39,18 @@ export interface SimpleJsHttpsServer extends https.Server {
|
|
|
39
39
|
useError: (mw: ErrorMiddleware) => void;
|
|
40
40
|
registerPlugin: (plugin: Plugin) => Promise<any> | void;
|
|
41
41
|
}
|
|
42
|
-
export interface SimpleJsCtx {
|
|
42
|
+
export interface SimpleJsCtx<T = any> {
|
|
43
43
|
body: ObjectPayload;
|
|
44
44
|
res: ResponseObject;
|
|
45
45
|
req: RequestObject;
|
|
46
46
|
query: ObjectPayload;
|
|
47
|
-
|
|
47
|
+
method: HttpMethod;
|
|
48
|
+
customData: T;
|
|
48
49
|
}
|
|
49
50
|
export interface SimpleJsEndpointDescriptor {
|
|
50
51
|
method: HttpMethod;
|
|
51
52
|
id?: "required" | "optional";
|
|
53
|
+
middleware?: Middleware[];
|
|
52
54
|
handler: (ctx: SimpleJsCtx, id?: string) => any;
|
|
53
55
|
}
|
|
56
|
+
export type SimpleJsEndpoint = SimpleJsEndpointDescriptor[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@increase21/simplenodejs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Lightweight Node.js HTTP framework with middlewares and plugins",
|
|
5
5
|
"dev": "dist/index.js",
|
|
6
6
|
"bugs": "https://github.com/increase21/simplenodejs/issues",
|
|
@@ -40,4 +40,4 @@
|
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"typescript": "^5.3.0"
|
|
42
42
|
}
|
|
43
|
-
}
|
|
43
|
+
}
|