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/utils/auto-register.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import fs from 'node:fs/promises';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
|
|
4
|
-
const findTargetFiles = async () => {
|
|
5
|
-
if (!process.env.DIR_TARGETS) return;
|
|
6
|
-
const fullPath = path.join(process.cwd(), process.env.DIR_TARGETS);
|
|
7
|
-
const directory = await fs.readdir(fullPath, {
|
|
8
|
-
withFileTypes: true,
|
|
9
|
-
recursive: true,
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
return directory.filter(
|
|
13
|
-
(file) => file.isFile() && file.name.endsWith('target.js'),
|
|
14
|
-
);
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
export { findTargetFiles };
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
const findTargetFiles = async () => {
|
|
5
|
+
if (!process.env.DIR_TARGETS) return;
|
|
6
|
+
const fullPath = path.join(process.cwd(), process.env.DIR_TARGETS);
|
|
7
|
+
const directory = await fs.readdir(fullPath, {
|
|
8
|
+
withFileTypes: true,
|
|
9
|
+
recursive: true,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
return directory.filter(
|
|
13
|
+
(file) => file.isFile() && file.name.endsWith('target.js'),
|
|
14
|
+
);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export { findTargetFiles };
|
package/utils/configuration.js
CHANGED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import { getAllEnv } from 'tej-env';
|
|
3
|
-
|
|
4
|
-
const loadConfigFile = () => {
|
|
5
|
-
try {
|
|
6
|
-
const data = fs.readFileSync('tejas.config.json', 'utf8');
|
|
7
|
-
return JSON.parse(data);
|
|
8
|
-
} catch (err) {
|
|
9
|
-
return {};
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
const keysToUpperCase = (obj) => {
|
|
14
|
-
if (!obj) return {};
|
|
15
|
-
const standardObj = {};
|
|
16
|
-
|
|
17
|
-
for (const key in obj) {
|
|
18
|
-
if (obj.hasOwnProperty(key)) {
|
|
19
|
-
const value = obj[key];
|
|
20
|
-
const upperKey = key.toUpperCase();
|
|
21
|
-
|
|
22
|
-
if (typeof value === 'object' && value !== null) {
|
|
23
|
-
standardObj[upperKey] = keysToUpperCase(value);
|
|
24
|
-
} else {
|
|
25
|
-
standardObj[upperKey] = value;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return standardObj;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const flattenObject = (obj, prefix = '') => {
|
|
34
|
-
let flattened = {};
|
|
35
|
-
|
|
36
|
-
for (const key in obj) {
|
|
37
|
-
if (obj.hasOwnProperty(key)) {
|
|
38
|
-
const value = obj[key];
|
|
39
|
-
const newKey = prefix ? `${prefix}_${key}` : key;
|
|
40
|
-
|
|
41
|
-
if (
|
|
42
|
-
typeof value === 'object' &&
|
|
43
|
-
value !== null &&
|
|
44
|
-
!Array.isArray(value) &&
|
|
45
|
-
Object.keys(value).length > 0
|
|
46
|
-
) {
|
|
47
|
-
const nested = flattenObject(value, newKey);
|
|
48
|
-
Object.assign(flattened, nested);
|
|
49
|
-
} else {
|
|
50
|
-
flattened[newKey] = value;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return flattened;
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const standardizeObj = (obj) => {
|
|
58
|
-
let standardObj = obj;
|
|
59
|
-
standardObj = keysToUpperCase(standardObj);
|
|
60
|
-
standardObj = flattenObject(standardObj);
|
|
61
|
-
return standardObj;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export { loadConfigFile, standardizeObj };
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import { getAllEnv } from 'tej-env';
|
|
3
|
+
|
|
4
|
+
const loadConfigFile = () => {
|
|
5
|
+
try {
|
|
6
|
+
const data = fs.readFileSync('tejas.config.json', 'utf8');
|
|
7
|
+
return JSON.parse(data);
|
|
8
|
+
} catch (err) {
|
|
9
|
+
return {};
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const keysToUpperCase = (obj) => {
|
|
14
|
+
if (!obj) return {};
|
|
15
|
+
const standardObj = {};
|
|
16
|
+
|
|
17
|
+
for (const key in obj) {
|
|
18
|
+
if (obj.hasOwnProperty(key)) {
|
|
19
|
+
const value = obj[key];
|
|
20
|
+
const upperKey = key.toUpperCase();
|
|
21
|
+
|
|
22
|
+
if (typeof value === 'object' && value !== null) {
|
|
23
|
+
standardObj[upperKey] = keysToUpperCase(value);
|
|
24
|
+
} else {
|
|
25
|
+
standardObj[upperKey] = value;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return standardObj;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const flattenObject = (obj, prefix = '') => {
|
|
34
|
+
let flattened = {};
|
|
35
|
+
|
|
36
|
+
for (const key in obj) {
|
|
37
|
+
if (obj.hasOwnProperty(key)) {
|
|
38
|
+
const value = obj[key];
|
|
39
|
+
const newKey = prefix ? `${prefix}_${key}` : key;
|
|
40
|
+
|
|
41
|
+
if (
|
|
42
|
+
typeof value === 'object' &&
|
|
43
|
+
value !== null &&
|
|
44
|
+
!Array.isArray(value) &&
|
|
45
|
+
Object.keys(value).length > 0
|
|
46
|
+
) {
|
|
47
|
+
const nested = flattenObject(value, newKey);
|
|
48
|
+
Object.assign(flattened, nested);
|
|
49
|
+
} else {
|
|
50
|
+
flattened[newKey] = value;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return flattened;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const standardizeObj = (obj) => {
|
|
58
|
+
let standardObj = obj;
|
|
59
|
+
standardObj = keysToUpperCase(standardObj);
|
|
60
|
+
standardObj = flattenObject(standardObj);
|
|
61
|
+
return standardObj;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export { loadConfigFile, standardizeObj };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve and validate errors.llm configuration (LLM-inferred error codes/messages).
|
|
3
|
+
* Uses ERRORS_LLM_* env vars with fallback to LLM_*.
|
|
4
|
+
* Config file keys (e.g. errors.llm.baseURL) are standardized to ERRORS_LLM_BASEURL etc.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { env } from 'tej-env';
|
|
8
|
+
|
|
9
|
+
const MESSAGE_TYPES = /** @type {const} */ (['endUser', 'developer']);
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Normalize messageType to 'endUser' | 'developer'.
|
|
13
|
+
* @param {string} v
|
|
14
|
+
* @returns {'endUser'|'developer'}
|
|
15
|
+
*/
|
|
16
|
+
function normalizeMessageType(v) {
|
|
17
|
+
const s = String(v ?? '').trim().toLowerCase();
|
|
18
|
+
if (s === 'developer' || s === 'dev') return 'developer';
|
|
19
|
+
return 'endUser'; // endUser, end_user, default
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Resolve errors.llm config from env (feature-specific then LLM_ fallback).
|
|
24
|
+
* @returns {{ enabled: boolean, baseURL: string, apiKey: string, model: string, messageType: 'endUser'|'developer' }}
|
|
25
|
+
*/
|
|
26
|
+
export function getErrorsLlmConfig() {
|
|
27
|
+
const enabledRaw = env('ERRORS_LLM_ENABLED') ?? '';
|
|
28
|
+
const enabled =
|
|
29
|
+
enabledRaw === true ||
|
|
30
|
+
enabledRaw === 'true' ||
|
|
31
|
+
enabledRaw === '1' ||
|
|
32
|
+
enabledRaw === 1;
|
|
33
|
+
|
|
34
|
+
const baseURL =
|
|
35
|
+
env('ERRORS_LLM_BASE_URL') ??
|
|
36
|
+
env('ERRORS_LLM_BASEURL') ??
|
|
37
|
+
env('LLM_BASE_URL') ??
|
|
38
|
+
env('LLM_BASEURL') ??
|
|
39
|
+
'';
|
|
40
|
+
|
|
41
|
+
const apiKey =
|
|
42
|
+
env('ERRORS_LLM_API_KEY') ??
|
|
43
|
+
env('ERRORS_LLM_APIKEY') ??
|
|
44
|
+
env('LLM_API_KEY') ??
|
|
45
|
+
env('LLM_APIKEY') ??
|
|
46
|
+
'';
|
|
47
|
+
|
|
48
|
+
const model =
|
|
49
|
+
env('ERRORS_LLM_MODEL') ?? env('LLM_MODEL') ?? '';
|
|
50
|
+
|
|
51
|
+
const messageTypeRaw =
|
|
52
|
+
env('ERRORS_LLM_MESSAGE_TYPE') ?? env('ERRORS_LLM_MESSAGETYPE') ?? env('LLM_MESSAGE_TYPE') ?? env('LLM_MESSAGETYPE') ?? '';
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
enabled: Boolean(enabled),
|
|
56
|
+
baseURL: String(baseURL ?? '').trim(),
|
|
57
|
+
apiKey: String(apiKey ?? '').trim(),
|
|
58
|
+
model: String(model ?? '').trim(),
|
|
59
|
+
messageType: normalizeMessageType(messageTypeRaw || 'endUser'),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { MESSAGE_TYPES };
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Validate errors.llm when enabled: require baseURL, apiKey, and model (after LLM_ fallback).
|
|
67
|
+
* Call at takeoff. Throws if enabled but config is invalid; no-op otherwise.
|
|
68
|
+
* @throws {Error} If errors.llm.enabled is true but any of baseURL, apiKey, or model is missing
|
|
69
|
+
*/
|
|
70
|
+
export function validateErrorsLlmAtTakeoff() {
|
|
71
|
+
const { enabled, baseURL, apiKey, model } = getErrorsLlmConfig();
|
|
72
|
+
if (!enabled) return;
|
|
73
|
+
|
|
74
|
+
const missing = [];
|
|
75
|
+
if (!baseURL) missing.push('baseURL (ERRORS_LLM_BASE_URL or LLM_BASE_URL)');
|
|
76
|
+
if (!apiKey) missing.push('apiKey (ERRORS_LLM_API_KEY or LLM_API_KEY)');
|
|
77
|
+
if (!model) missing.push('model (ERRORS_LLM_MODEL or LLM_MODEL)');
|
|
78
|
+
|
|
79
|
+
if (missing.length > 0) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
`errors.llm is enabled but required config is missing: ${missing.join(', ')}. Set these env vars or disable errors.llm.enabled.`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
package/utils/request-logger.js
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
import { env } from 'tej-env';
|
|
2
|
-
import ansi from 'ansi-colors';
|
|
3
|
-
import TejLogger from 'tej-logger';
|
|
4
|
-
|
|
5
|
-
const logger = new TejLogger('Tejas.Request');
|
|
6
|
-
const { italic, bold, blue, white, bgGreen, bgRed, whiteBright } = ansi;
|
|
7
|
-
|
|
8
|
-
function logHttpRequest(ammo, next) {
|
|
9
|
-
if (!env('LOG_HTTP_REQUESTS')) return;
|
|
10
|
-
|
|
11
|
-
const startTime = new Date();
|
|
12
|
-
ammo.res.on('finish', () => {
|
|
13
|
-
const res = ammo.res;
|
|
14
|
-
const method = italic(whiteBright(ammo.method));
|
|
15
|
-
const endpoint = bold(ammo.endpoint);
|
|
16
|
-
const statusCode =
|
|
17
|
-
res.statusCode >= 400
|
|
18
|
-
? bgRed(whiteBright(bold(`✖ ${res.statusCode}`)))
|
|
19
|
-
: bgGreen(whiteBright(bold(`✔ ${res.statusCode}`)));
|
|
20
|
-
|
|
21
|
-
const duration = white(`${new Date() - startTime}ms`);
|
|
22
|
-
const payload = `${blue('Request')}: ${white(
|
|
23
|
-
JSON.stringify(ammo.payload),
|
|
24
|
-
)}`;
|
|
25
|
-
const dispatchedData = `${blue('Response')}: ${white(ammo.dispatchedData)}`;
|
|
26
|
-
const nextLine = '\n';
|
|
27
|
-
|
|
28
|
-
logger.log(
|
|
29
|
-
italic(`Incoming request from ${ammo.ip}`),
|
|
30
|
-
nextLine,
|
|
31
|
-
method,
|
|
32
|
-
endpoint,
|
|
33
|
-
statusCode,
|
|
34
|
-
duration,
|
|
35
|
-
nextLine,
|
|
36
|
-
payload,
|
|
37
|
-
nextLine,
|
|
38
|
-
dispatchedData,
|
|
39
|
-
);
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export default logHttpRequest;
|
|
1
|
+
import { env } from 'tej-env';
|
|
2
|
+
import ansi from 'ansi-colors';
|
|
3
|
+
import TejLogger from 'tej-logger';
|
|
4
|
+
|
|
5
|
+
const logger = new TejLogger('Tejas.Request');
|
|
6
|
+
const { italic, bold, blue, white, bgGreen, bgRed, whiteBright } = ansi;
|
|
7
|
+
|
|
8
|
+
function logHttpRequest(ammo, next) {
|
|
9
|
+
if (!env('LOG_HTTP_REQUESTS')) return;
|
|
10
|
+
|
|
11
|
+
const startTime = new Date();
|
|
12
|
+
ammo.res.on('finish', () => {
|
|
13
|
+
const res = ammo.res;
|
|
14
|
+
const method = italic(whiteBright(ammo.method));
|
|
15
|
+
const endpoint = bold(ammo.endpoint);
|
|
16
|
+
const statusCode =
|
|
17
|
+
res.statusCode >= 400
|
|
18
|
+
? bgRed(whiteBright(bold(`✖ ${res.statusCode}`)))
|
|
19
|
+
: bgGreen(whiteBright(bold(`✔ ${res.statusCode}`)));
|
|
20
|
+
|
|
21
|
+
const duration = white(`${new Date() - startTime}ms`);
|
|
22
|
+
const payload = `${blue('Request')}: ${white(
|
|
23
|
+
JSON.stringify(ammo.payload),
|
|
24
|
+
)}`;
|
|
25
|
+
const dispatchedData = `${blue('Response')}: ${white(ammo.dispatchedData)}`;
|
|
26
|
+
const nextLine = '\n';
|
|
27
|
+
|
|
28
|
+
logger.log(
|
|
29
|
+
italic(`Incoming request from ${ammo.ip}`),
|
|
30
|
+
nextLine,
|
|
31
|
+
method,
|
|
32
|
+
endpoint,
|
|
33
|
+
statusCode,
|
|
34
|
+
duration,
|
|
35
|
+
nextLine,
|
|
36
|
+
payload,
|
|
37
|
+
nextLine,
|
|
38
|
+
dispatchedData,
|
|
39
|
+
);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export default logHttpRequest;
|
package/utils/status-codes.js
CHANGED
|
@@ -1,82 +1,82 @@
|
|
|
1
|
-
const statuses = {
|
|
2
|
-
'100': 'Continue',
|
|
3
|
-
'101': 'Switching Protocols',
|
|
4
|
-
'102': 'Processing',
|
|
5
|
-
'103': 'Early Hints',
|
|
6
|
-
'200': 'OK',
|
|
7
|
-
'201': 'Created',
|
|
8
|
-
'202': 'Accepted',
|
|
9
|
-
'203': 'Non-Authoritative Information',
|
|
10
|
-
'204': 'No Content',
|
|
11
|
-
'205': 'Reset Content',
|
|
12
|
-
'206': 'Partial Content',
|
|
13
|
-
'207': 'Multi-Status',
|
|
14
|
-
'208': 'Already Reported',
|
|
15
|
-
'226': 'IM Used',
|
|
16
|
-
'300': 'Multiple Choices',
|
|
17
|
-
'301': 'Moved Permanently',
|
|
18
|
-
'302': 'Found',
|
|
19
|
-
'303': 'See Other',
|
|
20
|
-
'304': 'Not Modified',
|
|
21
|
-
'305': 'Use Proxy',
|
|
22
|
-
'307': 'Temporary Redirect',
|
|
23
|
-
'308': 'Permanent Redirect',
|
|
24
|
-
'400': 'Bad Request',
|
|
25
|
-
'401': 'Unauthorized',
|
|
26
|
-
'402': 'Payment Required',
|
|
27
|
-
'403': 'Forbidden',
|
|
28
|
-
'404': 'Not Found',
|
|
29
|
-
'405': 'Method Not Allowed',
|
|
30
|
-
'406': 'Not Acceptable',
|
|
31
|
-
'407': 'Proxy Authentication Required',
|
|
32
|
-
'408': 'Request Timeout',
|
|
33
|
-
'409': 'Conflict',
|
|
34
|
-
'410': 'Gone',
|
|
35
|
-
'411': 'Length Required',
|
|
36
|
-
'412': 'Precondition Failed',
|
|
37
|
-
'413': 'Payload Too Large',
|
|
38
|
-
'414': 'URI Too Long',
|
|
39
|
-
'415': 'Unsupported Media Type',
|
|
40
|
-
'416': 'Range Not Satisfiable',
|
|
41
|
-
'417': 'Expectation Failed',
|
|
42
|
-
'418': 'I\'m a Teapot',
|
|
43
|
-
'421': 'Misdirected Request',
|
|
44
|
-
'422': 'Unprocessable Entity',
|
|
45
|
-
'423': 'Locked',
|
|
46
|
-
'424': 'Failed Dependency',
|
|
47
|
-
'425': 'Too Early',
|
|
48
|
-
'426': 'Upgrade Required',
|
|
49
|
-
'428': 'Precondition Required',
|
|
50
|
-
'429': 'Too Many Requests',
|
|
51
|
-
'431': 'Request Header Fields Too Large',
|
|
52
|
-
'451': 'Unavailable For Legal Reasons',
|
|
53
|
-
'500': 'Internal Server Error',
|
|
54
|
-
'501': 'Not Implemented',
|
|
55
|
-
'502': 'Bad Gateway',
|
|
56
|
-
'503': 'Service Unavailable',
|
|
57
|
-
'504': 'Gateway Timeout',
|
|
58
|
-
'505': 'HTTP Version Not Supported',
|
|
59
|
-
'506': 'Variant Also Negotiates',
|
|
60
|
-
'507': 'Insufficient Storage',
|
|
61
|
-
'508': 'Loop Detected',
|
|
62
|
-
'509': 'Bandwidth Limit Exceeded',
|
|
63
|
-
'510': 'Not Extended',
|
|
64
|
-
'511': 'Network Authentication Required',
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const reverseStatuses = Object.fromEntries(
|
|
68
|
-
Object.entries(statuses).map(([key, value]) => [value, key]));
|
|
69
|
-
|
|
70
|
-
const toStatusCode = (message) => {
|
|
71
|
-
return reverseStatuses[message];
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
const toStatusMessage = (code) => {
|
|
75
|
-
return statuses[code];
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
const isStatusCode = (code) => {
|
|
79
|
-
return statuses[code] !== undefined;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export {toStatusCode, toStatusMessage, isStatusCode};
|
|
1
|
+
const statuses = {
|
|
2
|
+
'100': 'Continue',
|
|
3
|
+
'101': 'Switching Protocols',
|
|
4
|
+
'102': 'Processing',
|
|
5
|
+
'103': 'Early Hints',
|
|
6
|
+
'200': 'OK',
|
|
7
|
+
'201': 'Created',
|
|
8
|
+
'202': 'Accepted',
|
|
9
|
+
'203': 'Non-Authoritative Information',
|
|
10
|
+
'204': 'No Content',
|
|
11
|
+
'205': 'Reset Content',
|
|
12
|
+
'206': 'Partial Content',
|
|
13
|
+
'207': 'Multi-Status',
|
|
14
|
+
'208': 'Already Reported',
|
|
15
|
+
'226': 'IM Used',
|
|
16
|
+
'300': 'Multiple Choices',
|
|
17
|
+
'301': 'Moved Permanently',
|
|
18
|
+
'302': 'Found',
|
|
19
|
+
'303': 'See Other',
|
|
20
|
+
'304': 'Not Modified',
|
|
21
|
+
'305': 'Use Proxy',
|
|
22
|
+
'307': 'Temporary Redirect',
|
|
23
|
+
'308': 'Permanent Redirect',
|
|
24
|
+
'400': 'Bad Request',
|
|
25
|
+
'401': 'Unauthorized',
|
|
26
|
+
'402': 'Payment Required',
|
|
27
|
+
'403': 'Forbidden',
|
|
28
|
+
'404': 'Not Found',
|
|
29
|
+
'405': 'Method Not Allowed',
|
|
30
|
+
'406': 'Not Acceptable',
|
|
31
|
+
'407': 'Proxy Authentication Required',
|
|
32
|
+
'408': 'Request Timeout',
|
|
33
|
+
'409': 'Conflict',
|
|
34
|
+
'410': 'Gone',
|
|
35
|
+
'411': 'Length Required',
|
|
36
|
+
'412': 'Precondition Failed',
|
|
37
|
+
'413': 'Payload Too Large',
|
|
38
|
+
'414': 'URI Too Long',
|
|
39
|
+
'415': 'Unsupported Media Type',
|
|
40
|
+
'416': 'Range Not Satisfiable',
|
|
41
|
+
'417': 'Expectation Failed',
|
|
42
|
+
'418': 'I\'m a Teapot',
|
|
43
|
+
'421': 'Misdirected Request',
|
|
44
|
+
'422': 'Unprocessable Entity',
|
|
45
|
+
'423': 'Locked',
|
|
46
|
+
'424': 'Failed Dependency',
|
|
47
|
+
'425': 'Too Early',
|
|
48
|
+
'426': 'Upgrade Required',
|
|
49
|
+
'428': 'Precondition Required',
|
|
50
|
+
'429': 'Too Many Requests',
|
|
51
|
+
'431': 'Request Header Fields Too Large',
|
|
52
|
+
'451': 'Unavailable For Legal Reasons',
|
|
53
|
+
'500': 'Internal Server Error',
|
|
54
|
+
'501': 'Not Implemented',
|
|
55
|
+
'502': 'Bad Gateway',
|
|
56
|
+
'503': 'Service Unavailable',
|
|
57
|
+
'504': 'Gateway Timeout',
|
|
58
|
+
'505': 'HTTP Version Not Supported',
|
|
59
|
+
'506': 'Variant Also Negotiates',
|
|
60
|
+
'507': 'Insufficient Storage',
|
|
61
|
+
'508': 'Loop Detected',
|
|
62
|
+
'509': 'Bandwidth Limit Exceeded',
|
|
63
|
+
'510': 'Not Extended',
|
|
64
|
+
'511': 'Network Authentication Required',
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const reverseStatuses = Object.fromEntries(
|
|
68
|
+
Object.entries(statuses).map(([key, value]) => [value, key]));
|
|
69
|
+
|
|
70
|
+
const toStatusCode = (message) => {
|
|
71
|
+
return reverseStatuses[message];
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const toStatusMessage = (code) => {
|
|
75
|
+
return statuses[code];
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const isStatusCode = (code) => {
|
|
79
|
+
return statuses[code] !== undefined;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export {toStatusCode, toStatusMessage, isStatusCode};
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
// TODO Create a better entrypoint html
|
|
2
|
-
|
|
3
|
-
const html =
|
|
4
|
-
"" +
|
|
5
|
-
"<!DOCTYPE html>" +
|
|
6
|
-
'<html lang="en">' +
|
|
7
|
-
"<head>" +
|
|
8
|
-
'<meta charset="UTF-8">' +
|
|
9
|
-
'<meta http-equiv="X-UA-Compatible" content="IE=edge">' +
|
|
10
|
-
'<meta name="viewport" content="width=device-width, initial-scale=1.0">' +
|
|
11
|
-
"<title>te.js</title>" +
|
|
12
|
-
"</head>" +
|
|
13
|
-
"<body>" +
|
|
14
|
-
"<h1>Tejas is flying</h1>" +
|
|
15
|
-
"</body>" +
|
|
16
|
-
"</html>";
|
|
17
|
-
|
|
18
|
-
export default html;
|
|
1
|
+
// TODO Create a better entrypoint html
|
|
2
|
+
|
|
3
|
+
const html =
|
|
4
|
+
"" +
|
|
5
|
+
"<!DOCTYPE html>" +
|
|
6
|
+
'<html lang="en">' +
|
|
7
|
+
"<head>" +
|
|
8
|
+
'<meta charset="UTF-8">' +
|
|
9
|
+
'<meta http-equiv="X-UA-Compatible" content="IE=edge">' +
|
|
10
|
+
'<meta name="viewport" content="width=device-width, initial-scale=1.0">' +
|
|
11
|
+
"<title>te.js</title>" +
|
|
12
|
+
"</head>" +
|
|
13
|
+
"<body>" +
|
|
14
|
+
"<h1>Tejas is flying</h1>" +
|
|
15
|
+
"</body>" +
|
|
16
|
+
"</html>";
|
|
17
|
+
|
|
18
|
+
export default html;
|
package/auto-docs/llm/index.js
DELETED
package/auto-docs/llm/parse.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parse JSON from LLM response text (handles markdown code blocks).
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Extract the first JSON object from a string.
|
|
7
|
-
* @param {string} str - Raw LLM response
|
|
8
|
-
* @returns {object|null}
|
|
9
|
-
*/
|
|
10
|
-
export function extractJSON(str) {
|
|
11
|
-
if (!str || typeof str !== 'string') return null;
|
|
12
|
-
const trimmed = str.trim();
|
|
13
|
-
const open = trimmed.indexOf('{');
|
|
14
|
-
if (open === -1) return null;
|
|
15
|
-
let depth = 0;
|
|
16
|
-
let end = -1;
|
|
17
|
-
for (let i = open; i < trimmed.length; i++) {
|
|
18
|
-
if (trimmed[i] === '{') depth++;
|
|
19
|
-
else if (trimmed[i] === '}') {
|
|
20
|
-
depth--;
|
|
21
|
-
if (depth === 0) {
|
|
22
|
-
end = i + 1;
|
|
23
|
-
break;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
if (end === -1) return null;
|
|
28
|
-
try {
|
|
29
|
-
return JSON.parse(trimmed.slice(open, end));
|
|
30
|
-
} catch {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Extract the first JSON array from a string.
|
|
37
|
-
* @param {string} str - Raw LLM response
|
|
38
|
-
* @returns {Array|null}
|
|
39
|
-
*/
|
|
40
|
-
export function extractJSONArray(str) {
|
|
41
|
-
if (!str || typeof str !== 'string') return null;
|
|
42
|
-
const trimmed = str.trim();
|
|
43
|
-
const open = trimmed.indexOf('[');
|
|
44
|
-
if (open === -1) return null;
|
|
45
|
-
let depth = 0;
|
|
46
|
-
let end = -1;
|
|
47
|
-
for (let i = open; i < trimmed.length; i++) {
|
|
48
|
-
if (trimmed[i] === '[') depth++;
|
|
49
|
-
else if (trimmed[i] === ']') {
|
|
50
|
-
depth--;
|
|
51
|
-
if (depth === 0) {
|
|
52
|
-
end = i + 1;
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
if (end === -1) return null;
|
|
58
|
-
try {
|
|
59
|
-
return JSON.parse(trimmed.slice(open, end));
|
|
60
|
-
} catch {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Reconcile LLM-ordered tag names with actual tag objects. Returns tags in desired order;
|
|
67
|
-
* any tag not in orderedTagNames is appended at the end.
|
|
68
|
-
* @param {string[]} orderedTagNames - Tag names in desired order (from LLM)
|
|
69
|
-
* @param {Array<{ name: string, description?: string }>} tags - Current spec.tags
|
|
70
|
-
* @returns {Array<{ name: string, description?: string }>} Tags reordered
|
|
71
|
-
*/
|
|
72
|
-
export function reconcileOrderedTags(orderedTagNames, tags) {
|
|
73
|
-
if (!Array.isArray(tags) || !tags.length) return [];
|
|
74
|
-
if (!Array.isArray(orderedTagNames) || !orderedTagNames.length) return [...tags];
|
|
75
|
-
const byName = new Map(tags.map((t) => [t.name, t]));
|
|
76
|
-
const ordered = [];
|
|
77
|
-
for (const name of orderedTagNames) {
|
|
78
|
-
const tag = byName.get(name);
|
|
79
|
-
if (tag) {
|
|
80
|
-
ordered.push(tag);
|
|
81
|
-
byName.delete(name);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
for (const [, tag] of byName) {
|
|
85
|
-
ordered.push(tag);
|
|
86
|
-
}
|
|
87
|
-
return ordered;
|
|
88
|
-
}
|