Skip to content

Commit 93acddb

Browse files
committed
feat: add extraction runtime
1 parent 7cf457f commit 93acddb

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

src/index.ts

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { loadStringConstants } from "./constants.js";
2+
import { loadConfig } from "./config.js";
3+
import { readTextFile, writeTextFile } from "./fs.js";
4+
import { ProgressReporter } from "./progress.js";
5+
import { discoverRoutes } from "./routes.js";
6+
import { extractRouteData } from "./analysis.js";
7+
import { buildSpec } from "./spec.js";
8+
import { indexFunctions } from "./symbols.js";
9+
import { resolveRawGithubUrl, resolveSourcePath } from "./source.js";
10+
import type { ApiSpec, CliOptions } from "./types.js";
11+
12+
export async function runExtraction(cliOptions: CliOptions): Promise<ApiSpec> {
13+
const progress = new ProgressReporter(cliOptions.json);
14+
const configStep = progress.startStep("loading config");
15+
const config = await loadConfig(cliOptions.configPath ?? "./config.json", cliOptions);
16+
configStep.done();
17+
18+
const routesStep = progress.startStep("discovering routes");
19+
const routes = await discoverRoutes(
20+
resolveRawGithubUrl(config.sourceBranch, resolveSourcePath(config.rootDir, config.routeFile)),
21+
);
22+
routesStep.done(`${routes.length} routes`);
23+
24+
const constantsStep = progress.startStep("loading constants");
25+
const constants = await loadStringConstants(config.rootDir, config.sourceBranch);
26+
constantsStep.done(`${constants.size} constants`);
27+
28+
const symbolsStep = progress.startStep("indexing functions");
29+
const functions = await indexFunctions(config.rootDir, config.includeHelpers, config.sourceBranch);
30+
symbolsStep.done(`${functions.size} functions`);
31+
32+
const extractStep = progress.startStep("extracting route parameters");
33+
const routeExtractions = routes.map((route) =>
34+
extractRouteData(route, functions, constants, config.maxCallDepth, config.debug),
35+
);
36+
extractStep.done(`${routeExtractions.length} route scans`);
37+
38+
const specStep = progress.startStep("building output");
39+
const diagnostics = routeExtractions.flatMap((extraction) => extraction.diagnostics);
40+
const spec = buildSpec(config, routeExtractions, diagnostics);
41+
const outputText = `${JSON.stringify(spec, null, 2)}\n`;
42+
await writeTextFile(config.outputPath, outputText);
43+
if (config.diagnosticsOutputPath !== undefined) {
44+
await writeTextFile(config.diagnosticsOutputPath, `${JSON.stringify(diagnostics, null, 2)}\n`);
45+
}
46+
specStep.done(config.outputPath);
47+
48+
if (config.failOnDiagnostics && diagnostics.length > 0) {
49+
throw new Error("Extraction produced diagnostics.");
50+
}
51+
52+
if (
53+
config.failOnUnresolved &&
54+
diagnostics.some((diagnostic) => diagnostic.level === "error")
55+
) {
56+
throw new Error("Extraction produced unresolved handler errors.");
57+
}
58+
59+
return spec;
60+
}
61+
62+
export async function readSpec(filePath: string): Promise<ApiSpec> {
63+
const sourceText = await readTextFile(filePath);
64+
return JSON.parse(sourceText) as ApiSpec;
65+
}

0 commit comments

Comments
 (0)