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.
- package/README.md +197 -196
- 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 -7
- package/auto-docs/docs-llm/prompts.js +222 -222
- package/auto-docs/docs-llm/provider.js +132 -132
- 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/cors/index.js +71 -0
- 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 -490
- package/docs/auto-docs.md +216 -216
- package/docs/cli.md +152 -152
- package/docs/configuration.md +275 -275
- package/docs/database.md +390 -390
- package/docs/error-handling.md +438 -438
- package/docs/file-uploads.md +333 -333
- package/docs/getting-started.md +214 -214
- package/docs/middleware.md +355 -355
- package/docs/rate-limiting.md +393 -393
- package/docs/routing.md +302 -302
- package/lib/llm/client.js +73 -0
- package/lib/llm/index.js +7 -0
- package/lib/llm/parse.js +89 -0
- package/package.json +64 -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 -415
- package/server/endpoint.js +97 -74
- package/server/error.js +9 -9
- package/server/errors/code-context.js +125 -125
- package/server/errors/llm-error-service.js +140 -140
- package/server/files/helper.js +33 -33
- package/server/files/uploader.js +143 -143
- package/server/handler.js +158 -119
- 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 -402
- package/utils/auto-register.js +17 -17
- package/utils/configuration.js +64 -64
- package/utils/errors-llm-config.js +84 -84
- package/utils/request-logger.js +43 -43
- package/utils/status-codes.js +82 -82
- package/utils/tejas-entrypoint-html.js +18 -18
|
@@ -1,107 +1,107 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* OpenAPI 3.0 spec generator for te.js auto-documentation.
|
|
3
|
-
* Orchestrates spec-builders and endpoint-processor; builds final spec object.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { OPENAPI_VERSION } from '../constants.js';
|
|
7
|
-
import { createVerboseLogger } from '../utils/logger.js';
|
|
8
|
-
import {
|
|
9
|
-
processEndpoint,
|
|
10
|
-
addEndpointToPaths,
|
|
11
|
-
buildTagDescriptions,
|
|
12
|
-
applyTagDisplayNames,
|
|
13
|
-
} from './endpoint-processor.js';
|
|
14
|
-
import {
|
|
15
|
-
toOpenAPIPath,
|
|
16
|
-
getPathParameters,
|
|
17
|
-
getQueryParameters,
|
|
18
|
-
buildSchemaFromMetadata,
|
|
19
|
-
buildRequestBody,
|
|
20
|
-
buildResponses,
|
|
21
|
-
buildOperation,
|
|
22
|
-
mergeMetadata,
|
|
23
|
-
} from './spec-builders.js';
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Build OpenAPI 3.0 spec from registry and options.
|
|
27
|
-
* @param {object} registry - Target registry with .targets
|
|
28
|
-
* @param {object} [options] - { llm?, info?, servers?, level?, dirTargets?, verbose?, logger? }
|
|
29
|
-
* @returns {Promise<object>} OpenAPI 3.0 spec
|
|
30
|
-
*/
|
|
31
|
-
async function generateOpenAPISpec(registry, options = {}) {
|
|
32
|
-
const {
|
|
33
|
-
llm,
|
|
34
|
-
info = {},
|
|
35
|
-
servers,
|
|
36
|
-
level = 1,
|
|
37
|
-
dirTargets = process.env.DIR_TARGETS || 'targets',
|
|
38
|
-
verbose = false,
|
|
39
|
-
logger = null,
|
|
40
|
-
} = options;
|
|
41
|
-
const targets = registry?.targets ?? [];
|
|
42
|
-
const paths = {};
|
|
43
|
-
const groupEndpoints = new Map();
|
|
44
|
-
const dependencyContextByGroup = new Map();
|
|
45
|
-
|
|
46
|
-
const useLlm = !!llm && typeof llm.enhanceEndpointDocs === 'function';
|
|
47
|
-
const effectiveLevel = level === 3 ? 2 : Math.max(1, Math.min(2, level));
|
|
48
|
-
const log = createVerboseLogger(logger, verbose);
|
|
49
|
-
const preferEnhanced = effectiveLevel === 2;
|
|
50
|
-
|
|
51
|
-
for (const target of targets) {
|
|
52
|
-
const result = await processEndpoint(target, {
|
|
53
|
-
llm,
|
|
54
|
-
effectiveLevel,
|
|
55
|
-
dirTargets,
|
|
56
|
-
dependencyContextByGroup,
|
|
57
|
-
useLlm,
|
|
58
|
-
preferEnhanced,
|
|
59
|
-
log,
|
|
60
|
-
});
|
|
61
|
-
if (!groupEndpoints.has(result.tag)) groupEndpoints.set(result.tag, []);
|
|
62
|
-
groupEndpoints.get(result.tag).push(result.groupEntry);
|
|
63
|
-
addEndpointToPaths(paths, result);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const tagDescriptions = await buildTagDescriptions(
|
|
67
|
-
groupEndpoints,
|
|
68
|
-
dependencyContextByGroup,
|
|
69
|
-
useLlm ? llm : null,
|
|
70
|
-
{ effectiveLevel, log },
|
|
71
|
-
);
|
|
72
|
-
applyTagDisplayNames(paths, tagDescriptions);
|
|
73
|
-
|
|
74
|
-
const tags = Array.from(tagDescriptions.entries()).map(([, { name, description }]) => ({
|
|
75
|
-
name,
|
|
76
|
-
...(description && { description }),
|
|
77
|
-
}));
|
|
78
|
-
|
|
79
|
-
const spec = {
|
|
80
|
-
openapi: OPENAPI_VERSION,
|
|
81
|
-
info: {
|
|
82
|
-
title: info.title ?? 'API',
|
|
83
|
-
version: info.version ?? '1.0.0',
|
|
84
|
-
...(info.description && { description: info.description }),
|
|
85
|
-
},
|
|
86
|
-
tags: tags.length > 0 ? tags : undefined,
|
|
87
|
-
paths,
|
|
88
|
-
};
|
|
89
|
-
if (Array.isArray(servers) && servers.length > 0) {
|
|
90
|
-
spec.servers = servers;
|
|
91
|
-
}
|
|
92
|
-
return spec;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export {
|
|
96
|
-
OPENAPI_VERSION,
|
|
97
|
-
toOpenAPIPath,
|
|
98
|
-
getPathParameters,
|
|
99
|
-
getQueryParameters,
|
|
100
|
-
buildSchemaFromMetadata,
|
|
101
|
-
buildRequestBody,
|
|
102
|
-
buildResponses,
|
|
103
|
-
buildOperation,
|
|
104
|
-
mergeMetadata,
|
|
105
|
-
generateOpenAPISpec,
|
|
106
|
-
};
|
|
107
|
-
export default generateOpenAPISpec;
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI 3.0 spec generator for te.js auto-documentation.
|
|
3
|
+
* Orchestrates spec-builders and endpoint-processor; builds final spec object.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { OPENAPI_VERSION } from '../constants.js';
|
|
7
|
+
import { createVerboseLogger } from '../utils/logger.js';
|
|
8
|
+
import {
|
|
9
|
+
processEndpoint,
|
|
10
|
+
addEndpointToPaths,
|
|
11
|
+
buildTagDescriptions,
|
|
12
|
+
applyTagDisplayNames,
|
|
13
|
+
} from './endpoint-processor.js';
|
|
14
|
+
import {
|
|
15
|
+
toOpenAPIPath,
|
|
16
|
+
getPathParameters,
|
|
17
|
+
getQueryParameters,
|
|
18
|
+
buildSchemaFromMetadata,
|
|
19
|
+
buildRequestBody,
|
|
20
|
+
buildResponses,
|
|
21
|
+
buildOperation,
|
|
22
|
+
mergeMetadata,
|
|
23
|
+
} from './spec-builders.js';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Build OpenAPI 3.0 spec from registry and options.
|
|
27
|
+
* @param {object} registry - Target registry with .targets
|
|
28
|
+
* @param {object} [options] - { llm?, info?, servers?, level?, dirTargets?, verbose?, logger? }
|
|
29
|
+
* @returns {Promise<object>} OpenAPI 3.0 spec
|
|
30
|
+
*/
|
|
31
|
+
async function generateOpenAPISpec(registry, options = {}) {
|
|
32
|
+
const {
|
|
33
|
+
llm,
|
|
34
|
+
info = {},
|
|
35
|
+
servers,
|
|
36
|
+
level = 1,
|
|
37
|
+
dirTargets = process.env.DIR_TARGETS || 'targets',
|
|
38
|
+
verbose = false,
|
|
39
|
+
logger = null,
|
|
40
|
+
} = options;
|
|
41
|
+
const targets = registry?.targets ?? [];
|
|
42
|
+
const paths = {};
|
|
43
|
+
const groupEndpoints = new Map();
|
|
44
|
+
const dependencyContextByGroup = new Map();
|
|
45
|
+
|
|
46
|
+
const useLlm = !!llm && typeof llm.enhanceEndpointDocs === 'function';
|
|
47
|
+
const effectiveLevel = level === 3 ? 2 : Math.max(1, Math.min(2, level));
|
|
48
|
+
const log = createVerboseLogger(logger, verbose);
|
|
49
|
+
const preferEnhanced = effectiveLevel === 2;
|
|
50
|
+
|
|
51
|
+
for (const target of targets) {
|
|
52
|
+
const result = await processEndpoint(target, {
|
|
53
|
+
llm,
|
|
54
|
+
effectiveLevel,
|
|
55
|
+
dirTargets,
|
|
56
|
+
dependencyContextByGroup,
|
|
57
|
+
useLlm,
|
|
58
|
+
preferEnhanced,
|
|
59
|
+
log,
|
|
60
|
+
});
|
|
61
|
+
if (!groupEndpoints.has(result.tag)) groupEndpoints.set(result.tag, []);
|
|
62
|
+
groupEndpoints.get(result.tag).push(result.groupEntry);
|
|
63
|
+
addEndpointToPaths(paths, result);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const tagDescriptions = await buildTagDescriptions(
|
|
67
|
+
groupEndpoints,
|
|
68
|
+
dependencyContextByGroup,
|
|
69
|
+
useLlm ? llm : null,
|
|
70
|
+
{ effectiveLevel, log },
|
|
71
|
+
);
|
|
72
|
+
applyTagDisplayNames(paths, tagDescriptions);
|
|
73
|
+
|
|
74
|
+
const tags = Array.from(tagDescriptions.entries()).map(([, { name, description }]) => ({
|
|
75
|
+
name,
|
|
76
|
+
...(description && { description }),
|
|
77
|
+
}));
|
|
78
|
+
|
|
79
|
+
const spec = {
|
|
80
|
+
openapi: OPENAPI_VERSION,
|
|
81
|
+
info: {
|
|
82
|
+
title: info.title ?? 'API',
|
|
83
|
+
version: info.version ?? '1.0.0',
|
|
84
|
+
...(info.description && { description: info.description }),
|
|
85
|
+
},
|
|
86
|
+
tags: tags.length > 0 ? tags : undefined,
|
|
87
|
+
paths,
|
|
88
|
+
};
|
|
89
|
+
if (Array.isArray(servers) && servers.length > 0) {
|
|
90
|
+
spec.servers = servers;
|
|
91
|
+
}
|
|
92
|
+
return spec;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export {
|
|
96
|
+
OPENAPI_VERSION,
|
|
97
|
+
toOpenAPIPath,
|
|
98
|
+
getPathParameters,
|
|
99
|
+
getQueryParameters,
|
|
100
|
+
buildSchemaFromMetadata,
|
|
101
|
+
buildRequestBody,
|
|
102
|
+
buildResponses,
|
|
103
|
+
buildOperation,
|
|
104
|
+
mergeMetadata,
|
|
105
|
+
generateOpenAPISpec,
|
|
106
|
+
};
|
|
107
|
+
export default generateOpenAPISpec;
|
|
@@ -1,131 +1,131 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Level 3 pipeline: reorder OpenAPI tag groups by importance and generate overview page.
|
|
3
|
-
* Single entry point is runLevel3(spec, options, llm). Runs after the spec is generated (level 2 quality).
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import path from 'node:path';
|
|
7
|
-
import { writeFile } from 'node:fs/promises';
|
|
8
|
-
import { createVerboseLogger } from '../utils/logger.js';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Resolve overview file path from option or derive from outputPath.
|
|
12
|
-
* @param {string} [overviewPathOption] - Explicit path for API_OVERVIEW.md
|
|
13
|
-
* @param {string} [outputPath] - OpenAPI spec output path (dir used for default overview)
|
|
14
|
-
* @returns {string} Overview path or ''
|
|
15
|
-
*/
|
|
16
|
-
export function resolveOverviewPath(overviewPathOption, outputPath) {
|
|
17
|
-
if (overviewPathOption && typeof overviewPathOption === 'string') {
|
|
18
|
-
return overviewPathOption;
|
|
19
|
-
}
|
|
20
|
-
if (outputPath && typeof outputPath === 'string') {
|
|
21
|
-
return path.join(path.dirname(outputPath), 'API_OVERVIEW.md');
|
|
22
|
-
}
|
|
23
|
-
return '';
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Generate overview markdown from the spec (no I/O). Pure except LLM call.
|
|
28
|
-
* @param {object} spec - OpenAPI 3 spec (after reorder)
|
|
29
|
-
* @param {object} options - { info?: { title?, version?, description? } }
|
|
30
|
-
* @param {object} llm - LLM provider with generateOverviewPage(spec, options)
|
|
31
|
-
* @returns {Promise<{ markdown: string }>}
|
|
32
|
-
*/
|
|
33
|
-
export async function generateOverview(spec, options, llm) {
|
|
34
|
-
if (typeof llm?.generateOverviewPage !== 'function') {
|
|
35
|
-
return { markdown: '' };
|
|
36
|
-
}
|
|
37
|
-
const info = options?.info ?? {};
|
|
38
|
-
const { markdown } = await llm.generateOverviewPage(spec, {
|
|
39
|
-
title: info.title,
|
|
40
|
-
version: info.version,
|
|
41
|
-
description: info.description,
|
|
42
|
-
});
|
|
43
|
-
return { markdown: markdown || '' };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Write level-3 artifacts: overview file and optionally the spec file.
|
|
48
|
-
* @param {object} spec - OpenAPI 3 spec (may have info.description set)
|
|
49
|
-
* @param {string} overviewPath - Path for API_OVERVIEW.md
|
|
50
|
-
* @param {string} [outputPath] - Path for openapi.json
|
|
51
|
-
* @param {string} [markdown] - Overview markdown content
|
|
52
|
-
* @returns {Promise<void>}
|
|
53
|
-
*/
|
|
54
|
-
export async function writeLevel3Artifacts(spec, overviewPath, outputPath, markdown) {
|
|
55
|
-
if (overviewPath && markdown) {
|
|
56
|
-
await writeFile(overviewPath, markdown, 'utf8');
|
|
57
|
-
}
|
|
58
|
-
if (outputPath && typeof outputPath === 'string') {
|
|
59
|
-
await writeFile(outputPath, JSON.stringify(spec, null, 2), 'utf8');
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Run the full level-3 pipeline: reorder tags, generate overview, write artifacts.
|
|
65
|
-
* @param {object} spec - OpenAPI 3 spec (mutated: tags reordered, info.description set)
|
|
66
|
-
* @param {object} options - { outputPath?, overviewPath?, info?, verbose?, logger? }
|
|
67
|
-
* @param {object} llm - LLM provider with reorderTagsByImportance and generateOverviewPage
|
|
68
|
-
* @returns {Promise<void>}
|
|
69
|
-
*/
|
|
70
|
-
export async function runLevel3(spec, options, llm) {
|
|
71
|
-
const { outputPath, overviewPath: overviewPathOption, info = {}, verbose = false, logger = null } = options;
|
|
72
|
-
const log = createVerboseLogger(logger, verbose);
|
|
73
|
-
|
|
74
|
-
if (!spec?.tags?.length || !llm) return;
|
|
75
|
-
|
|
76
|
-
log('Level 3: reordering tag groups by importance...');
|
|
77
|
-
await reorderSpecTags(spec, llm);
|
|
78
|
-
|
|
79
|
-
const overviewPath = resolveOverviewPath(overviewPathOption, outputPath);
|
|
80
|
-
if (!overviewPath) {
|
|
81
|
-
await writeLevel3Artifacts(spec, '', outputPath);
|
|
82
|
-
if (outputPath) log('Spec updated with reordered tags.');
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
log('Level 3: generating overview...');
|
|
87
|
-
const { markdown } = await generateOverview(spec, { info }, llm);
|
|
88
|
-
if (markdown) {
|
|
89
|
-
spec.info = spec.info || {};
|
|
90
|
-
spec.info.description = markdown;
|
|
91
|
-
log('Overview embedded in spec (info.description) for Scalar.');
|
|
92
|
-
}
|
|
93
|
-
log('Overview file written to ' + overviewPath + '.');
|
|
94
|
-
|
|
95
|
-
await writeLevel3Artifacts(spec, overviewPath, outputPath, markdown);
|
|
96
|
-
if (outputPath) log('Spec written with reordered tags and overview.');
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Reorder spec.tags by importance using the LLM. Mutates and returns the same spec object.
|
|
101
|
-
* @param {object} spec - OpenAPI 3 spec with tags array
|
|
102
|
-
* @param {object} llm - LLM provider with reorderTagsByImportance(spec)
|
|
103
|
-
* @returns {Promise<object>} The same spec with tags reordered
|
|
104
|
-
*/
|
|
105
|
-
export async function reorderSpecTags(spec, llm) {
|
|
106
|
-
if (!spec?.tags?.length || typeof llm?.reorderTagsByImportance !== 'function') {
|
|
107
|
-
return spec;
|
|
108
|
-
}
|
|
109
|
-
const result = await llm.reorderTagsByImportance(spec);
|
|
110
|
-
const ordered = result._orderedTags;
|
|
111
|
-
if (Array.isArray(ordered) && ordered.length > 0) {
|
|
112
|
-
spec.tags = ordered;
|
|
113
|
-
}
|
|
114
|
-
return spec;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Generate overview markdown and write it to overviewPath. (Convenience: generateOverview + write.)
|
|
119
|
-
* @param {object} spec - OpenAPI 3 spec (after reorder)
|
|
120
|
-
* @param {object} options - { overviewPath: string, info?: { title?, version?, description? } }
|
|
121
|
-
* @param {object} llm - LLM provider with generateOverviewPage(spec, options)
|
|
122
|
-
* @returns {Promise<{ markdown: string }>}
|
|
123
|
-
*/
|
|
124
|
-
export async function generateAndWriteOverview(spec, options, llm) {
|
|
125
|
-
const overviewPath = options?.overviewPath;
|
|
126
|
-
const { markdown } = await generateOverview(spec, options, llm);
|
|
127
|
-
if (overviewPath && markdown) {
|
|
128
|
-
await writeFile(overviewPath, markdown, 'utf8');
|
|
129
|
-
}
|
|
130
|
-
return { markdown };
|
|
131
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Level 3 pipeline: reorder OpenAPI tag groups by importance and generate overview page.
|
|
3
|
+
* Single entry point is runLevel3(spec, options, llm). Runs after the spec is generated (level 2 quality).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { writeFile } from 'node:fs/promises';
|
|
8
|
+
import { createVerboseLogger } from '../utils/logger.js';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Resolve overview file path from option or derive from outputPath.
|
|
12
|
+
* @param {string} [overviewPathOption] - Explicit path for API_OVERVIEW.md
|
|
13
|
+
* @param {string} [outputPath] - OpenAPI spec output path (dir used for default overview)
|
|
14
|
+
* @returns {string} Overview path or ''
|
|
15
|
+
*/
|
|
16
|
+
export function resolveOverviewPath(overviewPathOption, outputPath) {
|
|
17
|
+
if (overviewPathOption && typeof overviewPathOption === 'string') {
|
|
18
|
+
return overviewPathOption;
|
|
19
|
+
}
|
|
20
|
+
if (outputPath && typeof outputPath === 'string') {
|
|
21
|
+
return path.join(path.dirname(outputPath), 'API_OVERVIEW.md');
|
|
22
|
+
}
|
|
23
|
+
return '';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Generate overview markdown from the spec (no I/O). Pure except LLM call.
|
|
28
|
+
* @param {object} spec - OpenAPI 3 spec (after reorder)
|
|
29
|
+
* @param {object} options - { info?: { title?, version?, description? } }
|
|
30
|
+
* @param {object} llm - LLM provider with generateOverviewPage(spec, options)
|
|
31
|
+
* @returns {Promise<{ markdown: string }>}
|
|
32
|
+
*/
|
|
33
|
+
export async function generateOverview(spec, options, llm) {
|
|
34
|
+
if (typeof llm?.generateOverviewPage !== 'function') {
|
|
35
|
+
return { markdown: '' };
|
|
36
|
+
}
|
|
37
|
+
const info = options?.info ?? {};
|
|
38
|
+
const { markdown } = await llm.generateOverviewPage(spec, {
|
|
39
|
+
title: info.title,
|
|
40
|
+
version: info.version,
|
|
41
|
+
description: info.description,
|
|
42
|
+
});
|
|
43
|
+
return { markdown: markdown || '' };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Write level-3 artifacts: overview file and optionally the spec file.
|
|
48
|
+
* @param {object} spec - OpenAPI 3 spec (may have info.description set)
|
|
49
|
+
* @param {string} overviewPath - Path for API_OVERVIEW.md
|
|
50
|
+
* @param {string} [outputPath] - Path for openapi.json
|
|
51
|
+
* @param {string} [markdown] - Overview markdown content
|
|
52
|
+
* @returns {Promise<void>}
|
|
53
|
+
*/
|
|
54
|
+
export async function writeLevel3Artifacts(spec, overviewPath, outputPath, markdown) {
|
|
55
|
+
if (overviewPath && markdown) {
|
|
56
|
+
await writeFile(overviewPath, markdown, 'utf8');
|
|
57
|
+
}
|
|
58
|
+
if (outputPath && typeof outputPath === 'string') {
|
|
59
|
+
await writeFile(outputPath, JSON.stringify(spec, null, 2), 'utf8');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Run the full level-3 pipeline: reorder tags, generate overview, write artifacts.
|
|
65
|
+
* @param {object} spec - OpenAPI 3 spec (mutated: tags reordered, info.description set)
|
|
66
|
+
* @param {object} options - { outputPath?, overviewPath?, info?, verbose?, logger? }
|
|
67
|
+
* @param {object} llm - LLM provider with reorderTagsByImportance and generateOverviewPage
|
|
68
|
+
* @returns {Promise<void>}
|
|
69
|
+
*/
|
|
70
|
+
export async function runLevel3(spec, options, llm) {
|
|
71
|
+
const { outputPath, overviewPath: overviewPathOption, info = {}, verbose = false, logger = null } = options;
|
|
72
|
+
const log = createVerboseLogger(logger, verbose);
|
|
73
|
+
|
|
74
|
+
if (!spec?.tags?.length || !llm) return;
|
|
75
|
+
|
|
76
|
+
log('Level 3: reordering tag groups by importance...');
|
|
77
|
+
await reorderSpecTags(spec, llm);
|
|
78
|
+
|
|
79
|
+
const overviewPath = resolveOverviewPath(overviewPathOption, outputPath);
|
|
80
|
+
if (!overviewPath) {
|
|
81
|
+
await writeLevel3Artifacts(spec, '', outputPath);
|
|
82
|
+
if (outputPath) log('Spec updated with reordered tags.');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
log('Level 3: generating overview...');
|
|
87
|
+
const { markdown } = await generateOverview(spec, { info }, llm);
|
|
88
|
+
if (markdown) {
|
|
89
|
+
spec.info = spec.info || {};
|
|
90
|
+
spec.info.description = markdown;
|
|
91
|
+
log('Overview embedded in spec (info.description) for Scalar.');
|
|
92
|
+
}
|
|
93
|
+
log('Overview file written to ' + overviewPath + '.');
|
|
94
|
+
|
|
95
|
+
await writeLevel3Artifacts(spec, overviewPath, outputPath, markdown);
|
|
96
|
+
if (outputPath) log('Spec written with reordered tags and overview.');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Reorder spec.tags by importance using the LLM. Mutates and returns the same spec object.
|
|
101
|
+
* @param {object} spec - OpenAPI 3 spec with tags array
|
|
102
|
+
* @param {object} llm - LLM provider with reorderTagsByImportance(spec)
|
|
103
|
+
* @returns {Promise<object>} The same spec with tags reordered
|
|
104
|
+
*/
|
|
105
|
+
export async function reorderSpecTags(spec, llm) {
|
|
106
|
+
if (!spec?.tags?.length || typeof llm?.reorderTagsByImportance !== 'function') {
|
|
107
|
+
return spec;
|
|
108
|
+
}
|
|
109
|
+
const result = await llm.reorderTagsByImportance(spec);
|
|
110
|
+
const ordered = result._orderedTags;
|
|
111
|
+
if (Array.isArray(ordered) && ordered.length > 0) {
|
|
112
|
+
spec.tags = ordered;
|
|
113
|
+
}
|
|
114
|
+
return spec;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Generate overview markdown and write it to overviewPath. (Convenience: generateOverview + write.)
|
|
119
|
+
* @param {object} spec - OpenAPI 3 spec (after reorder)
|
|
120
|
+
* @param {object} options - { overviewPath: string, info?: { title?, version?, description? } }
|
|
121
|
+
* @param {object} llm - LLM provider with generateOverviewPage(spec, options)
|
|
122
|
+
* @returns {Promise<{ markdown: string }>}
|
|
123
|
+
*/
|
|
124
|
+
export async function generateAndWriteOverview(spec, options, llm) {
|
|
125
|
+
const overviewPath = options?.overviewPath;
|
|
126
|
+
const { markdown } = await generateOverview(spec, options, llm);
|
|
127
|
+
if (overviewPath && markdown) {
|
|
128
|
+
await writeFile(overviewPath, markdown, 'utf8');
|
|
129
|
+
}
|
|
130
|
+
return { markdown };
|
|
131
|
+
}
|