te.js 2.0.3 → 2.1.1
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 +197 -187
- package/auto-docs/analysis/handler-analyzer.js +58 -58
- package/auto-docs/analysis/source-resolver.js +101 -101
- package/auto-docs/constants.js +37 -37
- package/auto-docs/docs-llm/index.js +7 -0
- package/auto-docs/{llm → docs-llm}/prompts.js +222 -222
- package/auto-docs/{llm → docs-llm}/provider.js +132 -187
- package/auto-docs/index.js +146 -146
- package/auto-docs/openapi/endpoint-processor.js +277 -277
- package/auto-docs/openapi/generator.js +107 -107
- package/auto-docs/openapi/level3.js +131 -131
- package/auto-docs/openapi/spec-builders.js +244 -244
- package/auto-docs/ui/docs-ui.js +186 -186
- package/auto-docs/utils/logger.js +17 -17
- package/auto-docs/utils/strip-usage.js +10 -10
- package/cli/docs-command.js +315 -315
- package/cli/fly-command.js +71 -71
- package/cli/index.js +56 -56
- package/database/index.js +165 -165
- package/database/mongodb.js +146 -146
- package/database/redis.js +201 -201
- package/docs/README.md +36 -36
- package/docs/ammo.md +362 -362
- package/docs/api-reference.md +490 -489
- package/docs/auto-docs.md +216 -215
- package/docs/cli.md +152 -152
- package/docs/configuration.md +275 -233
- package/docs/database.md +390 -391
- package/docs/error-handling.md +438 -417
- package/docs/file-uploads.md +333 -334
- package/docs/getting-started.md +214 -215
- package/docs/middleware.md +355 -356
- package/docs/rate-limiting.md +393 -394
- package/docs/routing.md +302 -302
- package/package.json +62 -62
- package/rate-limit/algorithms/fixed-window.js +141 -141
- package/rate-limit/algorithms/sliding-window.js +147 -147
- package/rate-limit/algorithms/token-bucket.js +115 -115
- package/rate-limit/base.js +165 -165
- package/rate-limit/index.js +147 -147
- package/rate-limit/storage/base.js +104 -104
- package/rate-limit/storage/memory.js +101 -101
- package/rate-limit/storage/redis.js +88 -88
- package/server/ammo/body-parser.js +220 -220
- package/server/ammo/dispatch-helper.js +103 -103
- package/server/ammo/enhancer.js +57 -57
- package/server/ammo.js +454 -356
- package/server/endpoint.js +97 -74
- package/server/error.js +9 -9
- package/server/errors/code-context.js +125 -0
- package/server/errors/llm-error-service.js +140 -0
- package/server/files/helper.js +33 -33
- package/server/files/uploader.js +143 -143
- package/server/handler.js +158 -113
- package/server/target.js +185 -175
- package/server/targets/middleware-validator.js +22 -22
- package/server/targets/path-validator.js +21 -21
- package/server/targets/registry.js +160 -160
- package/server/targets/shoot-validator.js +21 -21
- package/te.js +428 -363
- package/utils/auto-register.js +17 -17
- package/utils/configuration.js +64 -64
- package/utils/errors-llm-config.js +84 -0
- package/utils/request-logger.js +43 -43
- package/utils/status-codes.js +82 -82
- package/utils/tejas-entrypoint-html.js +18 -18
- package/auto-docs/llm/index.js +0 -6
- package/auto-docs/llm/parse.js +0 -88
package/server/target.js
CHANGED
|
@@ -1,175 +1,185 @@
|
|
|
1
|
-
import TejLogger from 'tej-logger';
|
|
2
|
-
|
|
3
|
-
import isMiddlewareValid from './targets/middleware-validator.js';
|
|
4
|
-
import Endpoint from './endpoint.js';
|
|
5
|
-
|
|
6
|
-
import targetRegistry from './targets/registry.js';
|
|
7
|
-
|
|
8
|
-
const logger = new TejLogger('Target');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Target class represents a base routing configuration for endpoints. Think of it as router in express.
|
|
12
|
-
* It provides functionality to set base paths, add middleware, and register endpoints.
|
|
13
|
-
*
|
|
14
|
-
* @class
|
|
15
|
-
* @example
|
|
16
|
-
* // Create a new target for user-related endpoints
|
|
17
|
-
* const userTarget = new Target('/user');
|
|
18
|
-
*
|
|
19
|
-
* // Add middleware that applies to all user endpoints
|
|
20
|
-
* userTarget.midair(authMiddleware, loggingMiddleware);
|
|
21
|
-
*
|
|
22
|
-
* // Register endpoints
|
|
23
|
-
* userTarget.register('/profile', (ammo) => {
|
|
24
|
-
* // Handle GET /user/profile
|
|
25
|
-
* ammo.fire({ name: 'John Doe' });
|
|
26
|
-
* });
|
|
27
|
-
*
|
|
28
|
-
* userTarget.register('/settings', authMiddleware, (ammo) => {
|
|
29
|
-
* // Handle GET /user/settings with additional auth middleware
|
|
30
|
-
* ammo.fire({ theme: 'dark' });
|
|
31
|
-
* });
|
|
32
|
-
*/
|
|
33
|
-
class Target {
|
|
34
|
-
/**
|
|
35
|
-
* Creates a new Target instance.
|
|
36
|
-
*
|
|
37
|
-
* @param {string} [base=''] - The base path for all endpoints registered under this target.
|
|
38
|
-
* Must start with '/' if provided.
|
|
39
|
-
* @example
|
|
40
|
-
* const apiTarget = new Target('/api');
|
|
41
|
-
* const userTarget = new Target('/user');
|
|
42
|
-
*/
|
|
43
|
-
constructor(base = '') {
|
|
44
|
-
this.base = base;
|
|
45
|
-
this.targetMiddlewares = [];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Sets the base path for the target.
|
|
50
|
-
*
|
|
51
|
-
* @param {string} base - The base path to set. Must start with '/'.
|
|
52
|
-
* @returns {void}
|
|
53
|
-
* @example
|
|
54
|
-
* const target = new Target();
|
|
55
|
-
* target.base('/api/v1');
|
|
56
|
-
*/
|
|
57
|
-
base(base) {
|
|
58
|
-
if (!base || !base.startsWith('/')) return;
|
|
59
|
-
this.base = base;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Adds middleware functions to the target.
|
|
64
|
-
* These middleware functions will be applied to all endpoints registered under this target.
|
|
65
|
-
*
|
|
66
|
-
* @param {...Function} middlewares - One or more middleware functions to add.
|
|
67
|
-
* @returns {void}
|
|
68
|
-
* @example
|
|
69
|
-
* // Add authentication middleware to all endpoints
|
|
70
|
-
* target.midair(authMiddleware);
|
|
71
|
-
*
|
|
72
|
-
* // Add multiple middleware functions
|
|
73
|
-
* target.midair(loggingMiddleware, errorHandler, rateLimiter);
|
|
74
|
-
*/
|
|
75
|
-
midair() {
|
|
76
|
-
if (!arguments) return;
|
|
77
|
-
const middlewares = [...arguments];
|
|
78
|
-
|
|
79
|
-
const validMiddlewares = middlewares.filter(isMiddlewareValid);
|
|
80
|
-
this.targetMiddlewares = this.targetMiddlewares.concat(validMiddlewares);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Registers a new endpoint under this target.
|
|
85
|
-
*
|
|
86
|
-
* @param {string} path - The path for the endpoint, relative to the base path.
|
|
87
|
-
* @param {
|
|
88
|
-
* @param {Function}
|
|
89
|
-
* @
|
|
90
|
-
* @
|
|
91
|
-
* @
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* });
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* (
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const
|
|
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
|
-
endpoint
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
1
|
+
import TejLogger from 'tej-logger';
|
|
2
|
+
|
|
3
|
+
import isMiddlewareValid from './targets/middleware-validator.js';
|
|
4
|
+
import Endpoint from './endpoint.js';
|
|
5
|
+
|
|
6
|
+
import targetRegistry from './targets/registry.js';
|
|
7
|
+
|
|
8
|
+
const logger = new TejLogger('Target');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Target class represents a base routing configuration for endpoints. Think of it as router in express.
|
|
12
|
+
* It provides functionality to set base paths, add middleware, and register endpoints.
|
|
13
|
+
*
|
|
14
|
+
* @class
|
|
15
|
+
* @example
|
|
16
|
+
* // Create a new target for user-related endpoints
|
|
17
|
+
* const userTarget = new Target('/user');
|
|
18
|
+
*
|
|
19
|
+
* // Add middleware that applies to all user endpoints
|
|
20
|
+
* userTarget.midair(authMiddleware, loggingMiddleware);
|
|
21
|
+
*
|
|
22
|
+
* // Register endpoints
|
|
23
|
+
* userTarget.register('/profile', (ammo) => {
|
|
24
|
+
* // Handle GET /user/profile
|
|
25
|
+
* ammo.fire({ name: 'John Doe' });
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* userTarget.register('/settings', authMiddleware, (ammo) => {
|
|
29
|
+
* // Handle GET /user/settings with additional auth middleware
|
|
30
|
+
* ammo.fire({ theme: 'dark' });
|
|
31
|
+
* });
|
|
32
|
+
*/
|
|
33
|
+
class Target {
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new Target instance.
|
|
36
|
+
*
|
|
37
|
+
* @param {string} [base=''] - The base path for all endpoints registered under this target.
|
|
38
|
+
* Must start with '/' if provided.
|
|
39
|
+
* @example
|
|
40
|
+
* const apiTarget = new Target('/api');
|
|
41
|
+
* const userTarget = new Target('/user');
|
|
42
|
+
*/
|
|
43
|
+
constructor(base = '') {
|
|
44
|
+
this.base = base;
|
|
45
|
+
this.targetMiddlewares = [];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Sets the base path for the target.
|
|
50
|
+
*
|
|
51
|
+
* @param {string} base - The base path to set. Must start with '/'.
|
|
52
|
+
* @returns {void}
|
|
53
|
+
* @example
|
|
54
|
+
* const target = new Target();
|
|
55
|
+
* target.base('/api/v1');
|
|
56
|
+
*/
|
|
57
|
+
base(base) {
|
|
58
|
+
if (!base || !base.startsWith('/')) return;
|
|
59
|
+
this.base = base;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Adds middleware functions to the target.
|
|
64
|
+
* These middleware functions will be applied to all endpoints registered under this target.
|
|
65
|
+
*
|
|
66
|
+
* @param {...Function} middlewares - One or more middleware functions to add.
|
|
67
|
+
* @returns {void}
|
|
68
|
+
* @example
|
|
69
|
+
* // Add authentication middleware to all endpoints
|
|
70
|
+
* target.midair(authMiddleware);
|
|
71
|
+
*
|
|
72
|
+
* // Add multiple middleware functions
|
|
73
|
+
* target.midair(loggingMiddleware, errorHandler, rateLimiter);
|
|
74
|
+
*/
|
|
75
|
+
midair() {
|
|
76
|
+
if (!arguments) return;
|
|
77
|
+
const middlewares = [...arguments];
|
|
78
|
+
|
|
79
|
+
const validMiddlewares = middlewares.filter(isMiddlewareValid);
|
|
80
|
+
this.targetMiddlewares = this.targetMiddlewares.concat(validMiddlewares);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Registers a new endpoint under this target.
|
|
85
|
+
*
|
|
86
|
+
* @param {string} path - The path for the endpoint, relative to the base path.
|
|
87
|
+
* @param {Object} [metadata] - Optional metadata. If the second argument is a plain object, it is treated as metadata (e.g. { methods: ['GET', 'POST'] }). When `methods` is set, the framework returns 405 for other HTTP methods before the handler runs. HEAD is allowed automatically when GET is in the list.
|
|
88
|
+
* @param {...Function} [middlewares] - Optional middleware functions specific to this endpoint.
|
|
89
|
+
* @param {Function} shoot - The handler function for the endpoint.
|
|
90
|
+
* @returns {void}
|
|
91
|
+
* @throws {Error} If there's an error registering the endpoint.
|
|
92
|
+
* @example
|
|
93
|
+
* // Register a simple endpoint
|
|
94
|
+
* target.register('/hello', (ammo) => {
|
|
95
|
+
* ammo.fire({ message: 'Hello World' });
|
|
96
|
+
* });
|
|
97
|
+
*
|
|
98
|
+
* // Register with allowed methods (405 + Allow header for others)
|
|
99
|
+
* target.register('/users', { methods: ['GET', 'POST'] }, (ammo) => {
|
|
100
|
+
* if (ammo.GET) return ammo.fire(userService.list());
|
|
101
|
+
* if (ammo.POST) return ammo.fire(201, userService.create(ammo.payload));
|
|
102
|
+
* });
|
|
103
|
+
*
|
|
104
|
+
* // Register an endpoint with specific middleware
|
|
105
|
+
* target.register('/protected', authMiddleware, (ammo) => {
|
|
106
|
+
* ammo.fire({ data: 'Protected data' });
|
|
107
|
+
* });
|
|
108
|
+
*
|
|
109
|
+
* // Register an endpoint with multiple middleware
|
|
110
|
+
* target.register('/api/data',
|
|
111
|
+
* authMiddleware,
|
|
112
|
+
* rateLimiter,
|
|
113
|
+
* (ammo) => {
|
|
114
|
+
* ammo.fire({ data: 'Rate limited data' });
|
|
115
|
+
* }
|
|
116
|
+
* );
|
|
117
|
+
*/
|
|
118
|
+
register() {
|
|
119
|
+
const args = Array.from(arguments);
|
|
120
|
+
if (args.length < 2) {
|
|
121
|
+
logger.error('register(path, [...middlewares], handler) requires at least path and handler. Skipping.');
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const path = args[0];
|
|
126
|
+
const shoot = args[args.length - 1];
|
|
127
|
+
|
|
128
|
+
if (typeof path !== 'string') {
|
|
129
|
+
logger.error(`register() path must be a string, got ${typeof path}. Skipping.`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (typeof shoot !== 'function') {
|
|
133
|
+
logger.error(`register() last argument (handler) must be a function, got ${typeof shoot}. Skipping.`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const second = args[1];
|
|
138
|
+
const isPlainObject = (v) =>
|
|
139
|
+
typeof v === 'object' &&
|
|
140
|
+
v !== null &&
|
|
141
|
+
!Array.isArray(v) &&
|
|
142
|
+
(Object.getPrototypeOf(v) === Object.prototype || Object.getPrototypeOf(v) === null);
|
|
143
|
+
const isMetadataObject = isPlainObject(second);
|
|
144
|
+
|
|
145
|
+
let middlewares;
|
|
146
|
+
let metadata = null;
|
|
147
|
+
if (isMetadataObject && args.length >= 3) {
|
|
148
|
+
metadata = second;
|
|
149
|
+
middlewares = args.slice(2, -1);
|
|
150
|
+
} else {
|
|
151
|
+
middlewares = args.slice(1, -1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
try {
|
|
155
|
+
const endpoint = new Endpoint();
|
|
156
|
+
endpoint.setPath(this.base, path);
|
|
157
|
+
if (!endpoint.getPath()) {
|
|
158
|
+
logger.error(`Invalid path for endpoint "${path}". Skipping.`);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
endpoint.setMiddlewares(middlewares);
|
|
162
|
+
endpoint.setHandler(shoot);
|
|
163
|
+
if (!endpoint.getHandler()) {
|
|
164
|
+
logger.error(`Invalid handler for endpoint "${path}". Skipping.`);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (metadata !== null) {
|
|
168
|
+
endpoint.setMetadata(metadata);
|
|
169
|
+
if (Array.isArray(metadata.methods) && metadata.methods.length > 0) {
|
|
170
|
+
endpoint.setMethods(metadata.methods);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
const group = targetRegistry.getCurrentSourceGroup();
|
|
174
|
+
if (group != null) {
|
|
175
|
+
endpoint.setGroup(group);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
targetRegistry.targets.push(endpoint);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
logger.error(`Error registering target ${path}: ${error.message}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export default Target;
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import TejLogger from 'tej-logger';
|
|
2
|
-
|
|
3
|
-
const logger = new TejLogger('MiddlewareValidator');
|
|
4
|
-
|
|
5
|
-
const isMiddlewareValid = (middleware) => {
|
|
6
|
-
if (typeof middleware !== 'function') {
|
|
7
|
-
logger.error(`Middleware ${middleware} should be a function. Skipping...`);
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
const args = middleware.length;
|
|
12
|
-
if (args !== 2 && args !== 3) {
|
|
13
|
-
logger.error(
|
|
14
|
-
`Middleware ${middleware.name} should have 2 arguments (ammo, next) or 3 arguments (req, res, next). Skipping...`,
|
|
15
|
-
);
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return true;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export default isMiddlewareValid;
|
|
1
|
+
import TejLogger from 'tej-logger';
|
|
2
|
+
|
|
3
|
+
const logger = new TejLogger('MiddlewareValidator');
|
|
4
|
+
|
|
5
|
+
const isMiddlewareValid = (middleware) => {
|
|
6
|
+
if (typeof middleware !== 'function') {
|
|
7
|
+
logger.error(`Middleware ${middleware} should be a function. Skipping...`);
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const args = middleware.length;
|
|
12
|
+
if (args !== 2 && args !== 3) {
|
|
13
|
+
logger.error(
|
|
14
|
+
`Middleware ${middleware.name} should have 2 arguments (ammo, next) or 3 arguments (req, res, next). Skipping...`,
|
|
15
|
+
);
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return true;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export default isMiddlewareValid;
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import TejLogger from 'tej-logger';
|
|
2
|
-
|
|
3
|
-
const logger = new TejLogger('PathValidator');
|
|
4
|
-
|
|
5
|
-
const standardizePath = (path) => {
|
|
6
|
-
if (!path || path.length === 0) return '';
|
|
7
|
-
|
|
8
|
-
let standardized = path.startsWith('/') ? path : `/${path}`;
|
|
9
|
-
return standardized.endsWith('/') ? standardized.slice(0, -1) : standardized;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
const isPathValid = (path) => {
|
|
13
|
-
if (typeof path !== 'string') {
|
|
14
|
-
logger.error(`Path ${path} should be a string. Skipping...`);
|
|
15
|
-
return false;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return true;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
export { isPathValid, standardizePath };
|
|
1
|
+
import TejLogger from 'tej-logger';
|
|
2
|
+
|
|
3
|
+
const logger = new TejLogger('PathValidator');
|
|
4
|
+
|
|
5
|
+
const standardizePath = (path) => {
|
|
6
|
+
if (!path || path.length === 0) return '';
|
|
7
|
+
|
|
8
|
+
let standardized = path.startsWith('/') ? path : `/${path}`;
|
|
9
|
+
return standardized.endsWith('/') ? standardized.slice(0, -1) : standardized;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const isPathValid = (path) => {
|
|
13
|
+
if (typeof path !== 'string') {
|
|
14
|
+
logger.error(`Path ${path} should be a string. Skipping...`);
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return true;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export { isPathValid, standardizePath };
|