70 lines
2.4 KiB
JavaScript
70 lines
2.4 KiB
JavaScript
import { DuckDuckGoProvider } from "./duckduckgo.js";
|
|
import { BingProvider } from "./bing.js";
|
|
import { SearXNGProvider } from "./searxng.js";
|
|
import { BraveProvider } from "./brave.js";
|
|
import { DEFAULT_SEARCH_PROVIDER } from "../constants.js";
|
|
import { attemptProvider } from "./diagnostics.js";
|
|
|
|
const PROVIDERS = ["searxng", "brave", "duckduckgo", "bing"];
|
|
const PROVIDER_TIMEOUT_MS = Number(process.env.SEARCH_PROVIDER_TIMEOUT_MS || "15000");
|
|
const MAX_PROVIDER_ATTEMPTS = Math.max(1, Math.min(Number(process.env.MAX_PROVIDER_ATTEMPTS || "4"), 4));
|
|
|
|
export class ProviderRegistry {
|
|
constructor(providers) {
|
|
this.providers = providers || new Map([
|
|
["duckduckgo", new DuckDuckGoProvider()],
|
|
["bing", new BingProvider()],
|
|
["searxng", new SearXNGProvider()],
|
|
["brave", new BraveProvider()]
|
|
]);
|
|
}
|
|
|
|
get(name) {
|
|
return this.providers.get(name);
|
|
}
|
|
|
|
async searchWithFallback(q, limit, lang, preferredProvider, signal) {
|
|
const defaultProvider = preferredProvider || DEFAULT_SEARCH_PROVIDER;
|
|
const order = [defaultProvider, ...PROVIDERS.filter(name => name !== defaultProvider)].slice(0, MAX_PROVIDER_ATTEMPTS);
|
|
const attempts = [];
|
|
const started = performance.now();
|
|
for (const providerName of order) {
|
|
signal?.throwIfAborted();
|
|
const provider = this.providers.get(providerName);
|
|
if (!provider) continue;
|
|
const attempt = await attemptProvider(provider, q, limit, lang, {
|
|
timeoutMs: PROVIDER_TIMEOUT_MS,
|
|
signal
|
|
});
|
|
attempts.push(attempt.diagnostic);
|
|
if (attempt.items.length) {
|
|
return {
|
|
items: attempt.items,
|
|
providerUsed: providerName,
|
|
fallbackUsed: providerName !== defaultProvider,
|
|
triedProviders: attempts.map(item => item.provider),
|
|
diagnostics: {
|
|
attempts,
|
|
elapsed_ms: Math.round(performance.now() - started),
|
|
exhausted: false
|
|
}
|
|
};
|
|
}
|
|
}
|
|
return {
|
|
items: [],
|
|
providerUsed: defaultProvider,
|
|
fallbackUsed: attempts.length > 1,
|
|
triedProviders: attempts.map(item => item.provider),
|
|
diagnostics: {
|
|
attempts,
|
|
elapsed_ms: Math.round(performance.now() - started),
|
|
exhausted: true
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
export const providerRegistry = new ProviderRegistry();
|
|
export { DuckDuckGoProvider, BingProvider, SearXNGProvider, BraveProvider };
|