te.js 2.1.0 → 2.1.2

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.
Files changed (70) hide show
  1. package/README.md +197 -196
  2. package/auto-docs/analysis/handler-analyzer.js +58 -58
  3. package/auto-docs/analysis/source-resolver.js +101 -101
  4. package/auto-docs/constants.js +37 -37
  5. package/auto-docs/docs-llm/index.js +7 -7
  6. package/auto-docs/docs-llm/prompts.js +222 -222
  7. package/auto-docs/docs-llm/provider.js +132 -132
  8. package/auto-docs/index.js +146 -146
  9. package/auto-docs/openapi/endpoint-processor.js +277 -277
  10. package/auto-docs/openapi/generator.js +107 -107
  11. package/auto-docs/openapi/level3.js +131 -131
  12. package/auto-docs/openapi/spec-builders.js +244 -244
  13. package/auto-docs/ui/docs-ui.js +186 -186
  14. package/auto-docs/utils/logger.js +17 -17
  15. package/auto-docs/utils/strip-usage.js +10 -10
  16. package/cli/docs-command.js +315 -315
  17. package/cli/fly-command.js +71 -71
  18. package/cli/index.js +56 -56
  19. package/cors/index.js +71 -0
  20. package/database/index.js +165 -165
  21. package/database/mongodb.js +146 -146
  22. package/database/redis.js +201 -201
  23. package/docs/README.md +36 -36
  24. package/docs/ammo.md +362 -362
  25. package/docs/api-reference.md +490 -490
  26. package/docs/auto-docs.md +216 -216
  27. package/docs/cli.md +152 -152
  28. package/docs/configuration.md +275 -275
  29. package/docs/database.md +390 -390
  30. package/docs/error-handling.md +438 -438
  31. package/docs/file-uploads.md +333 -333
  32. package/docs/getting-started.md +214 -214
  33. package/docs/middleware.md +355 -355
  34. package/docs/rate-limiting.md +393 -393
  35. package/docs/routing.md +302 -302
  36. package/lib/llm/client.js +73 -0
  37. package/lib/llm/index.js +7 -0
  38. package/lib/llm/parse.js +89 -0
  39. package/package.json +64 -62
  40. package/rate-limit/algorithms/fixed-window.js +141 -141
  41. package/rate-limit/algorithms/sliding-window.js +147 -147
  42. package/rate-limit/algorithms/token-bucket.js +115 -115
  43. package/rate-limit/base.js +165 -165
  44. package/rate-limit/index.js +147 -147
  45. package/rate-limit/storage/base.js +104 -104
  46. package/rate-limit/storage/memory.js +101 -101
  47. package/rate-limit/storage/redis.js +88 -88
  48. package/server/ammo/body-parser.js +220 -220
  49. package/server/ammo/dispatch-helper.js +103 -103
  50. package/server/ammo/enhancer.js +57 -57
  51. package/server/ammo.js +454 -415
  52. package/server/endpoint.js +97 -74
  53. package/server/error.js +9 -9
  54. package/server/errors/code-context.js +125 -125
  55. package/server/errors/llm-error-service.js +140 -140
  56. package/server/files/helper.js +33 -33
  57. package/server/files/uploader.js +143 -143
  58. package/server/handler.js +158 -119
  59. package/server/target.js +185 -175
  60. package/server/targets/middleware-validator.js +22 -22
  61. package/server/targets/path-validator.js +21 -21
  62. package/server/targets/registry.js +160 -160
  63. package/server/targets/shoot-validator.js +21 -21
  64. package/te.js +428 -402
  65. package/utils/auto-register.js +17 -17
  66. package/utils/configuration.js +64 -64
  67. package/utils/errors-llm-config.js +84 -84
  68. package/utils/request-logger.js +43 -43
  69. package/utils/status-codes.js +82 -82
  70. package/utils/tejas-entrypoint-html.js +18 -18
@@ -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 };
@@ -1,160 +1,160 @@
1
- import isMiddlewareValid from './middleware-validator.js';
2
- import { standardizePath } from './path-validator.js';
3
-
4
- class TargetRegistry {
5
- constructor() {
6
- if (TargetRegistry.instance) {
7
- return TargetRegistry.instance;
8
- }
9
-
10
- TargetRegistry.instance = this;
11
-
12
- // TODO - Add a default target
13
- this.targets = [];
14
- this.globalMiddlewares = [];
15
- /** Current source group (target file id) set by loader before importing a target file. */
16
- this._currentSourceGroup = null;
17
- }
18
-
19
- setCurrentSourceGroup(group) {
20
- this._currentSourceGroup = group ?? null;
21
- }
22
-
23
- getCurrentSourceGroup() {
24
- return this._currentSourceGroup;
25
- }
26
-
27
- addGlobalMiddleware() {
28
- if (!arguments) return;
29
-
30
- const middlewares = [...arguments];
31
- const validMiddlewares = middlewares.filter(isMiddlewareValid);
32
- this.globalMiddlewares = this.globalMiddlewares.concat(validMiddlewares);
33
- }
34
-
35
- /**
36
- * @param {Array || Object} targets
37
- */
38
- register(targets) {
39
- if (Array.isArray(targets)) {
40
- this.targets = this.targets.concat(targets);
41
- } else {
42
- this.targets.push(targets);
43
- }
44
- }
45
-
46
- /**
47
- * Matches an endpoint URL to a registered target, supporting parameterized routes.
48
- *
49
- * @param {string} endpoint - The endpoint URL to match
50
- * @returns {Object|null} An object with `target` and `params`, or null if no match
51
- */
52
- aim(endpoint) {
53
- const standardizedEndpoint = standardizePath(endpoint);
54
-
55
- // First, try exact match (most specific)
56
- const exactMatch = this.targets.find((target) => {
57
- return target.getPath() === standardizedEndpoint;
58
- });
59
-
60
- if (exactMatch) {
61
- return { target: exactMatch, params: {} };
62
- }
63
-
64
- // Then, try parameterized route matching
65
- for (const target of this.targets) {
66
- const targetPath = target.getPath();
67
- const params = this.matchParameterizedRoute(
68
- targetPath,
69
- standardizedEndpoint,
70
- );
71
-
72
- if (params !== null) {
73
- return { target, params };
74
- }
75
- }
76
-
77
- return null;
78
- }
79
-
80
- /**
81
- * Matches a parameterized route pattern against an actual URL.
82
- *
83
- * @param {string} pattern - The route pattern (e.g., '/api/categories/:id')
84
- * @param {string} url - The actual URL to match (e.g., '/api/categories/123')
85
- * @returns {Object|null} An object with extracted parameters, or null if no match
86
- */
87
- matchParameterizedRoute(pattern, url) {
88
- // Handle root path case
89
- if (pattern === '/' && url === '/') {
90
- return {};
91
- }
92
-
93
- // Split both pattern and URL into segments
94
- const patternSegments = pattern.split('/').filter((s) => s.length > 0);
95
- const urlSegments = url.split('/').filter((s) => s.length > 0);
96
-
97
- // Must have same number of segments
98
- if (patternSegments.length !== urlSegments.length) {
99
- return null;
100
- }
101
-
102
- // If both are empty (root paths), they match
103
- if (patternSegments.length === 0 && urlSegments.length === 0) {
104
- return {};
105
- }
106
-
107
- const params = {};
108
-
109
- // Match each segment
110
- for (let i = 0; i < patternSegments.length; i++) {
111
- const patternSegment = patternSegments[i];
112
- const urlSegment = urlSegments[i];
113
-
114
- // If it's a parameter (starts with :)
115
- if (patternSegment.startsWith(':')) {
116
- const paramName = patternSegment.slice(1); // Remove the ':'
117
- params[paramName] = urlSegment;
118
- } else if (patternSegment !== urlSegment) {
119
- // If it's not a parameter and doesn't match, no match
120
- return null;
121
- }
122
- }
123
-
124
- return params;
125
- }
126
-
127
- /**
128
- * Get all registered endpoints.
129
- *
130
- * @param {boolean|{ detailed?: boolean, grouped?: boolean }} [options] - If boolean, treated as grouped (backward compat).
131
- * If object: detailed=true returns full metadata per endpoint; grouped=true returns paths grouped by first segment.
132
- * @returns {string[]|Object|Array<{ path: string, metadata: object|null, handler: function }>}
133
- */
134
- getAllEndpoints(options = {}) {
135
- const grouped =
136
- typeof options === 'boolean' ? options : (options && options.grouped);
137
- const detailed =
138
- typeof options === 'object' && options && options.detailed === true;
139
-
140
- if (detailed) {
141
- return this.targets.map((t) => ({
142
- path: t.getPath(),
143
- metadata: t.getMetadata(),
144
- handler: t.getHandler(),
145
- }));
146
- }
147
- if (grouped) {
148
- return this.targets.reduce((acc, target) => {
149
- const group = target.getPath().split('/')[1];
150
- if (!acc[group]) acc[group] = [];
151
- acc[group].push(target.getPath());
152
- return acc;
153
- }, {});
154
- }
155
- return this.targets.map((target) => target.getPath());
156
- }
157
- }
158
-
159
- const targetRegistry = new TargetRegistry();
160
- export default targetRegistry;
1
+ import isMiddlewareValid from './middleware-validator.js';
2
+ import { standardizePath } from './path-validator.js';
3
+
4
+ class TargetRegistry {
5
+ constructor() {
6
+ if (TargetRegistry.instance) {
7
+ return TargetRegistry.instance;
8
+ }
9
+
10
+ TargetRegistry.instance = this;
11
+
12
+ // TODO - Add a default target
13
+ this.targets = [];
14
+ this.globalMiddlewares = [];
15
+ /** Current source group (target file id) set by loader before importing a target file. */
16
+ this._currentSourceGroup = null;
17
+ }
18
+
19
+ setCurrentSourceGroup(group) {
20
+ this._currentSourceGroup = group ?? null;
21
+ }
22
+
23
+ getCurrentSourceGroup() {
24
+ return this._currentSourceGroup;
25
+ }
26
+
27
+ addGlobalMiddleware() {
28
+ if (!arguments) return;
29
+
30
+ const middlewares = [...arguments];
31
+ const validMiddlewares = middlewares.filter(isMiddlewareValid);
32
+ this.globalMiddlewares = this.globalMiddlewares.concat(validMiddlewares);
33
+ }
34
+
35
+ /**
36
+ * @param {Array || Object} targets
37
+ */
38
+ register(targets) {
39
+ if (Array.isArray(targets)) {
40
+ this.targets = this.targets.concat(targets);
41
+ } else {
42
+ this.targets.push(targets);
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Matches an endpoint URL to a registered target, supporting parameterized routes.
48
+ *
49
+ * @param {string} endpoint - The endpoint URL to match
50
+ * @returns {Object|null} An object with `target` and `params`, or null if no match
51
+ */
52
+ aim(endpoint) {
53
+ const standardizedEndpoint = standardizePath(endpoint);
54
+
55
+ // First, try exact match (most specific)
56
+ const exactMatch = this.targets.find((target) => {
57
+ return target.getPath() === standardizedEndpoint;
58
+ });
59
+
60
+ if (exactMatch) {
61
+ return { target: exactMatch, params: {} };
62
+ }
63
+
64
+ // Then, try parameterized route matching
65
+ for (const target of this.targets) {
66
+ const targetPath = target.getPath();
67
+ const params = this.matchParameterizedRoute(
68
+ targetPath,
69
+ standardizedEndpoint,
70
+ );
71
+
72
+ if (params !== null) {
73
+ return { target, params };
74
+ }
75
+ }
76
+
77
+ return null;
78
+ }
79
+
80
+ /**
81
+ * Matches a parameterized route pattern against an actual URL.
82
+ *
83
+ * @param {string} pattern - The route pattern (e.g., '/api/categories/:id')
84
+ * @param {string} url - The actual URL to match (e.g., '/api/categories/123')
85
+ * @returns {Object|null} An object with extracted parameters, or null if no match
86
+ */
87
+ matchParameterizedRoute(pattern, url) {
88
+ // Handle root path case
89
+ if (pattern === '/' && url === '/') {
90
+ return {};
91
+ }
92
+
93
+ // Split both pattern and URL into segments
94
+ const patternSegments = pattern.split('/').filter((s) => s.length > 0);
95
+ const urlSegments = url.split('/').filter((s) => s.length > 0);
96
+
97
+ // Must have same number of segments
98
+ if (patternSegments.length !== urlSegments.length) {
99
+ return null;
100
+ }
101
+
102
+ // If both are empty (root paths), they match
103
+ if (patternSegments.length === 0 && urlSegments.length === 0) {
104
+ return {};
105
+ }
106
+
107
+ const params = {};
108
+
109
+ // Match each segment
110
+ for (let i = 0; i < patternSegments.length; i++) {
111
+ const patternSegment = patternSegments[i];
112
+ const urlSegment = urlSegments[i];
113
+
114
+ // If it's a parameter (starts with :)
115
+ if (patternSegment.startsWith(':')) {
116
+ const paramName = patternSegment.slice(1); // Remove the ':'
117
+ params[paramName] = urlSegment;
118
+ } else if (patternSegment !== urlSegment) {
119
+ // If it's not a parameter and doesn't match, no match
120
+ return null;
121
+ }
122
+ }
123
+
124
+ return params;
125
+ }
126
+
127
+ /**
128
+ * Get all registered endpoints.
129
+ *
130
+ * @param {boolean|{ detailed?: boolean, grouped?: boolean }} [options] - If boolean, treated as grouped (backward compat).
131
+ * If object: detailed=true returns full metadata per endpoint; grouped=true returns paths grouped by first segment.
132
+ * @returns {string[]|Object|Array<{ path: string, metadata: object|null, handler: function }>}
133
+ */
134
+ getAllEndpoints(options = {}) {
135
+ const grouped =
136
+ typeof options === 'boolean' ? options : (options && options.grouped);
137
+ const detailed =
138
+ typeof options === 'object' && options && options.detailed === true;
139
+
140
+ if (detailed) {
141
+ return this.targets.map((t) => ({
142
+ path: t.getPath(),
143
+ metadata: t.getMetadata(),
144
+ handler: t.getHandler(),
145
+ }));
146
+ }
147
+ if (grouped) {
148
+ return this.targets.reduce((acc, target) => {
149
+ const group = target.getPath().split('/')[1];
150
+ if (!acc[group]) acc[group] = [];
151
+ acc[group].push(target.getPath());
152
+ return acc;
153
+ }, {});
154
+ }
155
+ return this.targets.map((target) => target.getPath());
156
+ }
157
+ }
158
+
159
+ const targetRegistry = new TargetRegistry();
160
+ export default targetRegistry;
@@ -1,21 +1,21 @@
1
- import TejLogger from 'tej-logger';
2
- import Ammo from '../ammo.js';
3
- const logger = new TejLogger('ShootValidator');
4
-
5
- const isShootValid = (shoot) => {
6
- if (typeof shoot !== 'function') {
7
- logger.error(`Shoot ${shoot} should be a function. Skipping...`);
8
- return false;
9
- }
10
-
11
- // Shoot should have 1 parameter, and it must be an instance of Ammo
12
- if (shoot.length !== 1) {
13
- logger.error(`Shoot function must have 1 parameter. Skipping...`);
14
- return false;
15
- }
16
-
17
-
18
- return true;
19
- };
20
-
21
- export default isShootValid;
1
+ import TejLogger from 'tej-logger';
2
+ import Ammo from '../ammo.js';
3
+ const logger = new TejLogger('ShootValidator');
4
+
5
+ const isShootValid = (shoot) => {
6
+ if (typeof shoot !== 'function') {
7
+ logger.error(`Shoot ${shoot} should be a function. Skipping...`);
8
+ return false;
9
+ }
10
+
11
+ // Shoot should have 1 parameter, and it must be an instance of Ammo
12
+ if (shoot.length !== 1) {
13
+ logger.error(`Shoot function must have 1 parameter. Skipping...`);
14
+ return false;
15
+ }
16
+
17
+
18
+ return true;
19
+ };
20
+
21
+ export default isShootValid;