Skip to content

Commit a2e4594

Browse files
committed
fix: Fixed several linter and formatter issues
1 parent a053567 commit a2e4594

36 files changed

+235
-459
lines changed

src/cli.ts

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@ import os from "node:os";
44
import path from "node:path";
55
import { Command } from "commander";
66
import { VectorStoreService } from "./store/VectorStoreService";
7-
import {
8-
FindVersionTool,
9-
ListLibrariesTool,
10-
ScrapeTool,
11-
SearchTool,
12-
} from "./tools";
7+
import { FindVersionTool, ListLibrariesTool, ScrapeTool, SearchTool } from "./tools";
138

149
const formatOutput = (data: unknown) => JSON.stringify(data, null, 2);
1510

@@ -44,11 +39,7 @@ async function main() {
4439
.description("Scrape and index documentation from a URL")
4540
.option("-p, --max-pages <number>", "Maximum pages to scrape", "100")
4641
.option("-d, --max-depth <number>", "Maximum navigation depth", "3")
47-
.option(
48-
"-c, --max-concurrency <number>",
49-
"Maximum concurrent page requests",
50-
"3"
51-
)
42+
.option("-c, --max-concurrency <number>", "Maximum concurrent page requests", "3")
5243
.option("--ignore-errors", "Ignore errors during scraping", true)
5344
.action(async (library, version, url, options) => {
5445
const result = await tools.scrape.execute({
@@ -72,13 +63,13 @@ async function main() {
7263
" - search react 18.0.0 'hooks' -> matches docs for React 18.0.0 or earlier versions\n" +
7364
" - search react 18.0.0 'hooks' --exact-match -> only matches React 18.0.0\n" +
7465
" - search typescript 5.x 'types' -> matches any TypeScript 5.x.x version\n" +
75-
" - search typescript 5.2.x 'types' -> matches any TypeScript 5.2.x version"
66+
" - search typescript 5.2.x 'types' -> matches any TypeScript 5.2.x version",
7667
)
7768
.option("-l, --limit <number>", "Maximum number of results", "5")
7869
.option(
7970
"-e, --exact-match",
8071
"Only use exact version match (e.g., '18.0.0' matches only 18.0.0, not 17.x.x) (default: false)",
81-
false
72+
false,
8273
)
8374
.action(async (library, version, query, options) => {
8475
const result = await tools.search.execute({
@@ -115,10 +106,7 @@ async function main() {
115106

116107
await program.parseAsync();
117108
} catch (error) {
118-
console.error(
119-
"Error:",
120-
error instanceof Error ? error.message : String(error)
121-
);
109+
console.error("Error:", error instanceof Error ? error.message : String(error));
122110
await storeService.shutdown();
123111
process.exit(1);
124112
}

src/mcp/index.ts

Lines changed: 33 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
#!/usr/bin/env node
22
import "dotenv/config";
3-
import {
4-
McpServer,
5-
ResourceTemplate,
6-
} from "@modelcontextprotocol/sdk/server/mcp.js";
3+
import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
74
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
85
import { z } from "zod";
96
import { VectorStoreService } from "../store/VectorStoreService";
@@ -40,7 +37,7 @@ export async function startServer() {
4037
prompts: {},
4138
resources: {},
4239
},
43-
}
40+
},
4441
);
4542

4643
// Scrape docs tool
@@ -56,11 +53,7 @@ export async function startServer() {
5653
.optional()
5754
.default(100)
5855
.describe("Maximum number of pages to scrape"),
59-
maxDepth: z
60-
.number()
61-
.optional()
62-
.default(3)
63-
.describe("Maximum navigation depth"),
56+
maxDepth: z.number().optional().default(3).describe("Maximum navigation depth"),
6457
subpagesOnly: z
6558
.boolean()
6659
.optional()
@@ -80,16 +73,16 @@ export async function startServer() {
8073
});
8174

8275
return createResponse(
83-
`Successfully scraped ${result.pagesScraped} pages from ${url} for ${library} v${version}.`
76+
`Successfully scraped ${result.pagesScraped} pages from ${url} for ${library} v${version}.`,
8477
);
8578
} catch (error) {
8679
return createError(
8780
`Failed to scrape documentation: ${
8881
error instanceof Error ? error.message : String(error)
89-
}`
82+
}`,
9083
);
9184
}
92-
}
85+
},
9386
);
9487

9588
// Search docs tool
@@ -107,14 +100,10 @@ export async function startServer() {
107100
.string()
108101
.optional()
109102
.describe(
110-
"Version of the library (supports exact versions like '18.0.0' or X-Range patterns like '5.x', '5.2.x')"
103+
"Version of the library (supports exact versions like '18.0.0' or X-Range patterns like '5.x', '5.2.x')",
111104
),
112105
query: z.string().describe("Search query"),
113-
limit: z
114-
.number()
115-
.optional()
116-
.default(5)
117-
.describe("Maximum number of results"),
106+
limit: z.number().optional().default(5).describe("Maximum number of results"),
118107
exactMatch: z
119108
.boolean()
120109
.optional()
@@ -136,12 +125,12 @@ export async function startServer() {
136125
------------------------------------------------------------
137126
Result ${i + 1}: ${r.metadata.url}
138127
139-
${r.content}\n`
128+
${r.content}\n`,
140129
);
141130

142131
return createResponse(
143132
`Search results for '${query}' in ${library} v${version}:
144-
${formattedResults.join("")}`
133+
${formattedResults.join("")}`,
145134
);
146135
} catch (error) {
147136
if (error instanceof VersionNotFoundError) {
@@ -151,39 +140,34 @@ ${formattedResults.join("")}`
151140
return createError(
152141
indexedVersions.length > 0
153142
? `Version not found. Available indexed versions for ${library}: ${indexedVersions.join(", ")}`
154-
: `Version not found. No indexed versions available for ${library}.`
143+
: `Version not found. No indexed versions available for ${library}.`,
155144
);
156145
}
157146
return createError(
158147
`Failed to search documentation: ${
159148
error instanceof Error ? error.message : String(error)
160-
}`
149+
}`,
161150
);
162151
}
163-
}
152+
},
164153
);
165154

166155
// List libraries tool
167-
server.tool(
168-
"list_libraries",
169-
"List all indexed libraries",
170-
{},
171-
async () => {
172-
try {
173-
const result = await tools.listLibraries.execute();
156+
server.tool("list_libraries", "List all indexed libraries", {}, async () => {
157+
try {
158+
const result = await tools.listLibraries.execute();
174159

175-
return createResponse(
176-
`Indexed libraries:\n${result.libraries.map((lib) => `- ${lib.name}`).join("\n")}`
177-
);
178-
} catch (error) {
179-
return createError(
180-
`Failed to list libraries: ${
181-
error instanceof Error ? error.message : String(error)
182-
}`
183-
);
184-
}
160+
return createResponse(
161+
`Indexed libraries:\n${result.libraries.map((lib) => `- ${lib.name}`).join("\n")}`,
162+
);
163+
} catch (error) {
164+
return createError(
165+
`Failed to list libraries: ${
166+
error instanceof Error ? error.message : String(error)
167+
}`,
168+
);
185169
}
186-
);
170+
});
187171

188172
// Find version tool
189173
server.tool(
@@ -195,7 +179,7 @@ ${formattedResults.join("")}`
195179
.string()
196180
.optional()
197181
.describe(
198-
"Target version to match (supports exact versions like '18.0.0' or X-Range patterns like '5.x', '5.2.x')"
182+
"Target version to match (supports exact versions like '18.0.0' or X-Range patterns like '5.x', '5.2.x')",
199183
),
200184
},
201185
async ({ library, targetVersion }) => {
@@ -214,10 +198,10 @@ ${formattedResults.join("")}`
214198
return createError(
215199
`Failed to find version: ${
216200
error instanceof Error ? error.message : String(error)
217-
}`
201+
}`,
218202
);
219203
}
220-
}
204+
},
221205
);
222206

223207
server.prompt(
@@ -240,7 +224,7 @@ ${formattedResults.join("")}`
240224
},
241225
],
242226
};
243-
}
227+
},
244228
);
245229

246230
server.resource(
@@ -258,7 +242,7 @@ ${formattedResults.join("")}`
258242
text: lib.name,
259243
})),
260244
};
261-
}
245+
},
262246
);
263247

264248
server.resource(
@@ -283,7 +267,7 @@ ${formattedResults.join("")}`
283267
text: v.version,
284268
})),
285269
};
286-
}
270+
},
287271
);
288272

289273
// Start server
@@ -299,10 +283,7 @@ ${formattedResults.join("")}`
299283
});
300284
} catch (error) {
301285
await storeService.shutdown();
302-
console.error(
303-
"Error:",
304-
error instanceof Error ? error.message : String(error)
305-
);
286+
console.error("Error:", error instanceof Error ? error.message : String(error));
306287
process.exit(1);
307288
}
308289
}

src/scraper/ScraperRegistry.test.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
1-
import { describe, it, expect } from "vitest";
2-
import { ScraperRegistry } from "./ScraperRegistry";
1+
import { describe, expect, it } from "vitest";
32
import { ScraperError } from "../utils/errors";
4-
import { LocalFileStrategy } from "./strategies/LocalFileStrategy";
3+
import { ScraperRegistry } from "./ScraperRegistry";
54
import { GitHubScraperStrategy } from "./strategies/GitHubScraperStrategy";
5+
import { LocalFileStrategy } from "./strategies/LocalFileStrategy";
66
import { NpmScraperStrategy } from "./strategies/NpmScraperStrategy";
77
import { PyPiScraperStrategy } from "./strategies/PyPiScraperStrategy";
88

99
describe("ScraperRegistry", () => {
1010
it("should throw error for unknown URLs", () => {
1111
const registry = new ScraperRegistry();
12+
expect(() => registry.getStrategy("invalid://example.com")).toThrow(ScraperError);
1213
expect(() => registry.getStrategy("invalid://example.com")).toThrow(
13-
ScraperError
14-
);
15-
expect(() => registry.getStrategy("invalid://example.com")).toThrow(
16-
"No strategy found for URL"
14+
"No strategy found for URL",
1715
);
1816
});
1917

src/scraper/ScraperRegistry.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1+
import { ScraperError } from "../utils/errors";
12
import { validateUrl } from "../utils/url";
2-
import { WebScraperStrategy } from "./strategies/WebScraperStrategy";
33
import { GitHubScraperStrategy } from "./strategies/GitHubScraperStrategy";
44
import { LocalFileStrategy } from "./strategies/LocalFileStrategy";
55
import { NpmScraperStrategy } from "./strategies/NpmScraperStrategy";
66
import { PyPiScraperStrategy } from "./strategies/PyPiScraperStrategy";
7+
import { WebScraperStrategy } from "./strategies/WebScraperStrategy";
78
import type { ScraperStrategy } from "./types";
8-
import { ScraperError } from "../utils/errors";
99

1010
export class ScraperRegistry {
1111
private strategies: ScraperStrategy[];

src/scraper/ScraperService.test.ts

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { describe, it, expect, vi, type Mock } from "vitest";
1+
import { type Mock, describe, expect, it, vi } from "vitest";
22
import type { ProgressCallback } from "../types";
33
import { ScraperError } from "../utils/errors";
4+
import type { ScraperRegistry } from "./ScraperRegistry";
45
import { ScraperService } from "./ScraperService";
56
import type { ScraperOptions, ScraperProgress, ScraperStrategy } from "./types";
6-
import type { ScraperRegistry } from "./ScraperRegistry";
77

88
describe("ScraperService", () => {
99
// Mock registry
@@ -17,9 +17,7 @@ describe("ScraperService", () => {
1717
};
1818

1919
it("should use registry to get correct strategy", async () => {
20-
const service = new ScraperService(
21-
mockRegistry as unknown as ScraperRegistry
22-
);
20+
const service = new ScraperService(mockRegistry as unknown as ScraperRegistry);
2321
const options: ScraperOptions = {
2422
url: "https://example.com",
2523
library: "test",
@@ -37,9 +35,7 @@ describe("ScraperService", () => {
3735
});
3836

3937
it("should pass progress callback to strategy", async () => {
40-
const service = new ScraperService(
41-
mockRegistry as unknown as ScraperRegistry
42-
);
38+
const service = new ScraperService(mockRegistry as unknown as ScraperRegistry);
4339
const options: ScraperOptions = {
4440
url: "https://example.com",
4541
library: "test",
@@ -56,9 +52,7 @@ describe("ScraperService", () => {
5652
});
5753

5854
it("should handle file:// URLs", async () => {
59-
const service = new ScraperService(
60-
mockRegistry as unknown as ScraperRegistry
61-
);
55+
const service = new ScraperService(mockRegistry as unknown as ScraperRegistry);
6256
const options: ScraperOptions = {
6357
url: "file:///path/to/file.md",
6458
library: "test",
@@ -76,9 +70,7 @@ describe("ScraperService", () => {
7670
});
7771

7872
it("should throw error if no strategy found", async () => {
79-
const service = new ScraperService(
80-
mockRegistry as unknown as ScraperRegistry
81-
);
73+
const service = new ScraperService(mockRegistry as unknown as ScraperRegistry);
8274
const options: ScraperOptions = {
8375
url: "unknown://example.com",
8476
library: "test",
@@ -90,18 +82,14 @@ describe("ScraperService", () => {
9082

9183
mockRegistry.getStrategy.mockReturnValue(null);
9284

85+
await expect(service.scrape(options, progressCallback)).rejects.toThrow(ScraperError);
9386
await expect(service.scrape(options, progressCallback)).rejects.toThrow(
94-
ScraperError
95-
);
96-
await expect(service.scrape(options, progressCallback)).rejects.toThrow(
97-
"No scraper strategy found for URL: unknown://example.com"
87+
"No scraper strategy found for URL: unknown://example.com",
9888
);
9989
});
10090

10191
it("should propagate errors from strategy", async () => {
102-
const service = new ScraperService(
103-
mockRegistry as unknown as ScraperRegistry
104-
);
92+
const service = new ScraperService(mockRegistry as unknown as ScraperRegistry);
10593
const options: ScraperOptions = {
10694
url: "https://example.com",
10795
library: "test",
@@ -115,7 +103,7 @@ describe("ScraperService", () => {
115103
mockStrategy.scrape.mockRejectedValue(new Error("Strategy error"));
116104

117105
await expect(service.scrape(options, progressCallback)).rejects.toThrow(
118-
"Strategy error"
106+
"Strategy error",
119107
);
120108
});
121109
});

0 commit comments

Comments
 (0)