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,147 +1,147 @@
1
- import RateLimiter from '../base.js';
2
- import TejError from '../../server/error.js';
3
-
4
- /**
5
- * Sliding Window Rate Limiter Implementation
6
- *
7
- * @extends RateLimiter
8
- * @description
9
- * The sliding window algorithm provides precise rate limiting by considering both the current
10
- * and previous time windows with configurable weights. This prevents traffic spikes that can
11
- * occur at window boundaries with fixed window rate limiting.
12
- *
13
- * Key features:
14
- * - Smoother rate limiting than fixed windows
15
- * - Prevents boundary spike issues
16
- * - Configurable time granularity
17
- * - Weighted window transitions
18
- *
19
- * For example, with 60-second windows and 30 seconds into the current window:
20
- * - Current window gets full weight (e.g. 1.0)
21
- * - Previous window gets partial weight (e.g. 0.5)
22
- * Total requests = (current_requests * 1.0) + (previous_requests * 0.5)
23
- *
24
- * @example
25
- * // Create a sliding window rate limiter with weighted windows
26
- * const limiter = new SlidingWindowRateLimiter({
27
- * maxRequests: 100, // Allow 100 requests per minute
28
- * timeWindowSeconds: 60,
29
- * slidingWindow: {
30
- * granularity: 1, // 1-second precision
31
- * weights: {
32
- * current: 1, // Full weight for current window
33
- * previous: 0.5 // Half weight for previous window
34
- * }
35
- * }
36
- * });
37
- *
38
- * // Use in an API endpoint
39
- * async function handleRequest(ip) {
40
- * const result = await limiter.consume(ip);
41
- * if (!result.success) {
42
- * throw new TejError(429, 'Rate limit exceeded');
43
- * }
44
- * // Process request...
45
- * }
46
- */
47
- class SlidingWindowRateLimiter extends RateLimiter {
48
- constructor(options) {
49
- if (!options.slidingWindowConfig) {
50
- options.slidingWindowConfig = {}; // Ensure defaults are set in base class
51
- }
52
- super(options);
53
-
54
- if (!this.slidingWindowOptions) {
55
- throw new TejError(
56
- 400,
57
- 'SlidingWindowRateLimiter requires slidingWindowConfig options',
58
- );
59
- }
60
- }
61
-
62
- /**
63
- * Check if a request should be allowed based on weighted window counts
64
- *
65
- * @param {string} identifier - Unique identifier for rate limiting (e.g., IP address, user ID)
66
- * @returns {Promise<Object>} Rate limit check result
67
- * @returns {boolean} result.success - Whether the request is allowed
68
- * @returns {number} result.remainingRequests - Number of requests remaining in the current window
69
- * @returns {number} result.resetTime - Unix timestamp when the current window ends
70
- */
71
- async consume(identifier) {
72
- const key = this.getKey(identifier);
73
- const now = Date.now();
74
- const options = this.getAlgorithmOptions('sliding-window');
75
-
76
- const stored = await this.storage.get(key);
77
- if (!stored) {
78
- await this.storage.set(
79
- key,
80
- {
81
- counter: 1,
82
- timestamps: [now],
83
- windowStart:
84
- Math.floor(now / (options.granularity * 1000)) *
85
- (options.granularity * 1000),
86
- },
87
- this.options.timeWindowSeconds,
88
- );
89
-
90
- return {
91
- success: true,
92
- remainingRequests: this.options.maxRequests - 1,
93
- resetTime: Math.floor(now / 1000) + this.options.timeWindowSeconds,
94
- };
95
- }
96
-
97
- // Calculate window boundaries
98
- const currentWindowStart =
99
- Math.floor(now / (options.granularity * 1000)) *
100
- (options.granularity * 1000);
101
- const previousWindowStart =
102
- currentWindowStart - this.options.timeWindowSeconds * 1000;
103
-
104
- // Split timestamps into current and previous windows
105
- const currentWindowRequests = stored.timestamps.filter(
106
- (ts) => ts >= currentWindowStart,
107
- ).length;
108
- const previousWindowRequests = stored.timestamps.filter(
109
- (ts) => ts >= previousWindowStart && ts < currentWindowStart,
110
- ).length;
111
-
112
- // Calculate weighted request count
113
- const weightedCount =
114
- currentWindowRequests * options.weights.current +
115
- previousWindowRequests * options.weights.previous;
116
-
117
- if (weightedCount >= this.options.maxRequests) {
118
- return {
119
- success: false,
120
- remainingRequests: 0,
121
- resetTime: Math.floor(
122
- currentWindowStart / 1000 + this.options.timeWindowSeconds,
123
- ),
124
- };
125
- }
126
-
127
- // Remove timestamps outside both windows and add new timestamp
128
- stored.timestamps = stored.timestamps.filter(
129
- (ts) => ts >= previousWindowStart,
130
- );
131
- stored.timestamps.push(now);
132
- stored.windowStart = currentWindowStart;
133
- await this.storage.set(key, stored, this.options.timeWindowSeconds);
134
-
135
- return {
136
- success: true,
137
- remainingRequests: Math.floor(
138
- this.options.maxRequests - weightedCount - 1,
139
- ),
140
- resetTime: Math.floor(
141
- currentWindowStart / 1000 + this.options.timeWindowSeconds,
142
- ),
143
- };
144
- }
145
- }
146
-
147
- export default SlidingWindowRateLimiter;
1
+ import RateLimiter from '../base.js';
2
+ import TejError from '../../server/error.js';
3
+
4
+ /**
5
+ * Sliding Window Rate Limiter Implementation
6
+ *
7
+ * @extends RateLimiter
8
+ * @description
9
+ * The sliding window algorithm provides precise rate limiting by considering both the current
10
+ * and previous time windows with configurable weights. This prevents traffic spikes that can
11
+ * occur at window boundaries with fixed window rate limiting.
12
+ *
13
+ * Key features:
14
+ * - Smoother rate limiting than fixed windows
15
+ * - Prevents boundary spike issues
16
+ * - Configurable time granularity
17
+ * - Weighted window transitions
18
+ *
19
+ * For example, with 60-second windows and 30 seconds into the current window:
20
+ * - Current window gets full weight (e.g. 1.0)
21
+ * - Previous window gets partial weight (e.g. 0.5)
22
+ * Total requests = (current_requests * 1.0) + (previous_requests * 0.5)
23
+ *
24
+ * @example
25
+ * // Create a sliding window rate limiter with weighted windows
26
+ * const limiter = new SlidingWindowRateLimiter({
27
+ * maxRequests: 100, // Allow 100 requests per minute
28
+ * timeWindowSeconds: 60,
29
+ * slidingWindow: {
30
+ * granularity: 1, // 1-second precision
31
+ * weights: {
32
+ * current: 1, // Full weight for current window
33
+ * previous: 0.5 // Half weight for previous window
34
+ * }
35
+ * }
36
+ * });
37
+ *
38
+ * // Use in an API endpoint
39
+ * async function handleRequest(ip) {
40
+ * const result = await limiter.consume(ip);
41
+ * if (!result.success) {
42
+ * throw new TejError(429, 'Rate limit exceeded');
43
+ * }
44
+ * // Process request...
45
+ * }
46
+ */
47
+ class SlidingWindowRateLimiter extends RateLimiter {
48
+ constructor(options) {
49
+ if (!options.slidingWindowConfig) {
50
+ options.slidingWindowConfig = {}; // Ensure defaults are set in base class
51
+ }
52
+ super(options);
53
+
54
+ if (!this.slidingWindowOptions) {
55
+ throw new TejError(
56
+ 400,
57
+ 'SlidingWindowRateLimiter requires slidingWindowConfig options',
58
+ );
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Check if a request should be allowed based on weighted window counts
64
+ *
65
+ * @param {string} identifier - Unique identifier for rate limiting (e.g., IP address, user ID)
66
+ * @returns {Promise<Object>} Rate limit check result
67
+ * @returns {boolean} result.success - Whether the request is allowed
68
+ * @returns {number} result.remainingRequests - Number of requests remaining in the current window
69
+ * @returns {number} result.resetTime - Unix timestamp when the current window ends
70
+ */
71
+ async consume(identifier) {
72
+ const key = this.getKey(identifier);
73
+ const now = Date.now();
74
+ const options = this.getAlgorithmOptions('sliding-window');
75
+
76
+ const stored = await this.storage.get(key);
77
+ if (!stored) {
78
+ await this.storage.set(
79
+ key,
80
+ {
81
+ counter: 1,
82
+ timestamps: [now],
83
+ windowStart:
84
+ Math.floor(now / (options.granularity * 1000)) *
85
+ (options.granularity * 1000),
86
+ },
87
+ this.options.timeWindowSeconds,
88
+ );
89
+
90
+ return {
91
+ success: true,
92
+ remainingRequests: this.options.maxRequests - 1,
93
+ resetTime: Math.floor(now / 1000) + this.options.timeWindowSeconds,
94
+ };
95
+ }
96
+
97
+ // Calculate window boundaries
98
+ const currentWindowStart =
99
+ Math.floor(now / (options.granularity * 1000)) *
100
+ (options.granularity * 1000);
101
+ const previousWindowStart =
102
+ currentWindowStart - this.options.timeWindowSeconds * 1000;
103
+
104
+ // Split timestamps into current and previous windows
105
+ const currentWindowRequests = stored.timestamps.filter(
106
+ (ts) => ts >= currentWindowStart,
107
+ ).length;
108
+ const previousWindowRequests = stored.timestamps.filter(
109
+ (ts) => ts >= previousWindowStart && ts < currentWindowStart,
110
+ ).length;
111
+
112
+ // Calculate weighted request count
113
+ const weightedCount =
114
+ currentWindowRequests * options.weights.current +
115
+ previousWindowRequests * options.weights.previous;
116
+
117
+ if (weightedCount >= this.options.maxRequests) {
118
+ return {
119
+ success: false,
120
+ remainingRequests: 0,
121
+ resetTime: Math.floor(
122
+ currentWindowStart / 1000 + this.options.timeWindowSeconds,
123
+ ),
124
+ };
125
+ }
126
+
127
+ // Remove timestamps outside both windows and add new timestamp
128
+ stored.timestamps = stored.timestamps.filter(
129
+ (ts) => ts >= previousWindowStart,
130
+ );
131
+ stored.timestamps.push(now);
132
+ stored.windowStart = currentWindowStart;
133
+ await this.storage.set(key, stored, this.options.timeWindowSeconds);
134
+
135
+ return {
136
+ success: true,
137
+ remainingRequests: Math.floor(
138
+ this.options.maxRequests - weightedCount - 1,
139
+ ),
140
+ resetTime: Math.floor(
141
+ currentWindowStart / 1000 + this.options.timeWindowSeconds,
142
+ ),
143
+ };
144
+ }
145
+ }
146
+
147
+ export default SlidingWindowRateLimiter;
@@ -1,115 +1,115 @@
1
- import RateLimiter from '../base.js';
2
- import TejError from '../../server/error.js';
3
-
4
- /**
5
- * Token Bucket Rate Limiter Implementation
6
- *
7
- * @extends RateLimiter
8
- * @description
9
- * The token bucket algorithm provides smooth rate limiting with burst handling capabilities.
10
- * It maintains a bucket of tokens that refills at a constant rate, allowing for temporary
11
- * bursts of traffic while maintaining a long-term average rate.
12
- *
13
- * Key features:
14
- * - Smooth rate limiting with continuous token regeneration
15
- * - Burst handling with configurable burst size
16
- * - Predictable long-term average rate
17
- * - Fair distribution of requests over time
18
- *
19
- * @example
20
- * // Create a rate limiter that allows bursts
21
- * const limiter = new TokenBucketRateLimiter({
22
- * maxRequests: 60, // Base rate: 60 requests per minute
23
- * timeWindowSeconds: 60,
24
- * tokenBucket: {
25
- * refillRate: 1, // Refill 1 token per second
26
- * burstSize: 90 // Allow bursts up to 90 requests
27
- * }
28
- * });
29
- *
30
- * // Use the rate limiter in an endpoint
31
- * async function handleRequest(ip) {
32
- * const result = await limiter.consume(ip);
33
- * if (!result.success) {
34
- * throw new TejError(429, 'Rate limit exceeded');
35
- * }
36
- * // Handle request...
37
- * }
38
- */
39
- class TokenBucketRateLimiter extends RateLimiter {
40
- constructor(options) {
41
- if (!options.tokenBucketConfig) {
42
- options.tokenBucketConfig = {}; // Ensure defaults are set in base class
43
- }
44
- super(options);
45
-
46
- if (!this.tokenBucketOptions) {
47
- throw new TejError(
48
- 400,
49
- 'TokenBucketRateLimiter requires tokenBucketConfig options',
50
- );
51
- }
52
- }
53
-
54
- /**
55
- * Check if a request should be allowed and update token count
56
- *
57
- * @param {string} identifier - Unique identifier for rate limiting (e.g., IP address, user ID)
58
- * @returns {Promise<Object>} Rate limit check result
59
- * @returns {boolean} result.success - Whether the request is allowed
60
- * @returns {number} result.remainingRequests - Number of tokens remaining in the bucket
61
- * @returns {number} result.resetTime - Unix timestamp when the next token will be added
62
- */
63
- async consume(identifier) {
64
- const key = this.getKey(identifier);
65
- const now = Date.now();
66
- const options = this.getAlgorithmOptions('tokenBucketConfig');
67
-
68
- const stored = await this.storage.get(key);
69
- if (!stored) {
70
- await this.storage.set(
71
- key,
72
- {
73
- tokens: options.burstSize - 1,
74
- lastRefill: now,
75
- },
76
- this.options.timeWindowSeconds,
77
- );
78
-
79
- return {
80
- success: true,
81
- remainingRequests: options.burstSize - 1,
82
- resetTime: Math.floor(now / 1000) + this.options.timeWindowSeconds,
83
- };
84
- }
85
-
86
- // Calculate token refill based on configured refill rate
87
- const timePassed = now - stored.lastRefill;
88
- const refillTokens = Math.floor((timePassed * options.refillRate) / 1000);
89
-
90
- stored.tokens = Math.min(options.burstSize, stored.tokens + refillTokens);
91
- stored.lastRefill = now;
92
-
93
- if (stored.tokens < 1) {
94
- const timeToNextToken = Math.ceil(
95
- ((1 - stored.tokens) / options.refillRate) * 1000,
96
- );
97
- return {
98
- success: false,
99
- remainingRequests: 0,
100
- resetTime: Math.floor((now + timeToNextToken) / 1000),
101
- };
102
- }
103
-
104
- stored.tokens--;
105
- await this.storage.set(key, stored, this.options.timeWindowSeconds);
106
-
107
- return {
108
- success: true,
109
- remainingRequests: Math.floor(stored.tokens),
110
- resetTime: Math.floor(now / 1000) + this.options.timeWindowSeconds,
111
- };
112
- }
113
- }
114
-
115
- export default TokenBucketRateLimiter;
1
+ import RateLimiter from '../base.js';
2
+ import TejError from '../../server/error.js';
3
+
4
+ /**
5
+ * Token Bucket Rate Limiter Implementation
6
+ *
7
+ * @extends RateLimiter
8
+ * @description
9
+ * The token bucket algorithm provides smooth rate limiting with burst handling capabilities.
10
+ * It maintains a bucket of tokens that refills at a constant rate, allowing for temporary
11
+ * bursts of traffic while maintaining a long-term average rate.
12
+ *
13
+ * Key features:
14
+ * - Smooth rate limiting with continuous token regeneration
15
+ * - Burst handling with configurable burst size
16
+ * - Predictable long-term average rate
17
+ * - Fair distribution of requests over time
18
+ *
19
+ * @example
20
+ * // Create a rate limiter that allows bursts
21
+ * const limiter = new TokenBucketRateLimiter({
22
+ * maxRequests: 60, // Base rate: 60 requests per minute
23
+ * timeWindowSeconds: 60,
24
+ * tokenBucket: {
25
+ * refillRate: 1, // Refill 1 token per second
26
+ * burstSize: 90 // Allow bursts up to 90 requests
27
+ * }
28
+ * });
29
+ *
30
+ * // Use the rate limiter in an endpoint
31
+ * async function handleRequest(ip) {
32
+ * const result = await limiter.consume(ip);
33
+ * if (!result.success) {
34
+ * throw new TejError(429, 'Rate limit exceeded');
35
+ * }
36
+ * // Handle request...
37
+ * }
38
+ */
39
+ class TokenBucketRateLimiter extends RateLimiter {
40
+ constructor(options) {
41
+ if (!options.tokenBucketConfig) {
42
+ options.tokenBucketConfig = {}; // Ensure defaults are set in base class
43
+ }
44
+ super(options);
45
+
46
+ if (!this.tokenBucketOptions) {
47
+ throw new TejError(
48
+ 400,
49
+ 'TokenBucketRateLimiter requires tokenBucketConfig options',
50
+ );
51
+ }
52
+ }
53
+
54
+ /**
55
+ * Check if a request should be allowed and update token count
56
+ *
57
+ * @param {string} identifier - Unique identifier for rate limiting (e.g., IP address, user ID)
58
+ * @returns {Promise<Object>} Rate limit check result
59
+ * @returns {boolean} result.success - Whether the request is allowed
60
+ * @returns {number} result.remainingRequests - Number of tokens remaining in the bucket
61
+ * @returns {number} result.resetTime - Unix timestamp when the next token will be added
62
+ */
63
+ async consume(identifier) {
64
+ const key = this.getKey(identifier);
65
+ const now = Date.now();
66
+ const options = this.getAlgorithmOptions('tokenBucketConfig');
67
+
68
+ const stored = await this.storage.get(key);
69
+ if (!stored) {
70
+ await this.storage.set(
71
+ key,
72
+ {
73
+ tokens: options.burstSize - 1,
74
+ lastRefill: now,
75
+ },
76
+ this.options.timeWindowSeconds,
77
+ );
78
+
79
+ return {
80
+ success: true,
81
+ remainingRequests: options.burstSize - 1,
82
+ resetTime: Math.floor(now / 1000) + this.options.timeWindowSeconds,
83
+ };
84
+ }
85
+
86
+ // Calculate token refill based on configured refill rate
87
+ const timePassed = now - stored.lastRefill;
88
+ const refillTokens = Math.floor((timePassed * options.refillRate) / 1000);
89
+
90
+ stored.tokens = Math.min(options.burstSize, stored.tokens + refillTokens);
91
+ stored.lastRefill = now;
92
+
93
+ if (stored.tokens < 1) {
94
+ const timeToNextToken = Math.ceil(
95
+ ((1 - stored.tokens) / options.refillRate) * 1000,
96
+ );
97
+ return {
98
+ success: false,
99
+ remainingRequests: 0,
100
+ resetTime: Math.floor((now + timeToNextToken) / 1000),
101
+ };
102
+ }
103
+
104
+ stored.tokens--;
105
+ await this.storage.set(key, stored, this.options.timeWindowSeconds);
106
+
107
+ return {
108
+ success: true,
109
+ remainingRequests: Math.floor(stored.tokens),
110
+ resetTime: Math.floor(now / 1000) + this.options.timeWindowSeconds,
111
+ };
112
+ }
113
+ }
114
+
115
+ export default TokenBucketRateLimiter;