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
package/database/redis.js CHANGED
@@ -1,201 +1,201 @@
1
- import { spawnSync } from 'child_process';
2
- import fs from 'fs';
3
- import path from 'path';
4
- import TejError from '../server/error.js';
5
- import TejLogger from 'tej-logger';
6
- import { pathToFileURL } from 'node:url';
7
-
8
- const packageJsonPath = path.join(process.cwd(), 'package.json');
9
- const packagePath = `${process.cwd()}/node_modules/redis/dist/index.js`;
10
-
11
- const logger = new TejLogger('RedisConnectionManager');
12
-
13
- function checkRedisInstallation() {
14
- try {
15
- // Check if redis exists in package.json
16
- const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
17
- const inPackageJson = !!packageJson.dependencies?.redis;
18
-
19
- // Check if redis exists in node_modules
20
- const inNodeModules = fs.existsSync(packagePath);
21
-
22
- return {
23
- needsInstall: !inPackageJson || !inNodeModules,
24
- reason: !inPackageJson
25
- ? 'not in package.json'
26
- : !inNodeModules
27
- ? 'not in node_modules'
28
- : null,
29
- };
30
- } catch (error) {
31
- logger.error(error, true);
32
- return { needsInstall: true, reason: 'error checking installation' };
33
- }
34
- }
35
-
36
- function installRedisSync() {
37
- const spinner = ['|', '/', '-', '\\'];
38
- let current = 0;
39
- let intervalId;
40
-
41
- try {
42
- const { needsInstall, reason } = checkRedisInstallation();
43
-
44
- if (!needsInstall) {
45
- return true;
46
- }
47
-
48
- // Start the spinner
49
- intervalId = setInterval(() => {
50
- process.stdout.write(`\r${spinner[current]} Installing redis...`);
51
- current = (current + 1) % spinner.length;
52
- }, 100);
53
-
54
- logger.info(`Tejas will install redis (${reason})...`);
55
-
56
- const command = process.platform === 'win32' ? 'npm.cmd' : 'npm';
57
- const result = spawnSync(command, ['install', 'redis'], {
58
- stdio: 'inherit',
59
- shell: true,
60
- });
61
-
62
- process.stdout.write('\r');
63
- clearInterval(intervalId);
64
-
65
- if (result.status === 0) {
66
- logger.info('Redis installed successfully');
67
- return true;
68
- } else {
69
- logger.error('Redis installation failed');
70
- return false;
71
- }
72
- } catch (error) {
73
- if (intervalId) {
74
- process.stdout.write('\r');
75
- clearInterval(intervalId);
76
- }
77
- logger.error(error, true);
78
- return false;
79
- }
80
- }
81
-
82
- /**
83
- * Create a new Redis client or cluster
84
- * @param {Object} config - Redis configuration
85
- * @param {boolean} [config.isCluster=false] - Whether to use Redis Cluster
86
- * @param {Object} [config.options={}] - Additional Redis options
87
- * @returns {Promise<RedisClient|RedisCluster>} Redis client or cluster instance
88
- */
89
- async function createConnection(config) {
90
- const { needsInstall } = checkRedisInstallation();
91
-
92
- if (needsInstall) {
93
- const installed = installRedisSync();
94
- if (!installed) {
95
- throw new TejError(500, 'Failed to install required redis package');
96
- }
97
- }
98
-
99
- const { isCluster = false, options = {} } = config;
100
- let client;
101
-
102
- try {
103
- const { createClient, createCluster } = await import(
104
- pathToFileURL(packagePath)
105
- );
106
-
107
- if (isCluster) {
108
- client = createCluster({
109
- ...options,
110
- });
111
- } else {
112
- client = createClient({
113
- ...options,
114
- });
115
- }
116
-
117
- let connectionTimeout;
118
- let hasConnected = false;
119
- let connectionAttempts = 0;
120
- const maxRetries = options.maxRetries || 3;
121
-
122
- // Create a promise that will resolve when connected or reject on fatal errors
123
- const connectionPromise = new Promise((resolve, reject) => {
124
- connectionTimeout = setTimeout(() => {
125
- if (!hasConnected) {
126
- client.quit().catch(() => {});
127
- reject(new TejError(500, 'Redis connection timeout'));
128
- }
129
- }, options.connectTimeout || 10000);
130
-
131
- client.on('error', (err) => {
132
- logger.error(`Redis connection error: ${err}`, true);
133
- if (!hasConnected && connectionAttempts >= maxRetries) {
134
- clearTimeout(connectionTimeout);
135
- client.quit().catch(() => {});
136
- reject(
137
- new TejError(
138
- 500,
139
- `Redis connection failed after ${maxRetries} attempts: ${err.message}`,
140
- ),
141
- );
142
- }
143
- connectionAttempts++;
144
- });
145
-
146
- client.on('connect', () => {
147
- hasConnected = true;
148
- clearTimeout(connectionTimeout);
149
- logger.info(
150
- `Redis connected on ${client?.options?.url ?? client?.options?.socket?.host}`,
151
- );
152
- });
153
-
154
- client.on('ready', () => {
155
- logger.info('Redis ready');
156
- resolve(client);
157
- });
158
-
159
- client.on('end', () => {
160
- logger.info('Redis connection closed');
161
- });
162
- });
163
-
164
- await client.connect();
165
- await connectionPromise;
166
-
167
- return client;
168
- } catch (error) {
169
- if (client) {
170
- try {
171
- await client.quit();
172
- } catch (quitError) {
173
- logger.error(
174
- `Error while cleaning up Redis connection: ${quitError}`,
175
- true,
176
- );
177
- }
178
- }
179
- logger.error(`Failed to create Redis connection: ${error}`, true);
180
- throw new TejError(
181
- 500,
182
- `Failed to create Redis connection: ${error.message}`,
183
- );
184
- }
185
- }
186
-
187
- /**
188
- * Close a Redis connection
189
- * @param {RedisClient|RedisCluster} client - Redis client to close
190
- * @returns {Promise<void>}
191
- */
192
- async function closeConnection(client) {
193
- if (client) {
194
- await client.quit();
195
- }
196
- }
197
-
198
- export default {
199
- createConnection,
200
- closeConnection,
201
- };
1
+ import { spawnSync } from 'child_process';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import TejError from '../server/error.js';
5
+ import TejLogger from 'tej-logger';
6
+ import { pathToFileURL } from 'node:url';
7
+
8
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
9
+ const packagePath = `${process.cwd()}/node_modules/redis/dist/index.js`;
10
+
11
+ const logger = new TejLogger('RedisConnectionManager');
12
+
13
+ function checkRedisInstallation() {
14
+ try {
15
+ // Check if redis exists in package.json
16
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
17
+ const inPackageJson = !!packageJson.dependencies?.redis;
18
+
19
+ // Check if redis exists in node_modules
20
+ const inNodeModules = fs.existsSync(packagePath);
21
+
22
+ return {
23
+ needsInstall: !inPackageJson || !inNodeModules,
24
+ reason: !inPackageJson
25
+ ? 'not in package.json'
26
+ : !inNodeModules
27
+ ? 'not in node_modules'
28
+ : null,
29
+ };
30
+ } catch (error) {
31
+ logger.error(error, true);
32
+ return { needsInstall: true, reason: 'error checking installation' };
33
+ }
34
+ }
35
+
36
+ function installRedisSync() {
37
+ const spinner = ['|', '/', '-', '\\'];
38
+ let current = 0;
39
+ let intervalId;
40
+
41
+ try {
42
+ const { needsInstall, reason } = checkRedisInstallation();
43
+
44
+ if (!needsInstall) {
45
+ return true;
46
+ }
47
+
48
+ // Start the spinner
49
+ intervalId = setInterval(() => {
50
+ process.stdout.write(`\r${spinner[current]} Installing redis...`);
51
+ current = (current + 1) % spinner.length;
52
+ }, 100);
53
+
54
+ logger.info(`Tejas will install redis (${reason})...`);
55
+
56
+ const command = process.platform === 'win32' ? 'npm.cmd' : 'npm';
57
+ const result = spawnSync(command, ['install', 'redis'], {
58
+ stdio: 'inherit',
59
+ shell: true,
60
+ });
61
+
62
+ process.stdout.write('\r');
63
+ clearInterval(intervalId);
64
+
65
+ if (result.status === 0) {
66
+ logger.info('Redis installed successfully');
67
+ return true;
68
+ } else {
69
+ logger.error('Redis installation failed');
70
+ return false;
71
+ }
72
+ } catch (error) {
73
+ if (intervalId) {
74
+ process.stdout.write('\r');
75
+ clearInterval(intervalId);
76
+ }
77
+ logger.error(error, true);
78
+ return false;
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Create a new Redis client or cluster
84
+ * @param {Object} config - Redis configuration
85
+ * @param {boolean} [config.isCluster=false] - Whether to use Redis Cluster
86
+ * @param {Object} [config.options={}] - Additional Redis options
87
+ * @returns {Promise<RedisClient|RedisCluster>} Redis client or cluster instance
88
+ */
89
+ async function createConnection(config) {
90
+ const { needsInstall } = checkRedisInstallation();
91
+
92
+ if (needsInstall) {
93
+ const installed = installRedisSync();
94
+ if (!installed) {
95
+ throw new TejError(500, 'Failed to install required redis package');
96
+ }
97
+ }
98
+
99
+ const { isCluster = false, options = {} } = config;
100
+ let client;
101
+
102
+ try {
103
+ const { createClient, createCluster } = await import(
104
+ pathToFileURL(packagePath)
105
+ );
106
+
107
+ if (isCluster) {
108
+ client = createCluster({
109
+ ...options,
110
+ });
111
+ } else {
112
+ client = createClient({
113
+ ...options,
114
+ });
115
+ }
116
+
117
+ let connectionTimeout;
118
+ let hasConnected = false;
119
+ let connectionAttempts = 0;
120
+ const maxRetries = options.maxRetries || 3;
121
+
122
+ // Create a promise that will resolve when connected or reject on fatal errors
123
+ const connectionPromise = new Promise((resolve, reject) => {
124
+ connectionTimeout = setTimeout(() => {
125
+ if (!hasConnected) {
126
+ client.quit().catch(() => {});
127
+ reject(new TejError(500, 'Redis connection timeout'));
128
+ }
129
+ }, options.connectTimeout || 10000);
130
+
131
+ client.on('error', (err) => {
132
+ logger.error(`Redis connection error: ${err}`, true);
133
+ if (!hasConnected && connectionAttempts >= maxRetries) {
134
+ clearTimeout(connectionTimeout);
135
+ client.quit().catch(() => {});
136
+ reject(
137
+ new TejError(
138
+ 500,
139
+ `Redis connection failed after ${maxRetries} attempts: ${err.message}`,
140
+ ),
141
+ );
142
+ }
143
+ connectionAttempts++;
144
+ });
145
+
146
+ client.on('connect', () => {
147
+ hasConnected = true;
148
+ clearTimeout(connectionTimeout);
149
+ logger.info(
150
+ `Redis connected on ${client?.options?.url ?? client?.options?.socket?.host}`,
151
+ );
152
+ });
153
+
154
+ client.on('ready', () => {
155
+ logger.info('Redis ready');
156
+ resolve(client);
157
+ });
158
+
159
+ client.on('end', () => {
160
+ logger.info('Redis connection closed');
161
+ });
162
+ });
163
+
164
+ await client.connect();
165
+ await connectionPromise;
166
+
167
+ return client;
168
+ } catch (error) {
169
+ if (client) {
170
+ try {
171
+ await client.quit();
172
+ } catch (quitError) {
173
+ logger.error(
174
+ `Error while cleaning up Redis connection: ${quitError}`,
175
+ true,
176
+ );
177
+ }
178
+ }
179
+ logger.error(`Failed to create Redis connection: ${error}`, true);
180
+ throw new TejError(
181
+ 500,
182
+ `Failed to create Redis connection: ${error.message}`,
183
+ );
184
+ }
185
+ }
186
+
187
+ /**
188
+ * Close a Redis connection
189
+ * @param {RedisClient|RedisCluster} client - Redis client to close
190
+ * @returns {Promise<void>}
191
+ */
192
+ async function closeConnection(client) {
193
+ if (client) {
194
+ await client.quit();
195
+ }
196
+ }
197
+
198
+ export default {
199
+ createConnection,
200
+ closeConnection,
201
+ };
package/docs/README.md CHANGED
@@ -1,36 +1,36 @@
1
- # Tejas Documentation
2
-
3
- Welcome to the documentation for **Tejas** — a Node.js framework for building powerful backend services.
4
-
5
- ## Table of Contents
6
-
7
- ### Getting Started
8
-
9
- - [Introduction & Quick Start](./getting-started.md) — AI-assisted setup (MCP), install, create your first app, and core concepts
10
- - [Configuration](./configuration.md) — Config sources, all available options, and environment variables
11
-
12
- ### Core Concepts
13
-
14
- - [Routing (Targets)](./routing.md) — Define routes, parameterized paths, and endpoint metadata
15
- - [Request & Response (Ammo)](./ammo.md) — Handle requests, send responses, and access request data
16
- - [Middleware](./middleware.md) — Global, target, and route-level middleware with Express compatibility
17
- - [Error Handling](./error-handling.md) — Zero-config error handling, TejError, and BodyParserError
18
-
19
- ### Features
20
-
21
- - [Database Integration](./database.md) — Redis and MongoDB connections with auto-install
22
- - [Rate Limiting](./rate-limiting.md) — Three algorithms, two storage backends, custom headers
23
- - [File Uploads](./file-uploads.md) — Single and multiple file handling with validation
24
-
25
- ### Tooling
26
-
27
- - [CLI Reference](./cli.md) — `tejas fly`, `tejas generate:docs`, and `tejas docs:on-push`
28
- - [Auto-Documentation](./auto-docs.md) — LLM-powered OpenAPI generation and Scalar API docs UI
29
-
30
- ### Reference
31
-
32
- - [API Reference](./api-reference.md) — Complete API documentation for all classes and functions
33
-
34
- ---
35
-
36
- This documentation is for Tejas v2.0.0.
1
+ # Tejas Documentation
2
+
3
+ Welcome to the documentation for **Tejas** — a Node.js framework for building powerful backend services.
4
+
5
+ ## Table of Contents
6
+
7
+ ### Getting Started
8
+
9
+ - [Introduction & Quick Start](./getting-started.md) — AI-assisted setup (MCP), install, create your first app, and core concepts
10
+ - [Configuration](./configuration.md) — Config sources, all available options, and environment variables
11
+
12
+ ### Core Concepts
13
+
14
+ - [Routing (Targets)](./routing.md) — Define routes, parameterized paths, and endpoint metadata
15
+ - [Request & Response (Ammo)](./ammo.md) — Handle requests, send responses, and access request data
16
+ - [Middleware](./middleware.md) — Global, target, and route-level middleware with Express compatibility
17
+ - [Error Handling](./error-handling.md) — Zero-config error handling, TejError, and BodyParserError
18
+
19
+ ### Features
20
+
21
+ - [Database Integration](./database.md) — Redis and MongoDB connections with auto-install
22
+ - [Rate Limiting](./rate-limiting.md) — Three algorithms, two storage backends, custom headers
23
+ - [File Uploads](./file-uploads.md) — Single and multiple file handling with validation
24
+
25
+ ### Tooling
26
+
27
+ - [CLI Reference](./cli.md) — `tejas fly`, `tejas generate:docs`, and `tejas docs:on-push`
28
+ - [Auto-Documentation](./auto-docs.md) — LLM-powered OpenAPI generation and Scalar API docs UI
29
+
30
+ ### Reference
31
+
32
+ - [API Reference](./api-reference.md) — Complete API documentation for all classes and functions
33
+
34
+ ---
35
+
36
+ This documentation is for Tejas v2.0.0.