mcp-docs-scraper 0.1.0

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 (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +357 -0
  3. package/dist/index.d.ts +3 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +20 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/server.d.ts +6 -0
  8. package/dist/server.d.ts.map +1 -0
  9. package/dist/server.js +231 -0
  10. package/dist/server.js.map +1 -0
  11. package/dist/services/cache-manager.d.ts +100 -0
  12. package/dist/services/cache-manager.d.ts.map +1 -0
  13. package/dist/services/cache-manager.js +212 -0
  14. package/dist/services/cache-manager.js.map +1 -0
  15. package/dist/services/content-cleaner.d.ts +48 -0
  16. package/dist/services/content-cleaner.d.ts.map +1 -0
  17. package/dist/services/content-cleaner.js +295 -0
  18. package/dist/services/content-cleaner.js.map +1 -0
  19. package/dist/services/github-detector.d.ts +49 -0
  20. package/dist/services/github-detector.d.ts.map +1 -0
  21. package/dist/services/github-detector.js +276 -0
  22. package/dist/services/github-detector.js.map +1 -0
  23. package/dist/services/github-fetcher.d.ts +94 -0
  24. package/dist/services/github-fetcher.d.ts.map +1 -0
  25. package/dist/services/github-fetcher.js +393 -0
  26. package/dist/services/github-fetcher.js.map +1 -0
  27. package/dist/services/search-index.d.ts +106 -0
  28. package/dist/services/search-index.d.ts.map +1 -0
  29. package/dist/services/search-index.js +210 -0
  30. package/dist/services/search-index.js.map +1 -0
  31. package/dist/services/web-scraper.d.ts +88 -0
  32. package/dist/services/web-scraper.d.ts.map +1 -0
  33. package/dist/services/web-scraper.js +244 -0
  34. package/dist/services/web-scraper.js.map +1 -0
  35. package/dist/tools/clear-cache.d.ts +24 -0
  36. package/dist/tools/clear-cache.d.ts.map +1 -0
  37. package/dist/tools/clear-cache.js +29 -0
  38. package/dist/tools/clear-cache.js.map +1 -0
  39. package/dist/tools/detect-github.d.ts +21 -0
  40. package/dist/tools/detect-github.d.ts.map +1 -0
  41. package/dist/tools/detect-github.js +18 -0
  42. package/dist/tools/detect-github.js.map +1 -0
  43. package/dist/tools/get-content.d.ts +43 -0
  44. package/dist/tools/get-content.d.ts.map +1 -0
  45. package/dist/tools/get-content.js +84 -0
  46. package/dist/tools/get-content.js.map +1 -0
  47. package/dist/tools/get-tree.d.ts +31 -0
  48. package/dist/tools/get-tree.d.ts.map +1 -0
  49. package/dist/tools/get-tree.js +102 -0
  50. package/dist/tools/get-tree.js.map +1 -0
  51. package/dist/tools/index-docs.d.ts +63 -0
  52. package/dist/tools/index-docs.d.ts.map +1 -0
  53. package/dist/tools/index-docs.js +371 -0
  54. package/dist/tools/index-docs.js.map +1 -0
  55. package/dist/tools/index.d.ts +11 -0
  56. package/dist/tools/index.d.ts.map +1 -0
  57. package/dist/tools/index.js +11 -0
  58. package/dist/tools/index.js.map +1 -0
  59. package/dist/tools/list-cached.d.ts +19 -0
  60. package/dist/tools/list-cached.d.ts.map +1 -0
  61. package/dist/tools/list-cached.js +20 -0
  62. package/dist/tools/list-cached.js.map +1 -0
  63. package/dist/tools/search-docs.d.ts +31 -0
  64. package/dist/tools/search-docs.d.ts.map +1 -0
  65. package/dist/tools/search-docs.js +64 -0
  66. package/dist/tools/search-docs.js.map +1 -0
  67. package/dist/types/cache.d.ts +53 -0
  68. package/dist/types/cache.d.ts.map +1 -0
  69. package/dist/types/cache.js +2 -0
  70. package/dist/types/cache.js.map +1 -0
  71. package/dist/types/errors.d.ts +102 -0
  72. package/dist/types/errors.d.ts.map +1 -0
  73. package/dist/types/errors.js +216 -0
  74. package/dist/types/errors.js.map +1 -0
  75. package/dist/types/index.d.ts +6 -0
  76. package/dist/types/index.d.ts.map +1 -0
  77. package/dist/types/index.js +5 -0
  78. package/dist/types/index.js.map +1 -0
  79. package/dist/utils/fs.d.ts +45 -0
  80. package/dist/utils/fs.d.ts.map +1 -0
  81. package/dist/utils/fs.js +113 -0
  82. package/dist/utils/fs.js.map +1 -0
  83. package/dist/utils/rate-limit.d.ts +55 -0
  84. package/dist/utils/rate-limit.d.ts.map +1 -0
  85. package/dist/utils/rate-limit.js +89 -0
  86. package/dist/utils/rate-limit.js.map +1 -0
  87. package/dist/utils/url.d.ts +69 -0
  88. package/dist/utils/url.d.ts.map +1 -0
  89. package/dist/utils/url.js +251 -0
  90. package/dist/utils/url.js.map +1 -0
  91. package/package.json +58 -0
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Custom error types for MCP Docs Scraper.
3
+ *
4
+ * All errors extend DocsError for consistent handling.
5
+ */
6
+ /**
7
+ * Error codes for categorizing errors.
8
+ */
9
+ export type DocsErrorCode = "INVALID_URL" | "GITHUB_RATE_LIMIT" | "GITHUB_NOT_FOUND" | "GITHUB_ACCESS_DENIED" | "CACHE_NOT_FOUND" | "SCRAPING_BLOCKED" | "NO_CONTENT" | "NETWORK_ERROR" | "PARSE_ERROR" | "VALIDATION_ERROR" | "UNKNOWN_ERROR";
10
+ /**
11
+ * Base error class for all documentation-related errors.
12
+ * Provides structured error information for agents.
13
+ */
14
+ export declare class DocsError extends Error {
15
+ /** Error code for categorization */
16
+ readonly code: DocsErrorCode;
17
+ /** User-friendly message */
18
+ readonly userMessage: string;
19
+ /** Recovery suggestions */
20
+ readonly suggestions: string[];
21
+ /** Additional context */
22
+ readonly context?: Record<string, unknown>;
23
+ constructor(code: DocsErrorCode, message: string, options?: {
24
+ userMessage?: string;
25
+ suggestions?: string[];
26
+ context?: Record<string, unknown>;
27
+ cause?: Error;
28
+ });
29
+ /**
30
+ * Converts the error to a structured object for MCP responses.
31
+ */
32
+ toJSON(): Record<string, unknown>;
33
+ }
34
+ /**
35
+ * Error for invalid URLs.
36
+ */
37
+ export declare class InvalidUrlError extends DocsError {
38
+ constructor(url: string, reason?: string);
39
+ }
40
+ /**
41
+ * Error for GitHub rate limit exceeded.
42
+ */
43
+ export declare class GitHubRateLimitError extends DocsError {
44
+ constructor(resetTime?: Date);
45
+ }
46
+ /**
47
+ * Error for GitHub repository not found.
48
+ */
49
+ export declare class GitHubNotFoundError extends DocsError {
50
+ constructor(repo: string);
51
+ }
52
+ /**
53
+ * Error for GitHub access denied (private repo).
54
+ */
55
+ export declare class GitHubAccessDeniedError extends DocsError {
56
+ constructor(repo: string);
57
+ }
58
+ /**
59
+ * Error for cache entry not found.
60
+ */
61
+ export declare class CacheNotFoundError extends DocsError {
62
+ constructor(docsId: string);
63
+ }
64
+ /**
65
+ * Error for scraping blocked.
66
+ */
67
+ export declare class ScrapingBlockedError extends DocsError {
68
+ constructor(url: string, reason?: string);
69
+ }
70
+ /**
71
+ * Error for no content found.
72
+ */
73
+ export declare class NoContentError extends DocsError {
74
+ constructor(url: string);
75
+ }
76
+ /**
77
+ * Error for network failures.
78
+ */
79
+ export declare class NetworkError extends DocsError {
80
+ constructor(url: string, cause?: Error);
81
+ }
82
+ /**
83
+ * Error for validation failures.
84
+ */
85
+ export declare class ValidationError extends DocsError {
86
+ constructor(message: string, field?: string);
87
+ }
88
+ /**
89
+ * Wraps an unknown error in a DocsError.
90
+ */
91
+ export declare function wrapError(error: unknown, context?: string): DocsError;
92
+ /**
93
+ * Creates a structured error response for MCP tools.
94
+ */
95
+ export declare function createErrorResponse(error: unknown): {
96
+ content: Array<{
97
+ type: "text";
98
+ text: string;
99
+ }>;
100
+ isError: true;
101
+ };
102
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,MAAM,aAAa,GACrB,aAAa,GACb,mBAAmB,GACnB,kBAAkB,GAClB,sBAAsB,GACtB,iBAAiB,GACjB,kBAAkB,GAClB,YAAY,GACZ,eAAe,GACf,aAAa,GACb,kBAAkB,GAClB,eAAe,CAAC;AAEpB;;;GAGG;AACH,qBAAa,SAAU,SAAQ,KAAK;IAClC,oCAAoC;IACpC,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,4BAA4B;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2BAA2B;IAC3B,QAAQ,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC;IAC/B,yBAAyB;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGzC,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QACP,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAClC,KAAK,CAAC,EAAE,KAAK,CAAC;KACV;IAUR;;OAEG;IACH,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CASlC;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAS;gBAChC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAWzC;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;gBACrC,SAAS,CAAC,EAAE,IAAI;CAiB7B;AAED;;GAEG;AACH,qBAAa,mBAAoB,SAAQ,SAAS;gBACpC,IAAI,EAAE,MAAM;CAWzB;AAED;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,SAAS;gBACxC,IAAI,EAAE,MAAM;CAWzB;AAED;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,SAAS;gBACnC,MAAM,EAAE,MAAM;CAW3B;AAED;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;gBACrC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAWzC;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,SAAS;gBAC/B,GAAG,EAAE,MAAM;CAWxB;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,SAAS;gBAC7B,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAYvC;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,SAAS;gBAChC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;CAO5C;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAarE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG;IACnD,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,EAAE,IAAI,CAAC;CACf,CAYA"}
@@ -0,0 +1,216 @@
1
+ /**
2
+ * Custom error types for MCP Docs Scraper.
3
+ *
4
+ * All errors extend DocsError for consistent handling.
5
+ */
6
+ /**
7
+ * Base error class for all documentation-related errors.
8
+ * Provides structured error information for agents.
9
+ */
10
+ export class DocsError extends Error {
11
+ /** Error code for categorization */
12
+ code;
13
+ /** User-friendly message */
14
+ userMessage;
15
+ /** Recovery suggestions */
16
+ suggestions;
17
+ /** Additional context */
18
+ context;
19
+ constructor(code, message, options = {}) {
20
+ super(message, { cause: options.cause });
21
+ this.name = "DocsError";
22
+ this.code = code;
23
+ this.userMessage = options.userMessage || message;
24
+ this.suggestions = options.suggestions || [];
25
+ this.context = options.context;
26
+ }
27
+ /**
28
+ * Converts the error to a structured object for MCP responses.
29
+ */
30
+ toJSON() {
31
+ return {
32
+ error: true,
33
+ code: this.code,
34
+ message: this.userMessage,
35
+ suggestions: this.suggestions.length > 0 ? this.suggestions : undefined,
36
+ context: this.context,
37
+ };
38
+ }
39
+ }
40
+ /**
41
+ * Error for invalid URLs.
42
+ */
43
+ export class InvalidUrlError extends DocsError {
44
+ constructor(url, reason) {
45
+ super("INVALID_URL", `Invalid URL: ${url}${reason ? ` - ${reason}` : ""}`, {
46
+ userMessage: "Could not access URL. Check the URL is correct and accessible.",
47
+ suggestions: [
48
+ "Verify the URL is spelled correctly",
49
+ "Ensure the URL includes the protocol (https://)",
50
+ "Check if the website is accessible in a browser",
51
+ ],
52
+ context: { url, reason },
53
+ });
54
+ }
55
+ }
56
+ /**
57
+ * Error for GitHub rate limit exceeded.
58
+ */
59
+ export class GitHubRateLimitError extends DocsError {
60
+ constructor(resetTime) {
61
+ const resetIn = resetTime
62
+ ? Math.ceil((resetTime.getTime() - Date.now()) / 60000)
63
+ : undefined;
64
+ super("GITHUB_RATE_LIMIT", "GitHub API rate limit exceeded", {
65
+ userMessage: resetIn
66
+ ? `GitHub API rate limit reached. Try again in ${resetIn} minutes or use scraping fallback.`
67
+ : "GitHub API rate limit reached. Try again later or use scraping fallback.",
68
+ suggestions: [
69
+ 'Use type: "scrape" to fetch via web scraping instead',
70
+ "Set GITHUB_TOKEN environment variable for higher rate limits (5000/hour)",
71
+ "Wait for the rate limit to reset",
72
+ ],
73
+ context: { resetTime: resetTime?.toISOString(), resetInMinutes: resetIn },
74
+ });
75
+ }
76
+ }
77
+ /**
78
+ * Error for GitHub repository not found.
79
+ */
80
+ export class GitHubNotFoundError extends DocsError {
81
+ constructor(repo) {
82
+ super("GITHUB_NOT_FOUND", `GitHub repository not found: ${repo}`, {
83
+ userMessage: `Repository "${repo}" not found on GitHub.`,
84
+ suggestions: [
85
+ "Check if the repository name is spelled correctly",
86
+ "Verify the repository exists and is public",
87
+ "Use the full URL format: https://github.com/owner/repo",
88
+ ],
89
+ context: { repo },
90
+ });
91
+ }
92
+ }
93
+ /**
94
+ * Error for GitHub access denied (private repo).
95
+ */
96
+ export class GitHubAccessDeniedError extends DocsError {
97
+ constructor(repo) {
98
+ super("GITHUB_ACCESS_DENIED", `Access denied to repository: ${repo}`, {
99
+ userMessage: `Cannot access repository "${repo}". It may be private or restricted.`,
100
+ suggestions: [
101
+ "Ensure the repository is public",
102
+ "Set GITHUB_TOKEN with appropriate permissions",
103
+ 'Use type: "scrape" if documentation is available on a public website',
104
+ ],
105
+ context: { repo },
106
+ });
107
+ }
108
+ }
109
+ /**
110
+ * Error for cache entry not found.
111
+ */
112
+ export class CacheNotFoundError extends DocsError {
113
+ constructor(docsId) {
114
+ super("CACHE_NOT_FOUND", `Documentation not found in cache: ${docsId}`, {
115
+ userMessage: `Documentation "${docsId}" not found in cache.`,
116
+ suggestions: [
117
+ "Run index_docs first to fetch and cache the documentation",
118
+ "Use list_cached_docs to see available cached documentation",
119
+ "Check if the docs_id is spelled correctly",
120
+ ],
121
+ context: { docsId },
122
+ });
123
+ }
124
+ }
125
+ /**
126
+ * Error for scraping blocked.
127
+ */
128
+ export class ScrapingBlockedError extends DocsError {
129
+ constructor(url, reason) {
130
+ super("SCRAPING_BLOCKED", `Scraping blocked for ${url}`, {
131
+ userMessage: "Website blocked automated access.",
132
+ suggestions: [
133
+ "Try using a GitHub repository URL if available",
134
+ "Use detect_github_repo to find the source repository",
135
+ "The website may require authentication or block bots",
136
+ ],
137
+ context: { url, reason },
138
+ });
139
+ }
140
+ }
141
+ /**
142
+ * Error for no content found.
143
+ */
144
+ export class NoContentError extends DocsError {
145
+ constructor(url) {
146
+ super("NO_CONTENT", `No documentation content found at ${url}`, {
147
+ userMessage: "No documentation content found at this URL.",
148
+ suggestions: [
149
+ "Try a different starting URL (e.g., /docs or /documentation)",
150
+ "Increase the crawl depth if content is nested",
151
+ "Check if the URL returns actual documentation content",
152
+ ],
153
+ context: { url },
154
+ });
155
+ }
156
+ }
157
+ /**
158
+ * Error for network failures.
159
+ */
160
+ export class NetworkError extends DocsError {
161
+ constructor(url, cause) {
162
+ super("NETWORK_ERROR", `Network error accessing ${url}`, {
163
+ userMessage: "Could not connect to the server. Check your network connection.",
164
+ suggestions: [
165
+ "Verify your internet connection",
166
+ "Check if the website is online",
167
+ "Try again in a few moments",
168
+ ],
169
+ context: { url },
170
+ cause,
171
+ });
172
+ }
173
+ }
174
+ /**
175
+ * Error for validation failures.
176
+ */
177
+ export class ValidationError extends DocsError {
178
+ constructor(message, field) {
179
+ super("VALIDATION_ERROR", message, {
180
+ userMessage: message,
181
+ suggestions: ["Check the input parameters", "Refer to the tool description for required fields"],
182
+ context: { field },
183
+ });
184
+ }
185
+ }
186
+ /**
187
+ * Wraps an unknown error in a DocsError.
188
+ */
189
+ export function wrapError(error, context) {
190
+ if (error instanceof DocsError) {
191
+ return error;
192
+ }
193
+ const message = error instanceof Error ? error.message : String(error);
194
+ const cause = error instanceof Error ? error : undefined;
195
+ return new DocsError("UNKNOWN_ERROR", context ? `${context}: ${message}` : message, {
196
+ userMessage: "An unexpected error occurred.",
197
+ suggestions: ["Try the operation again", "Check the input parameters"],
198
+ cause,
199
+ });
200
+ }
201
+ /**
202
+ * Creates a structured error response for MCP tools.
203
+ */
204
+ export function createErrorResponse(error) {
205
+ const docsError = error instanceof DocsError ? error : wrapError(error);
206
+ return {
207
+ content: [
208
+ {
209
+ type: "text",
210
+ text: JSON.stringify(docsError.toJSON(), null, 2),
211
+ },
212
+ ],
213
+ isError: true,
214
+ };
215
+ }
216
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/types/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Shared types - re-exports from domain-specific type files.
3
+ */
4
+ export type { DocsTreeNode, CacheMeta, CacheEntrySummary, } from "./cache.js";
5
+ export { DocsError, InvalidUrlError, GitHubRateLimitError, GitHubNotFoundError, GitHubAccessDeniedError, CacheNotFoundError, ScrapingBlockedError, NoContentError, NetworkError, ValidationError, wrapError, createErrorResponse, type DocsErrorCode, } from "./errors.js";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY,EACV,YAAY,EACZ,SAAS,EACT,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,SAAS,EACT,mBAAmB,EACnB,KAAK,aAAa,GACnB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared types - re-exports from domain-specific type files.
3
+ */
4
+ export { DocsError, InvalidUrlError, GitHubRateLimitError, GitHubNotFoundError, GitHubAccessDeniedError, CacheNotFoundError, ScrapingBlockedError, NoContentError, NetworkError, ValidationError, wrapError, createErrorResponse, } from "./errors.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,EACL,SAAS,EACT,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACvB,kBAAkB,EAClB,oBAAoB,EACpB,cAAc,EACd,YAAY,EACZ,eAAe,EACf,SAAS,EACT,mBAAmB,GAEpB,MAAM,aAAa,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Default cache directory location.
3
+ */
4
+ export declare const CACHE_DIR: string;
5
+ /**
6
+ * Ensures a directory exists, creating it and parents if needed.
7
+ */
8
+ export declare function ensureDir(dirPath: string): Promise<void>;
9
+ /**
10
+ * Ensures parent directory exists before writing a file.
11
+ */
12
+ export declare function ensureParentDir(filePath: string): Promise<void>;
13
+ /**
14
+ * Reads a JSON file and parses it.
15
+ * Returns null if file doesn't exist.
16
+ */
17
+ export declare function readJson<T>(filePath: string): Promise<T | null>;
18
+ /**
19
+ * Writes an object as JSON to a file, creating parent dirs if needed.
20
+ */
21
+ export declare function writeJson<T>(filePath: string, data: T): Promise<void>;
22
+ /**
23
+ * Reads a text file.
24
+ * Returns null if file doesn't exist.
25
+ */
26
+ export declare function readText(filePath: string): Promise<string | null>;
27
+ /**
28
+ * Writes text to a file, creating parent dirs if needed.
29
+ */
30
+ export declare function writeText(filePath: string, content: string): Promise<void>;
31
+ /**
32
+ * Removes a file or directory recursively.
33
+ * Does nothing if path doesn't exist.
34
+ */
35
+ export declare function remove(targetPath: string): Promise<void>;
36
+ /**
37
+ * Lists immediate subdirectories in a directory.
38
+ * Returns empty array if directory doesn't exist.
39
+ */
40
+ export declare function listDirectories(dirPath: string): Promise<string[]>;
41
+ /**
42
+ * Checks if a path exists.
43
+ */
44
+ export declare function exists(targetPath: string): Promise<boolean>;
45
+ //# sourceMappingURL=fs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,eAAO,MAAM,SAAS,QAAqC,CAAC;AAE5D;;GAEG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE9D;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAErE;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAUrE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAG3E;AAED;;;GAGG;AACH,wBAAsB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CASvE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGhF;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS9D;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAYxE;AAED;;GAEG;AACH,wBAAsB,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAUjE"}
@@ -0,0 +1,113 @@
1
+ import { mkdir, readFile, writeFile, rm, readdir, stat } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ /**
5
+ * Default cache directory location.
6
+ */
7
+ export const CACHE_DIR = join(homedir(), ".mcp-docs-cache");
8
+ /**
9
+ * Ensures a directory exists, creating it and parents if needed.
10
+ */
11
+ export async function ensureDir(dirPath) {
12
+ await mkdir(dirPath, { recursive: true });
13
+ }
14
+ /**
15
+ * Ensures parent directory exists before writing a file.
16
+ */
17
+ export async function ensureParentDir(filePath) {
18
+ await ensureDir(dirname(filePath));
19
+ }
20
+ /**
21
+ * Reads a JSON file and parses it.
22
+ * Returns null if file doesn't exist.
23
+ */
24
+ export async function readJson(filePath) {
25
+ try {
26
+ const content = await readFile(filePath, "utf-8");
27
+ return JSON.parse(content);
28
+ }
29
+ catch (error) {
30
+ if (error.code === "ENOENT") {
31
+ return null;
32
+ }
33
+ throw error;
34
+ }
35
+ }
36
+ /**
37
+ * Writes an object as JSON to a file, creating parent dirs if needed.
38
+ */
39
+ export async function writeJson(filePath, data) {
40
+ await ensureParentDir(filePath);
41
+ await writeFile(filePath, JSON.stringify(data, null, 2), "utf-8");
42
+ }
43
+ /**
44
+ * Reads a text file.
45
+ * Returns null if file doesn't exist.
46
+ */
47
+ export async function readText(filePath) {
48
+ try {
49
+ return await readFile(filePath, "utf-8");
50
+ }
51
+ catch (error) {
52
+ if (error.code === "ENOENT") {
53
+ return null;
54
+ }
55
+ throw error;
56
+ }
57
+ }
58
+ /**
59
+ * Writes text to a file, creating parent dirs if needed.
60
+ */
61
+ export async function writeText(filePath, content) {
62
+ await ensureParentDir(filePath);
63
+ await writeFile(filePath, content, "utf-8");
64
+ }
65
+ /**
66
+ * Removes a file or directory recursively.
67
+ * Does nothing if path doesn't exist.
68
+ */
69
+ export async function remove(targetPath) {
70
+ try {
71
+ await rm(targetPath, { recursive: true, force: true });
72
+ }
73
+ catch (error) {
74
+ // Ignore if already doesn't exist
75
+ if (error.code !== "ENOENT") {
76
+ throw error;
77
+ }
78
+ }
79
+ }
80
+ /**
81
+ * Lists immediate subdirectories in a directory.
82
+ * Returns empty array if directory doesn't exist.
83
+ */
84
+ export async function listDirectories(dirPath) {
85
+ try {
86
+ const entries = await readdir(dirPath, { withFileTypes: true });
87
+ return entries
88
+ .filter((entry) => entry.isDirectory())
89
+ .map((entry) => entry.name);
90
+ }
91
+ catch (error) {
92
+ if (error.code === "ENOENT") {
93
+ return [];
94
+ }
95
+ throw error;
96
+ }
97
+ }
98
+ /**
99
+ * Checks if a path exists.
100
+ */
101
+ export async function exists(targetPath) {
102
+ try {
103
+ await stat(targetPath);
104
+ return true;
105
+ }
106
+ catch (error) {
107
+ if (error.code === "ENOENT") {
108
+ return false;
109
+ }
110
+ throw error;
111
+ }
112
+ }
113
+ //# sourceMappingURL=fs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/utils/fs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Rate limit tracker for GitHub API.
3
+ */
4
+ export interface RateLimitInfo {
5
+ /** Maximum requests allowed per hour */
6
+ limit: number;
7
+ /** Remaining requests in current window */
8
+ remaining: number;
9
+ /** Unix timestamp when rate limit resets */
10
+ reset: number;
11
+ /** When this info was last updated */
12
+ updatedAt: Date;
13
+ }
14
+ /**
15
+ * Tracks GitHub API rate limits.
16
+ */
17
+ export declare class RateLimitTracker {
18
+ private info;
19
+ /**
20
+ * Updates rate limit info from response headers.
21
+ */
22
+ updateFromHeaders(headers: Headers): void;
23
+ /**
24
+ * Gets the current rate limit info.
25
+ */
26
+ getInfo(): RateLimitInfo | null;
27
+ /**
28
+ * Checks if we're running low on remaining requests.
29
+ * @param threshold Number of remaining requests to consider "low"
30
+ */
31
+ isLow(threshold?: number): boolean;
32
+ /**
33
+ * Checks if rate limit is exhausted.
34
+ */
35
+ isExhausted(): boolean;
36
+ /**
37
+ * Gets time until rate limit resets (in milliseconds).
38
+ * Returns 0 if reset time has passed or no info available.
39
+ */
40
+ getTimeUntilReset(): number;
41
+ /**
42
+ * Gets a human-readable status message.
43
+ */
44
+ getStatusMessage(): string;
45
+ /**
46
+ * Gets the reset time as a Date object.
47
+ * Returns undefined if no rate limit info is available.
48
+ */
49
+ getResetTime(): Date | undefined;
50
+ }
51
+ /**
52
+ * Default rate limit tracker instance for GitHub API.
53
+ */
54
+ export declare const githubRateLimit: RateLimitTracker;
55
+ //# sourceMappingURL=rate-limit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/utils/rate-limit.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,aAAa;IAC5B,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,SAAS,EAAE,IAAI,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,IAAI,CAA8B;IAE1C;;OAEG;IACH,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAezC;;OAEG;IACH,OAAO,IAAI,aAAa,GAAG,IAAI;IAI/B;;;OAGG;IACH,KAAK,CAAC,SAAS,GAAE,MAAU,GAAG,OAAO;IAKrC;;OAEG;IACH,WAAW,IAAI,OAAO;IAKtB;;;OAGG;IACH,iBAAiB,IAAI,MAAM;IAO3B;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAkB1B;;;OAGG;IACH,YAAY,IAAI,IAAI,GAAG,SAAS;CAIjC;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,kBAAyB,CAAC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Rate limit tracker for GitHub API.
3
+ */
4
+ /**
5
+ * Tracks GitHub API rate limits.
6
+ */
7
+ export class RateLimitTracker {
8
+ info = null;
9
+ /**
10
+ * Updates rate limit info from response headers.
11
+ */
12
+ updateFromHeaders(headers) {
13
+ const limit = headers.get("X-RateLimit-Limit");
14
+ const remaining = headers.get("X-RateLimit-Remaining");
15
+ const reset = headers.get("X-RateLimit-Reset");
16
+ if (limit && remaining && reset) {
17
+ this.info = {
18
+ limit: parseInt(limit, 10),
19
+ remaining: parseInt(remaining, 10),
20
+ reset: parseInt(reset, 10),
21
+ updatedAt: new Date(),
22
+ };
23
+ }
24
+ }
25
+ /**
26
+ * Gets the current rate limit info.
27
+ */
28
+ getInfo() {
29
+ return this.info;
30
+ }
31
+ /**
32
+ * Checks if we're running low on remaining requests.
33
+ * @param threshold Number of remaining requests to consider "low"
34
+ */
35
+ isLow(threshold = 5) {
36
+ if (!this.info)
37
+ return false;
38
+ return this.info.remaining < threshold;
39
+ }
40
+ /**
41
+ * Checks if rate limit is exhausted.
42
+ */
43
+ isExhausted() {
44
+ if (!this.info)
45
+ return false;
46
+ return this.info.remaining <= 0;
47
+ }
48
+ /**
49
+ * Gets time until rate limit resets (in milliseconds).
50
+ * Returns 0 if reset time has passed or no info available.
51
+ */
52
+ getTimeUntilReset() {
53
+ if (!this.info)
54
+ return 0;
55
+ const resetTime = this.info.reset * 1000; // Convert to ms
56
+ const now = Date.now();
57
+ return Math.max(0, resetTime - now);
58
+ }
59
+ /**
60
+ * Gets a human-readable status message.
61
+ */
62
+ getStatusMessage() {
63
+ if (!this.info) {
64
+ return "Rate limit info not available";
65
+ }
66
+ const minutesUntilReset = Math.ceil(this.getTimeUntilReset() / 60000);
67
+ if (this.isExhausted()) {
68
+ return `Rate limit exhausted. Resets in ${minutesUntilReset} minutes.`;
69
+ }
70
+ if (this.isLow()) {
71
+ return `Rate limit low: ${this.info.remaining}/${this.info.limit} remaining. Resets in ${minutesUntilReset} minutes.`;
72
+ }
73
+ return `Rate limit: ${this.info.remaining}/${this.info.limit} remaining`;
74
+ }
75
+ /**
76
+ * Gets the reset time as a Date object.
77
+ * Returns undefined if no rate limit info is available.
78
+ */
79
+ getResetTime() {
80
+ if (!this.info)
81
+ return undefined;
82
+ return new Date(this.info.reset * 1000);
83
+ }
84
+ }
85
+ /**
86
+ * Default rate limit tracker instance for GitHub API.
87
+ */
88
+ export const githubRateLimit = new RateLimitTracker();
89
+ //# sourceMappingURL=rate-limit.js.map