diff --git a/src/__tests__/__snapshots__/options.defaults.test.ts.snap b/src/__tests__/__snapshots__/options.defaults.test.ts.snap index 3aaade15..d9725955 100644 --- a/src/__tests__/__snapshots__/options.defaults.test.ts.snap +++ b/src/__tests__/__snapshots__/options.defaults.test.ts.snap @@ -82,5 +82,8 @@ exports[`options defaults should return specific properties: defaults 1`] = ` "toolModules": [], "urlRegex": /\\^\\(https\\?:\\)\\\\/\\\\//i, "version": "0.0.0", + "xhrFetch": { + "timeoutMs": 15000, + }, } `; diff --git a/src/options.defaults.ts b/src/options.defaults.ts index 915c7c7f..d41c4734 100644 --- a/src/options.defaults.ts +++ b/src/options.defaults.ts @@ -40,6 +40,7 @@ import { type ToolModule } from './server.toolsUser'; * registered with the server. * @property urlRegex - Regular expression pattern for URL matching. * @property version - Version of the package. + * @property xhrFetch - XHR and Fetch options. */ interface DefaultOptions { contextPath: string; @@ -73,6 +74,7 @@ interface DefaultOptions { toolModules: ToolModule | ToolModule[]; urlRegex: RegExp; version: string; + xhrFetch: XhrFetchOptions; } /** @@ -153,6 +155,9 @@ interface LoggingSession extends LoggingOptions { readonly channelName: string; } +/** + * Base stats options. + */ type StatsOptions = { reportIntervalMs: { health: number; @@ -160,6 +165,9 @@ type StatsOptions = { } }; +/** + * Stats channel names. + */ type StatsChannels = { readonly health: string; readonly session: string; @@ -179,6 +187,17 @@ interface StatsSession extends StatsOptions { channels: StatsChannels } +/** + * XHR and Fetch options. + * + * @interface XhrFetchOptions + * + * @property timeoutMs Timeout for XHR and Fetch requests (ms). + */ +interface XhrFetchOptions { + timeoutMs: number; +} + /** * Base logging options. */ @@ -205,7 +224,7 @@ const HTTP_OPTIONS: HttpOptions = { */ const PLUGIN_HOST_OPTIONS: PluginHostOptions = { loadTimeoutMs: 5000, - invokeTimeoutMs: 10000, + invokeTimeoutMs: 10_000, gracePeriodMs: 2000 }; @@ -250,7 +269,7 @@ const TOOL_MEMO_OPTIONS = { }; /** - * Stats options. + * Default stats options. */ const STATS_OPTIONS: StatsOptions = { reportIntervalMs: { @@ -259,6 +278,13 @@ const STATS_OPTIONS: StatsOptions = { } }; +/** + * Default XHR and Fetch options. + */ +const XHR_FETCH_OPTIONS: XhrFetchOptions = { + timeoutMs: 15_000 +}; + /** * Base logging channel name. Fixed to avoid user override. */ @@ -387,7 +413,8 @@ const DEFAULT_OPTIONS: DefaultOptions = { toolModules: [], separator: DEFAULT_SEPARATOR, urlRegex: URL_REGEX, - version: (process.env.NODE_ENV === 'local' && '0.0.0') || packageJson.version + version: (process.env.NODE_ENV === 'local' && '0.0.0') || packageJson.version, + xhrFetch: XHR_FETCH_OPTIONS }; export { @@ -412,5 +439,6 @@ export { type LoggingOptions, type LoggingSession, type PluginHostOptions, - type StatsSession + type StatsSession, + type XhrFetchOptions }; diff --git a/src/server.getResources.ts b/src/server.getResources.ts index 74cee031..2e0225fd 100644 --- a/src/server.getResources.ts +++ b/src/server.getResources.ts @@ -23,12 +23,12 @@ readLocalFileFunction.memo = memo(readLocalFileFunction, DEFAULT_OPTIONS.resourc * * @note Review expanding fetch to handle more file types like JSON. * - * @param url + * @param url - URL to fetch + * @param options - Options */ -const fetchUrlFunction = async (url: string) => { +const fetchUrlFunction = async (url: string, options = getOptions()) => { const controller = new AbortController(); - const timeoutMs = Number(process.env.DOC_MCP_FETCH_TIMEOUT_MS || 15_000); - const timeout = setTimeout(() => controller.abort(), timeoutMs); + const timeout = setTimeout(() => controller.abort(), options.xhrFetch.timeoutMs); // Allow the process to exit timeout.unref();