te.js 2.1.2 → 2.1.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/auto-docs/analysis/handler-analyzer.js +46 -4
- package/docs/configuration.md +13 -0
- package/docs/routing.md +2 -0
- package/package.json +1 -1
- package/server/handler.js +9 -0
|
@@ -15,9 +15,49 @@ const ALL_METHODS = [
|
|
|
15
15
|
];
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* Extracts allowed methods from .only('GET'), .only("POST", "PUT"), etc. in source.
|
|
19
|
+
* Returns a non-empty array only when at least one valid quoted method is found;
|
|
20
|
+
* otherwise [] so caller can fall back to other detection.
|
|
21
|
+
*
|
|
22
|
+
* @param {string} src - Handler source (e.g. handler.toString())
|
|
23
|
+
* @returns {string[]} Normalized method names (uppercase, HEAD added when GET present), or []
|
|
24
|
+
*/
|
|
25
|
+
function detectOnlyMethods(src) {
|
|
26
|
+
const startMarker = '.only(';
|
|
27
|
+
const start = src.indexOf(startMarker);
|
|
28
|
+
if (start === -1) return [];
|
|
29
|
+
|
|
30
|
+
let depth = 1;
|
|
31
|
+
let pos = start + startMarker.length;
|
|
32
|
+
while (pos < src.length && depth > 0) {
|
|
33
|
+
const ch = src[pos];
|
|
34
|
+
if (ch === '(') depth += 1;
|
|
35
|
+
else if (ch === ')') depth -= 1;
|
|
36
|
+
pos += 1;
|
|
37
|
+
}
|
|
38
|
+
const argsStr = src.slice(start + startMarker.length, pos - 1);
|
|
39
|
+
|
|
40
|
+
// Match quoted method names: 'GET', "POST", etc. Only accept known methods.
|
|
41
|
+
const quotedMethodRe = /['"](GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)['"]/gi;
|
|
42
|
+
const seen = new Set();
|
|
43
|
+
let match;
|
|
44
|
+
while ((match = quotedMethodRe.exec(argsStr)) !== null) {
|
|
45
|
+
seen.add(match[1].toUpperCase());
|
|
46
|
+
}
|
|
47
|
+
if (seen.size === 0) return [];
|
|
48
|
+
|
|
49
|
+
const list = [...seen];
|
|
50
|
+
if (list.includes('GET') && !list.includes('HEAD')) {
|
|
51
|
+
list.push('HEAD');
|
|
52
|
+
}
|
|
53
|
+
return list;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Detects which HTTP methods the handler checks (e.g. ammo.GET, ammo.POST)
|
|
58
|
+
* or restricts via ammo.only('GET'), ammo.only('GET','POST').
|
|
59
|
+
* Prefers .only(...) when present with valid string args; otherwise matches
|
|
60
|
+
* property access like `.GET`, `ammo.GET`.
|
|
21
61
|
*
|
|
22
62
|
* When no method checks are found, the endpoint is treated as method-agnostic
|
|
23
63
|
* and accepts ALL methods (te.js default behavior).
|
|
@@ -29,8 +69,10 @@ function detectMethods(handler) {
|
|
|
29
69
|
if (typeof handler !== 'function') return [...ALL_METHODS];
|
|
30
70
|
|
|
31
71
|
const src = handler.toString();
|
|
32
|
-
const
|
|
72
|
+
const onlyMethods = detectOnlyMethods(src);
|
|
73
|
+
if (onlyMethods.length > 0) return onlyMethods;
|
|
33
74
|
|
|
75
|
+
const detected = [];
|
|
34
76
|
for (const m of ALL_METHODS) {
|
|
35
77
|
// Match property access patterns like .GET, ammo.GET, avoiding
|
|
36
78
|
// false positives in strings or unrelated identifiers
|
package/docs/configuration.md
CHANGED
|
@@ -59,6 +59,16 @@ app.takeoff();
|
|
|
59
59
|
| `log.http_requests` | `LOG_HTTP_REQUESTS` | boolean | `false` | Log incoming HTTP requests (method, path, status, time) |
|
|
60
60
|
| `log.exceptions` | `LOG_EXCEPTIONS` | boolean | `false` | Log unhandled exceptions and errors |
|
|
61
61
|
|
|
62
|
+
### Developer warnings
|
|
63
|
+
|
|
64
|
+
When an endpoint is called and it has no allowed methods defined (see [Routing — Endpoint Metadata](./routing.md#endpoint-metadata)), the framework logs a warning once per path so you can restrict methods for security (405 and `Allow` header). To disable this warning:
|
|
65
|
+
|
|
66
|
+
| Config Key | Env Variable | Type | Default | Description |
|
|
67
|
+
|------------|-------------|------|---------|-------------|
|
|
68
|
+
| `warn_missing_allowed_methods` | `WARN_MISSING_ALLOWED_METHODS` | boolean/string | *(warn)* | Set to `false` to disable the runtime warning for endpoints without allowed methods. |
|
|
69
|
+
|
|
70
|
+
Example: in `tejas.config.json` use `"warn_missing_allowed_methods": false`, or in `.env` use `WARN_MISSING_ALLOWED_METHODS=false`.
|
|
71
|
+
|
|
62
72
|
### Request Body
|
|
63
73
|
|
|
64
74
|
| Config Key | Env Variable | Type | Default | Description |
|
|
@@ -178,6 +188,9 @@ LLM_MODEL=gpt-4o-mini
|
|
|
178
188
|
# ERRORS_LLM_API_KEY=...
|
|
179
189
|
# ERRORS_LLM_MODEL=...
|
|
180
190
|
# ERRORS_LLM_MESSAGE_TYPE=endUser # or "developer" for technical messages
|
|
191
|
+
|
|
192
|
+
# Optional: disable runtime warning for endpoints without allowed methods
|
|
193
|
+
# WARN_MISSING_ALLOWED_METHODS=false
|
|
181
194
|
```
|
|
182
195
|
|
|
183
196
|
## Constructor Options
|
package/docs/routing.md
CHANGED
|
@@ -214,6 +214,8 @@ target.register('/users', {
|
|
|
214
214
|
|
|
215
215
|
When metadata is omitted, the auto-docs LLM infers everything from the handler source code.
|
|
216
216
|
|
|
217
|
+
If an endpoint has no `methods` in its metadata (and does not use `ammo.only()` to restrict methods), the framework logs a warning the first time that path is called. You can disable this warning via config: set `WARN_MISSING_ALLOWED_METHODS=false` (env) or `warn_missing_allowed_methods: false` in config. See [Configuration — Developer warnings](./configuration.md#developer-warnings).
|
|
218
|
+
|
|
217
219
|
## Method-Agnostic Handlers
|
|
218
220
|
|
|
219
221
|
If a handler does not check any method flags (`ammo.GET`, `ammo.POST`, etc.), it is treated as accepting **all HTTP methods**. This is useful for simple endpoints:
|
package/package.json
CHANGED
package/server/handler.js
CHANGED
|
@@ -7,6 +7,9 @@ import TejError from './error.js';
|
|
|
7
7
|
import targetRegistry from './targets/registry.js';
|
|
8
8
|
|
|
9
9
|
const errorLogger = new TejLogger('Tejas.Exception');
|
|
10
|
+
const logger = new TejLogger('Tejas');
|
|
11
|
+
/** Paths we have already warned about (missing allowed methods). */
|
|
12
|
+
const warnedPaths = new Set();
|
|
10
13
|
|
|
11
14
|
const DEFAULT_ALLOWED_METHODS = [
|
|
12
15
|
'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS',
|
|
@@ -134,6 +137,12 @@ const handler = async (req, res) => {
|
|
|
134
137
|
await errorHandler(ammo, new TejError(405, 'Method Not Allowed'));
|
|
135
138
|
return;
|
|
136
139
|
}
|
|
140
|
+
} else if (env('WARN_MISSING_ALLOWED_METHODS') !== 'false') {
|
|
141
|
+
const path = match.target.getPath();
|
|
142
|
+
if (!warnedPaths.has(path)) {
|
|
143
|
+
warnedPaths.add(path);
|
|
144
|
+
logger.warn(`Endpoint missing allowed methods: ${path}`);
|
|
145
|
+
}
|
|
137
146
|
}
|
|
138
147
|
|
|
139
148
|
// Add route parameters to ammo.payload
|