te.js 1.3.0 → 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/.cursor/plans/ai_native_framework_features_5bb1a20a.plan.md +234 -0
- package/.cursor/plans/auto_error_fix_agent_e68979c5.plan.md +356 -0
- package/.cursor/plans/tejas_framework_test_suite_5e3c6fad.plan.md +168 -0
- package/.prettierignore +31 -0
- package/README.md +156 -14
- package/auto-docs/analysis/handler-analyzer.js +58 -0
- package/auto-docs/analysis/source-resolver.js +101 -0
- package/auto-docs/constants.js +37 -0
- package/auto-docs/index.js +146 -0
- package/auto-docs/llm/index.js +6 -0
- package/auto-docs/llm/parse.js +88 -0
- package/auto-docs/llm/prompts.js +222 -0
- package/auto-docs/llm/provider.js +187 -0
- package/auto-docs/openapi/endpoint-processor.js +277 -0
- package/auto-docs/openapi/generator.js +107 -0
- package/auto-docs/openapi/level3.js +131 -0
- package/auto-docs/openapi/spec-builders.js +244 -0
- package/auto-docs/ui/docs-ui.js +186 -0
- package/auto-docs/utils/logger.js +17 -0
- package/auto-docs/utils/strip-usage.js +10 -0
- package/cli/docs-command.js +315 -0
- package/cli/fly-command.js +71 -0
- package/cli/index.js +57 -0
- package/database/index.js +163 -5
- package/database/mongodb.js +146 -0
- package/database/redis.js +201 -0
- package/docs/README.md +36 -0
- package/docs/ammo.md +362 -0
- package/docs/api-reference.md +489 -0
- package/docs/auto-docs.md +215 -0
- package/docs/cli.md +152 -0
- package/docs/configuration.md +233 -0
- package/docs/database.md +391 -0
- package/docs/error-handling.md +417 -0
- package/docs/file-uploads.md +334 -0
- package/docs/getting-started.md +181 -0
- package/docs/middleware.md +356 -0
- package/docs/rate-limiting.md +394 -0
- package/docs/routing.md +302 -0
- package/example/API_OVERVIEW.md +77 -0
- package/example/README.md +155 -0
- package/example/index.js +27 -2
- package/example/openapi.json +390 -0
- package/example/package.json +5 -2
- package/example/services/cache.service.js +25 -0
- package/example/services/user.service.js +42 -0
- package/example/start-redis.js +2 -0
- package/example/targets/cache.target.js +35 -0
- package/example/targets/index.target.js +11 -2
- package/example/targets/users.target.js +60 -0
- package/example/tejas.config.json +13 -1
- package/package.json +20 -5
- package/rate-limit/algorithms/fixed-window.js +141 -0
- package/rate-limit/algorithms/sliding-window.js +147 -0
- package/rate-limit/algorithms/token-bucket.js +115 -0
- package/rate-limit/base.js +165 -0
- package/rate-limit/index.js +147 -0
- package/rate-limit/storage/base.js +104 -0
- package/rate-limit/storage/memory.js +102 -0
- package/rate-limit/storage/redis.js +88 -0
- package/server/ammo/body-parser.js +152 -25
- package/server/ammo/enhancer.js +6 -2
- package/server/ammo.js +356 -327
- package/server/endpoint.js +21 -0
- package/server/handler.js +113 -87
- package/server/target.js +50 -9
- package/server/targets/registry.js +111 -6
- package/te.js +363 -137
- package/tests/auto-docs/handler-analyzer.test.js +44 -0
- package/tests/auto-docs/openapi-generator.test.js +103 -0
- package/tests/auto-docs/parse.test.js +63 -0
- package/tests/auto-docs/source-resolver.test.js +58 -0
- package/tests/helpers/index.js +37 -0
- package/tests/helpers/mock-http.js +342 -0
- package/tests/helpers/test-utils.js +446 -0
- package/tests/setup.test.js +148 -0
- package/utils/configuration.js +13 -10
- package/vitest.config.js +54 -0
- package/database/mongo.js +0 -67
- package/example/targets/user/user.target.js +0 -17
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Tejas Framework Test Suite
|
|
3
|
+
overview: Create a comprehensive test suite using Vitest for all core features of the Tejas framework, including unit tests, integration tests, edge cases, and error scenarios.
|
|
4
|
+
todos:
|
|
5
|
+
- id: setup-vitest
|
|
6
|
+
content: Set up Vitest configuration and install dependencies
|
|
7
|
+
status: completed
|
|
8
|
+
- id: test-helpers
|
|
9
|
+
content: Create test helper utilities and HTTP mocks
|
|
10
|
+
status: pending
|
|
11
|
+
- id: test-ammo
|
|
12
|
+
content: Write unit tests for Ammo class (fire, throw, redirect, shortcuts)
|
|
13
|
+
status: pending
|
|
14
|
+
- id: test-target-registry
|
|
15
|
+
content: Write tests for Target class and TargetRegistry route matching
|
|
16
|
+
status: pending
|
|
17
|
+
- id: test-body-parser
|
|
18
|
+
content: Write tests for body parser (JSON, URL-encoded, multipart)
|
|
19
|
+
status: pending
|
|
20
|
+
- id: test-rate-limiting
|
|
21
|
+
content: Write tests for all 3 rate limiting algorithms
|
|
22
|
+
status: pending
|
|
23
|
+
- id: test-file-uploader
|
|
24
|
+
content: Write tests for file upload middleware
|
|
25
|
+
status: pending
|
|
26
|
+
- id: test-configuration
|
|
27
|
+
content: Write tests for configuration loading and standardization
|
|
28
|
+
status: pending
|
|
29
|
+
- id: test-handler-integration
|
|
30
|
+
content: Write integration tests for request handler and middleware chain
|
|
31
|
+
status: pending
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
# Tejas Framework Test Suite Plan
|
|
35
|
+
|
|
36
|
+
Create comprehensive tests using Vitest for all core features of the Tejas framework, organized by module with unit, integration, and error scenario coverage.
|
|
37
|
+
|
|
38
|
+
## Test Infrastructure Setup
|
|
39
|
+
|
|
40
|
+
Install Vitest and configure for ES modules. Create test utilities and mocks for HTTP requests, database connections, and file system operations.**Files to create:**
|
|
41
|
+
|
|
42
|
+
- `vitest.config.js` - Vitest configuration with ESM support
|
|
43
|
+
- `tests/helpers/mock-http.js` - HTTP request/response mocks
|
|
44
|
+
- `tests/helpers/test-utils.js` - Common test utilities
|
|
45
|
+
|
|
46
|
+
## Core Module Tests
|
|
47
|
+
|
|
48
|
+
### 1. Ammo Class ([server/ammo.js](server/ammo.js))
|
|
49
|
+
|
|
50
|
+
Unit tests for the request/response handler:
|
|
51
|
+
|
|
52
|
+
- HTTP method flag initialization (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS)
|
|
53
|
+
- `fire()` response dispatch with various argument patterns (status only, data only, status+data, status+data+content-type)
|
|
54
|
+
- `redirect()` with default and custom status codes
|
|
55
|
+
- `throw()` error handling (TejError, Error instances, status codes, strings)
|
|
56
|
+
- `notFound()`, `notAllowed()`, `unauthorized()` shortcuts
|
|
57
|
+
- `enhance()` method populating request properties
|
|
58
|
+
|
|
59
|
+
### 2. Target & Registry ([server/target.js](server/target.js), [server/targets/registry.js](server/targets/registry.js))
|
|
60
|
+
|
|
61
|
+
Unit tests for routing:
|
|
62
|
+
|
|
63
|
+
- Target constructor with base path
|
|
64
|
+
- `midair()` middleware registration
|
|
65
|
+
- `register()` endpoint registration with path + handler + optional middlewares
|
|
66
|
+
- TargetRegistry singleton pattern
|
|
67
|
+
- `aim()` exact path matching
|
|
68
|
+
- `aim()` parameterized route matching (`/users/:id`, `/api/:category/:id`)
|
|
69
|
+
- `getAllEndpoints()` listing (flat and grouped)
|
|
70
|
+
|
|
71
|
+
### 3. Request Handler ([server/handler.js](server/handler.js))
|
|
72
|
+
|
|
73
|
+
Integration tests for request processing:
|
|
74
|
+
|
|
75
|
+
- Middleware chain execution order
|
|
76
|
+
- Global + target + route middleware composition
|
|
77
|
+
- Async middleware handling
|
|
78
|
+
- Error propagation through chain
|
|
79
|
+
- 404 handling for unmatched routes
|
|
80
|
+
- Response already sent detection
|
|
81
|
+
|
|
82
|
+
### 4. Body Parser ([server/ammo/body-parser.js](server/ammo/body-parser.js))
|
|
83
|
+
|
|
84
|
+
Unit tests for request body parsing:
|
|
85
|
+
|
|
86
|
+
- JSON body parsing (valid, invalid, empty)
|
|
87
|
+
- URL-encoded body parsing
|
|
88
|
+
- Multipart form data parsing with boundary extraction
|
|
89
|
+
- Body size limit enforcement (413 errors)
|
|
90
|
+
- Request timeout handling (408 errors)
|
|
91
|
+
- Missing content-type handling
|
|
92
|
+
|
|
93
|
+
### 5. Rate Limiting ([rate-limit/](rate-limit/))
|
|
94
|
+
|
|
95
|
+
Unit tests for each algorithm:
|
|
96
|
+
|
|
97
|
+
- **Fixed Window:** Counter increments, window reset, strict mode alignment
|
|
98
|
+
- **Sliding Window:** Weighted counts, timestamp pruning, window transitions
|
|
99
|
+
- **Token Bucket:** Token consumption, refill rate, burst handling
|
|
100
|
+
- Storage interface (memory operations)
|
|
101
|
+
- Rate limit header generation (standard, legacy, draft7, draft8)
|
|
102
|
+
- `onRateLimited` callback
|
|
103
|
+
|
|
104
|
+
### 6. File Uploader ([server/files/uploader.js](server/files/uploader.js))
|
|
105
|
+
|
|
106
|
+
Unit tests for file handling:
|
|
107
|
+
|
|
108
|
+
- Single file upload with `file()` middleware
|
|
109
|
+
- Multiple file upload with `files()` middleware
|
|
110
|
+
- File size validation (413 errors for oversized files)
|
|
111
|
+
- File metadata extraction (extension, mimetype, path)
|
|
112
|
+
- Non-multipart request passthrough
|
|
113
|
+
- Directory creation
|
|
114
|
+
|
|
115
|
+
### 7. Configuration ([utils/configuration.js](utils/configuration.js))
|
|
116
|
+
|
|
117
|
+
Unit tests for config processing:
|
|
118
|
+
|
|
119
|
+
- `loadConfigFile()` file reading and JSON parsing
|
|
120
|
+
- `standardizeObj()` key uppercasing and flattening
|
|
121
|
+
- Missing config file handling
|
|
122
|
+
- Nested object flattening with underscores
|
|
123
|
+
|
|
124
|
+
### 8. TejError ([server/error.js](server/error.js))
|
|
125
|
+
|
|
126
|
+
Unit tests for custom error:
|
|
127
|
+
|
|
128
|
+
- Constructor with code and message
|
|
129
|
+
- Error inheritance
|
|
130
|
+
- Name property
|
|
131
|
+
|
|
132
|
+
### 9. Database Manager ([database/index.js](database/index.js))
|
|
133
|
+
|
|
134
|
+
Unit tests (mocked connections):
|
|
135
|
+
|
|
136
|
+
- Singleton pattern enforcement
|
|
137
|
+
- Connection initialization tracking
|
|
138
|
+
- `hasConnection()` status checking
|
|
139
|
+
- `getConnection()` retrieval
|
|
140
|
+
- Connection not found error
|
|
141
|
+
|
|
142
|
+
## Test File Structure
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
tests/
|
|
146
|
+
helpers/
|
|
147
|
+
mock-http.js
|
|
148
|
+
test-utils.js
|
|
149
|
+
unit/
|
|
150
|
+
ammo.test.js
|
|
151
|
+
target.test.js
|
|
152
|
+
registry.test.js
|
|
153
|
+
body-parser.test.js
|
|
154
|
+
rate-limit/
|
|
155
|
+
fixed-window.test.js
|
|
156
|
+
sliding-window.test.js
|
|
157
|
+
token-bucket.test.js
|
|
158
|
+
file-uploader.test.js
|
|
159
|
+
configuration.test.js
|
|
160
|
+
tej-error.test.js
|
|
161
|
+
database-manager.test.js
|
|
162
|
+
integration/
|
|
163
|
+
handler.test.js
|
|
164
|
+
middleware-chain.test.js
|
|
165
|
+
rate-limit-middleware.test.js
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
```
|
package/.prettierignore
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules/
|
|
3
|
+
package-lock.json
|
|
4
|
+
yarn.lock
|
|
5
|
+
|
|
6
|
+
# Build output
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.min.js
|
|
10
|
+
|
|
11
|
+
# Coverage directory
|
|
12
|
+
coverage/
|
|
13
|
+
|
|
14
|
+
# Cache directories
|
|
15
|
+
.cache/
|
|
16
|
+
.npm/
|
|
17
|
+
|
|
18
|
+
# Logs
|
|
19
|
+
logs/
|
|
20
|
+
*.log
|
|
21
|
+
npm-debug.log*
|
|
22
|
+
|
|
23
|
+
# IDE specific files
|
|
24
|
+
.idea/
|
|
25
|
+
.vscode/
|
|
26
|
+
*.swp
|
|
27
|
+
*.swo
|
|
28
|
+
|
|
29
|
+
# System Files
|
|
30
|
+
.DS_Store
|
|
31
|
+
Thumbs.db
|
package/README.md
CHANGED
|
@@ -1,20 +1,162 @@
|
|
|
1
|
-
<
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://tejas-documentation.vercel.app/tejas-logo.svg" alt="Tejas Logo" width="200">
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
<
|
|
5
|
+
<h1 align="center">Tejas</h1>
|
|
4
6
|
|
|
5
|
-
<p
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>A Node.js Framework for Powerful Backend Services</strong>
|
|
9
|
+
</p>
|
|
6
10
|
|
|
7
|
-
<
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="https://www.npmjs.com/package/te.js"><img src="https://img.shields.io/npm/v/te.js.svg" alt="npm version"></a>
|
|
13
|
+
<a href="https://www.npmjs.com/package/te.js"><img src="https://img.shields.io/npm/dm/te.js.svg" alt="npm downloads"></a>
|
|
14
|
+
<a href="https://github.com/hirakchhatbar/te.js/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/te.js.svg" alt="license"></a>
|
|
15
|
+
</p>
|
|
8
16
|
|
|
9
|
-
<
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="https://tejas-documentation.vercel.app">Documentation</a> •
|
|
19
|
+
<a href="#quick-start">Quick Start</a> •
|
|
20
|
+
<a href="#features">Features</a> •
|
|
21
|
+
<a href="./docs">Full Docs</a>
|
|
22
|
+
</p>
|
|
10
23
|
|
|
24
|
+
---
|
|
11
25
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
## What is Tejas?
|
|
27
|
+
|
|
28
|
+
Tejas (meaning "radiance" in Hindi) is a modern, lightweight Node.js framework designed for building robust backend services. It offers an intuitive API with aviation-inspired naming conventions, making your code both expressive and enjoyable to write.
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
import Tejas, { Target } from 'te.js';
|
|
32
|
+
|
|
33
|
+
const app = new Tejas();
|
|
34
|
+
const api = new Target('/api');
|
|
35
|
+
|
|
36
|
+
api.register('/hello/:name', (ammo) => {
|
|
37
|
+
ammo.fire({ message: `Hello, ${ammo.payload.name}!` });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
app.takeoff();
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- **Simple Routing** — Clean, method-agnostic URL structures with parameterized routes
|
|
46
|
+
- **Express Compatible** — Use existing Express middleware alongside Tejas middleware
|
|
47
|
+
- **Zero-Config Error Handling** — No try-catch needed! Tejas catches all errors automatically
|
|
48
|
+
- **Built-in Rate Limiting** — Three algorithms (Token Bucket, Sliding Window, Fixed Window) with memory or Redis storage
|
|
49
|
+
- **Database Ready** — First-class Redis and MongoDB support with auto-install of drivers
|
|
50
|
+
- **File Uploads** — Easy file handling with size limits and type validation
|
|
51
|
+
- **Auto-Documentation** — Generate OpenAPI specs from your code with LLM-powered analysis (`tejas generate:docs`)
|
|
52
|
+
- **Interactive API Docs** — Serve a Scalar API reference UI with `app.serveDocs()`
|
|
53
|
+
- **Auto-Discovery** — Automatic route registration from `.target.js` files
|
|
54
|
+
- **Request Logging** — Built-in HTTP request and exception logging
|
|
55
|
+
|
|
56
|
+
## Quick Start
|
|
57
|
+
|
|
58
|
+
### Install
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
npm install te.js
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Create Your App
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
// index.js
|
|
68
|
+
import Tejas from 'te.js';
|
|
69
|
+
|
|
70
|
+
const app = new Tejas({ port: 3000 });
|
|
71
|
+
app.takeoff();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Define Routes
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
// targets/user.target.js
|
|
78
|
+
import { Target } from 'te.js';
|
|
79
|
+
|
|
80
|
+
const users = new Target('/users');
|
|
81
|
+
|
|
82
|
+
users.register('/', (ammo) => {
|
|
83
|
+
if (ammo.GET) {
|
|
84
|
+
ammo.fire([{ id: 1, name: 'John' }]);
|
|
85
|
+
} else if (ammo.POST) {
|
|
86
|
+
const { name, email } = ammo.payload;
|
|
87
|
+
ammo.fire(201, { id: 2, name, email });
|
|
88
|
+
} else {
|
|
89
|
+
ammo.notAllowed();
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
users.register('/:id', (ammo) => {
|
|
94
|
+
const { id } = ammo.payload;
|
|
95
|
+
ammo.fire({ id, name: 'John Doe' });
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Run
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
node index.js
|
|
103
|
+
# Server running at http://localhost:3000
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Core Concepts
|
|
107
|
+
|
|
108
|
+
| Tejas Term | Purpose | Express Equivalent |
|
|
109
|
+
| ----------- | ------------------------ | ------------------ |
|
|
110
|
+
| `Tejas` | Application instance | `express()` |
|
|
111
|
+
| `Target` | Route group/router | `Router()` |
|
|
112
|
+
| `Ammo` | Request/response context | `req` + `res` |
|
|
113
|
+
| `fire()` | Send response | `res.send()` |
|
|
114
|
+
| `midair()` | Register middleware | `use()` |
|
|
115
|
+
| `takeoff()` | Start server | `listen()` |
|
|
116
|
+
|
|
117
|
+
## CLI
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
tejas fly [file] # Start the server
|
|
121
|
+
tejas generate:docs [--ci] # Generate OpenAPI docs (interactive or CI mode)
|
|
122
|
+
tejas docs:on-push # Auto-generate docs when pushing to production branch
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## API Documentation
|
|
126
|
+
|
|
127
|
+
Generate and serve interactive API docs:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npx tejas generate:docs
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
app.serveDocs({ specPath: './openapi.json' });
|
|
135
|
+
app.takeoff();
|
|
136
|
+
// Visit http://localhost:1403/docs
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Documentation
|
|
140
|
+
|
|
141
|
+
For comprehensive documentation, see the [docs folder](./docs) or visit [tejas-documentation.vercel.app](https://tejas-documentation.vercel.app).
|
|
142
|
+
|
|
143
|
+
- [Getting Started](./docs/getting-started.md) — Installation and quick start
|
|
144
|
+
- [Configuration](./docs/configuration.md) — All configuration options
|
|
145
|
+
- [Routing](./docs/routing.md) — Target-based routing system
|
|
146
|
+
- [Ammo](./docs/ammo.md) — Request/response handling
|
|
147
|
+
- [Middleware](./docs/middleware.md) — Global, target, and route middleware
|
|
148
|
+
- [Error Handling](./docs/error-handling.md) — Zero-config error handling
|
|
149
|
+
- [Database](./docs/database.md) — Redis and MongoDB integration
|
|
150
|
+
- [Rate Limiting](./docs/rate-limiting.md) — API protection
|
|
151
|
+
- [File Uploads](./docs/file-uploads.md) — File handling
|
|
152
|
+
- [CLI Reference](./docs/cli.md) — Command-line interface
|
|
153
|
+
- [Auto-Documentation](./docs/auto-docs.md) — OpenAPI generation
|
|
154
|
+
- [API Reference](./docs/api-reference.md) — Complete API docs
|
|
155
|
+
|
|
156
|
+
## Contributing
|
|
157
|
+
|
|
158
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
159
|
+
|
|
160
|
+
## License
|
|
161
|
+
|
|
162
|
+
ISC © [Hirak Chhatbar](https://github.com/hirakchhatbar)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handler analyzer for auto-documentation.
|
|
3
|
+
* Detects HTTP methods and extracts basic info from handler source via handler.toString().
|
|
4
|
+
* Used when endpoint metadata does not declare `methods`; otherwise explicit metadata wins.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const ALL_METHODS = [
|
|
8
|
+
'GET',
|
|
9
|
+
'POST',
|
|
10
|
+
'PUT',
|
|
11
|
+
'DELETE',
|
|
12
|
+
'PATCH',
|
|
13
|
+
'HEAD',
|
|
14
|
+
'OPTIONS',
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Detects which HTTP methods the handler checks (e.g. ammo.GET, ammo.POST).
|
|
19
|
+
* Matches property access patterns like `.GET`, `ammo.GET`, avoiding false positives
|
|
20
|
+
* in strings or unrelated identifiers.
|
|
21
|
+
*
|
|
22
|
+
* When no method checks are found, the endpoint is treated as method-agnostic
|
|
23
|
+
* and accepts ALL methods (te.js default behavior).
|
|
24
|
+
*
|
|
25
|
+
* @param {Function} handler - The endpoint handler function
|
|
26
|
+
* @returns {string[]} Detected method names, or ALL_METHODS if none detected
|
|
27
|
+
*/
|
|
28
|
+
function detectMethods(handler) {
|
|
29
|
+
if (typeof handler !== 'function') return [...ALL_METHODS];
|
|
30
|
+
|
|
31
|
+
const src = handler.toString();
|
|
32
|
+
const detected = [];
|
|
33
|
+
|
|
34
|
+
for (const m of ALL_METHODS) {
|
|
35
|
+
// Match property access patterns like .GET, ammo.GET, avoiding
|
|
36
|
+
// false positives in strings or unrelated identifiers
|
|
37
|
+
const pattern = new RegExp(`\\.${m}\\b`);
|
|
38
|
+
if (pattern.test(src)) detected.push(m);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return detected.length > 0 ? detected : [...ALL_METHODS];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Analyzes a handler and returns basic info for documentation (e.g. OpenAPI).
|
|
46
|
+
* Explicit metadata from register() should override these results when present.
|
|
47
|
+
*
|
|
48
|
+
* @param {Function} handler - The endpoint handler function
|
|
49
|
+
* @returns {{ methods: string[] }} Analyzed info (methods; more fields can be added later)
|
|
50
|
+
*/
|
|
51
|
+
function analyzeHandler(handler) {
|
|
52
|
+
return {
|
|
53
|
+
methods: detectMethods(handler),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export { ALL_METHODS, detectMethods, analyzeHandler };
|
|
58
|
+
export default analyzeHandler;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves downstream dependency sources for level-2 documentation (handler + deps context).
|
|
3
|
+
* Reads a target file, extracts relative imports, and returns their source code.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readFile } from 'node:fs/promises';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import { DEPENDENCY_CONTEXT_MAX_CHARS } from '../constants.js';
|
|
9
|
+
|
|
10
|
+
/** Match ES module imports: import x from './...' or import { x } from '../...' or import '...' */
|
|
11
|
+
const IMPORT_REGEX = /import\s+(?:(?:\{[^}]*\}|\w+)(?:\s*,\s*(?:\{[^}]*\}|\w+))*\s+from\s+)?['"]([^'"]+)['"]/g;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Extract import specifiers that are relative paths (./ or ../).
|
|
15
|
+
* @param {string} source - File source code
|
|
16
|
+
* @returns {string[]} Relative paths (e.g. ['../services/user.service.js'])
|
|
17
|
+
*/
|
|
18
|
+
function extractRelativeImports(source) {
|
|
19
|
+
const out = [];
|
|
20
|
+
let match;
|
|
21
|
+
IMPORT_REGEX.lastIndex = 0;
|
|
22
|
+
while ((match = IMPORT_REGEX.exec(source)) !== null) {
|
|
23
|
+
const spec = match[1];
|
|
24
|
+
if (spec.startsWith('./') || spec.startsWith('../')) {
|
|
25
|
+
out.push(spec);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return [...new Set(out)];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resolve target file path from groupId and DIR_TARGETS.
|
|
33
|
+
* @param {string} groupId - e.g. 'users' or 'subdir/users'
|
|
34
|
+
* @param {string} dirTargets - e.g. 'targets'
|
|
35
|
+
* @returns {string} Absolute path to the target file
|
|
36
|
+
*/
|
|
37
|
+
function resolveTargetFilePath(groupId, dirTargets = 'targets') {
|
|
38
|
+
const baseDir = path.join(process.cwd(), dirTargets);
|
|
39
|
+
const relative = groupId.replace(/\//g, path.sep) + '.target.js';
|
|
40
|
+
return path.join(baseDir, relative);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Read a target file and all its relative-import dependencies (one level deep).
|
|
45
|
+
* @param {string} groupId - Source group id (e.g. 'users')
|
|
46
|
+
* @param {string} [dirTargets] - DIR_TARGETS (default from process.env or 'targets')
|
|
47
|
+
* @returns {Promise<Map<string, string>>} Map of absolute file path -> source code
|
|
48
|
+
*/
|
|
49
|
+
export async function resolveDependencySources(groupId, dirTargets = process.env.DIR_TARGETS || 'targets') {
|
|
50
|
+
const targetPath = resolveTargetFilePath(groupId, dirTargets);
|
|
51
|
+
const result = new Map();
|
|
52
|
+
|
|
53
|
+
let targetSource;
|
|
54
|
+
try {
|
|
55
|
+
targetSource = await readFile(targetPath, 'utf8');
|
|
56
|
+
} catch {
|
|
57
|
+
return result;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
result.set(targetPath, targetSource);
|
|
61
|
+
const targetDir = path.dirname(targetPath);
|
|
62
|
+
const relativeImports = extractRelativeImports(targetSource);
|
|
63
|
+
|
|
64
|
+
for (const rel of relativeImports) {
|
|
65
|
+
const resolvedPath = path.resolve(targetDir, rel);
|
|
66
|
+
try {
|
|
67
|
+
const code = await readFile(resolvedPath, 'utf8');
|
|
68
|
+
result.set(resolvedPath, code);
|
|
69
|
+
} catch {
|
|
70
|
+
// Skip missing or unreadable files
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Format resolved dependency sources as a single string for LLM context.
|
|
79
|
+
* @param {Map<string, string>} sources - Map of file path -> source
|
|
80
|
+
* @param {string} [targetPath] - Path to the target file (excluded from "dependencies" label)
|
|
81
|
+
* @param {number} [maxChars] - Max total characters to include (default: DEPENDENCY_CONTEXT_MAX_CHARS)
|
|
82
|
+
* @returns {string}
|
|
83
|
+
*/
|
|
84
|
+
export function formatDependencyContext(sources, targetPath, maxChars = DEPENDENCY_CONTEXT_MAX_CHARS) {
|
|
85
|
+
if (!sources || sources.size === 0) return '';
|
|
86
|
+
const lines = [];
|
|
87
|
+
let total = 0;
|
|
88
|
+
for (const [filePath, code] of sources) {
|
|
89
|
+
const label = filePath === targetPath ? 'Target' : path.relative(process.cwd(), filePath);
|
|
90
|
+
const block = `\n// --- ${label} ---\n${code}`;
|
|
91
|
+
if (total + block.length > maxChars) {
|
|
92
|
+
lines.push(block.slice(0, maxChars - total) + '\n// ... (truncated)');
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
95
|
+
lines.push(block);
|
|
96
|
+
total += block.length;
|
|
97
|
+
}
|
|
98
|
+
return lines.join('\n');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { extractRelativeImports, resolveTargetFilePath };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared constants for auto-documentation.
|
|
3
|
+
* Centralizes OpenAPI version, method keys, and token/character limits.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** OpenAPI 3.0 version string */
|
|
7
|
+
export const OPENAPI_VERSION = '3.0.3';
|
|
8
|
+
|
|
9
|
+
/** Lowercase HTTP method names (for method-keyed LLM response detection and OpenAPI operation keys). */
|
|
10
|
+
export const METHOD_KEYS = new Set(['get', 'put', 'post', 'delete', 'patch', 'head', 'options']);
|
|
11
|
+
|
|
12
|
+
/** When an endpoint accepts all HTTP methods, document it once under this key. */
|
|
13
|
+
export const METHOD_AGNOSTIC_OPERATION_KEY = 'get';
|
|
14
|
+
|
|
15
|
+
/** Max handler source length by level (chars; tokens roughly scale). Level 1 = moderate, 2 = high. */
|
|
16
|
+
export const HANDLER_SOURCE_MAX_LENGTH_BY_LEVEL = { 1: 2800, 2: 6000 };
|
|
17
|
+
|
|
18
|
+
/** Default max chars for dependency context in formatDependencyContext and level-2 prompts. */
|
|
19
|
+
export const DEPENDENCY_CONTEXT_MAX_CHARS = 6000;
|
|
20
|
+
|
|
21
|
+
/** Max handler source chars in single-endpoint enhance prompts (no deps). */
|
|
22
|
+
export const PROMPT_HANDLER_SLICE = 3000;
|
|
23
|
+
|
|
24
|
+
/** Max handler source chars in single-endpoint enhance prompts (with deps). */
|
|
25
|
+
export const PROMPT_HANDLER_SLICE_WITH_DEPS = 4000;
|
|
26
|
+
|
|
27
|
+
/** Max dependency source chars included in enhance/summarize prompts. */
|
|
28
|
+
export const PROMPT_DEPENDENCY_SLICE = 5000;
|
|
29
|
+
|
|
30
|
+
/** Max total code chars in group-summary prompt when no dependency context. */
|
|
31
|
+
export const PROMPT_GROUP_CODE_LIMIT = 4000;
|
|
32
|
+
|
|
33
|
+
/** Max total code chars in group-summary prompt when dependency context is present. */
|
|
34
|
+
export const PROMPT_GROUP_CODE_LIMIT_WITH_DEPS = 6000;
|
|
35
|
+
|
|
36
|
+
/** Max handler source chars per endpoint in group-summary code snippets. */
|
|
37
|
+
export const PROMPT_GROUP_SNIPPET_CHARS = 800;
|