@endday/search-mcp 1.0.0 → 1.0.1

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 (85) hide show
  1. package/dist/index.js +4724 -0
  2. package/dist/search-mcp.js +4715 -0
  3. package/package.json +14 -14
  4. package/data/blocklist.generated.js +0 -2
  5. package/envs.js +0 -129
  6. package/index.js +0 -6
  7. package/mcp/search-mcp.js +0 -8
  8. package/src/content/extract.impl.js +0 -228
  9. package/src/content/extract.js +0 -1
  10. package/src/content/fetch.impl.js +0 -400
  11. package/src/content/fetch.js +0 -1
  12. package/src/core/crypto.js +0 -7
  13. package/src/core/errors.impl.js +0 -52
  14. package/src/core/errors.js +0 -1
  15. package/src/core/html.impl.js +0 -69
  16. package/src/core/html.js +0 -1
  17. package/src/mcp/config.js +0 -75
  18. package/src/mcp/format.js +0 -44
  19. package/src/mcp/index.js +0 -10
  20. package/src/mcp/local/content.js +0 -26
  21. package/src/mcp/local/search.js +0 -233
  22. package/src/mcp/schemas.js +0 -132
  23. package/src/mcp/server.js +0 -97
  24. package/src/mcp/tools/content.js +0 -31
  25. package/src/mcp/tools/jinaContent.js +0 -38
  26. package/src/mcp/tools/newsSearch.js +0 -22
  27. package/src/mcp/tools/webSearch.js +0 -57
  28. package/src/platform/auth.impl.js +0 -166
  29. package/src/platform/auth.js +0 -1
  30. package/src/platform/cache.impl.js +0 -166
  31. package/src/platform/cache.js +0 -1
  32. package/src/platform/health.impl.js +0 -133
  33. package/src/platform/health.js +0 -1
  34. package/src/platform/http.impl.js +0 -108
  35. package/src/platform/http.js +0 -1
  36. package/src/platform/logger.impl.js +0 -51
  37. package/src/platform/logger.js +0 -1
  38. package/src/platform/metrics.impl.js +0 -43
  39. package/src/platform/metrics.js +0 -1
  40. package/src/platform/nodeHttpClient.js +0 -104
  41. package/src/platform/rateLimit.impl.js +0 -141
  42. package/src/platform/rateLimit.js +0 -1
  43. package/src/platform/requestContext.impl.js +0 -10
  44. package/src/platform/requestContext.js +0 -1
  45. package/src/platform/session.impl.js +0 -198
  46. package/src/platform/session.js +0 -1
  47. package/src/platform/stateKv.impl.js +0 -18
  48. package/src/platform/stateKv.js +0 -1
  49. package/src/platform/tasks.impl.js +0 -17
  50. package/src/platform/tasks.js +0 -1
  51. package/src/routes/requestParams.impl.js +0 -12
  52. package/src/routes/requestParams.js +0 -1
  53. package/src/search/engineRegistry.impl.js +0 -117
  54. package/src/search/engineRegistry.js +0 -1
  55. package/src/search/engineRequest.impl.js +0 -377
  56. package/src/search/engineRequest.js +0 -1
  57. package/src/search/engineUtils.impl.js +0 -227
  58. package/src/search/engineUtils.js +0 -1
  59. package/src/search/engines/baidu.impl.js +0 -145
  60. package/src/search/engines/baidu.js +0 -2
  61. package/src/search/engines/bing.impl.js +0 -509
  62. package/src/search/engines/bing.js +0 -2
  63. package/src/search/engines/brave.impl.js +0 -223
  64. package/src/search/engines/brave.js +0 -2
  65. package/src/search/engines/duckduckgo.impl.js +0 -164
  66. package/src/search/engines/duckduckgo.js +0 -2
  67. package/src/search/engines/mojeek.impl.js +0 -115
  68. package/src/search/engines/mojeek.js +0 -2
  69. package/src/search/engines/qwant.impl.js +0 -188
  70. package/src/search/engines/qwant.js +0 -2
  71. package/src/search/engines/startpage.impl.js +0 -237
  72. package/src/search/engines/startpage.js +0 -2
  73. package/src/search/engines/toutiao.impl.js +0 -265
  74. package/src/search/engines/toutiao.js +0 -2
  75. package/src/search/engines/yahoo.impl.js +0 -379
  76. package/src/search/engines/yahoo.js +0 -2
  77. package/src/search/gateway.impl.js +0 -423
  78. package/src/search/gateway.js +0 -1
  79. package/src/search/ranking.impl.js +0 -381
  80. package/src/search/ranking.js +0 -1
  81. package/src/search/requestPolicy.impl.js +0 -137
  82. package/src/search/requestPolicy.js +0 -1
  83. package/src/search/upstreamSession.impl.js +0 -148
  84. package/src/search/upstreamSession.js +0 -1
  85. /package/{index.d.ts → dist/index.d.ts} +0 -0
@@ -1,104 +0,0 @@
1
- import { Impit } from "impit/index.js";
2
-
3
- const impitClients = new Map();
4
-
5
- function isNodeRuntime() {
6
- return typeof process !== "undefined" && !!process.versions?.node;
7
- }
8
-
9
- function isPatchedFetch(fetchImpl = globalThis.fetch) {
10
- if (typeof fetchImpl !== "function") {
11
- return false;
12
- }
13
-
14
- return !/\[native code\]/.test(Function.prototype.toString.call(fetchImpl));
15
- }
16
-
17
- function normalizeClientMode(value) {
18
- const mode = String(value || "auto").trim().toLowerCase();
19
- if (mode === "fetch" || mode === "impit") {
20
- return mode;
21
- }
22
- return "auto";
23
- }
24
-
25
- function resolveBrowserProfile(profile) {
26
- const profileId = String(profile?.id || "").toLowerCase();
27
-
28
- if (profileId.startsWith("firefox")) {
29
- return "firefox144";
30
- }
31
-
32
- return "chrome136";
33
- }
34
-
35
- function buildClientKey({ browser, proxyUrl, ignoreTlsErrors }) {
36
- return JSON.stringify({
37
- browser,
38
- proxyUrl: proxyUrl || "",
39
- ignoreTlsErrors: !!ignoreTlsErrors,
40
- });
41
- }
42
-
43
- function getImpitClient({ profile } = {}) {
44
- const browser = resolveBrowserProfile(profile);
45
- const proxyUrl = process.env.SEARCH_MCP_PROXY_URL || "";
46
- const ignoreTlsErrors = ["1", "true", "yes", "on"].includes(
47
- String(process.env.SEARCH_MCP_IGNORE_TLS_ERRORS || "").trim().toLowerCase()
48
- );
49
- const key = buildClientKey({ browser, proxyUrl, ignoreTlsErrors });
50
-
51
- if (!impitClients.has(key)) {
52
- impitClients.set(
53
- key,
54
- new Impit({
55
- browser,
56
- proxyUrl: proxyUrl || undefined,
57
- ignoreTlsErrors,
58
- followRedirects: true,
59
- vanillaFallback: false,
60
- timeout: Number.parseInt(process.env.SEARCH_MCP_UPSTREAM_TIMEOUT_MS || "15000", 10),
61
- })
62
- );
63
- }
64
-
65
- return impitClients.get(key);
66
- }
67
-
68
- function normalizeRequestInit(init = {}) {
69
- const normalized = { ...init };
70
-
71
- if (normalized.headers instanceof Headers) {
72
- normalized.headers = Object.fromEntries(normalized.headers.entries());
73
- }
74
-
75
- delete normalized.referrer;
76
- return normalized;
77
- }
78
-
79
- export async function fetchWithOptionalCurlImpersonate(
80
- url,
81
- init = {},
82
- { profile } = {}
83
- ) {
84
- const clientMode = normalizeClientMode(process.env.SEARCH_MCP_UPSTREAM_CLIENT);
85
- const shouldUseImpit =
86
- clientMode !== "fetch" &&
87
- isNodeRuntime() &&
88
- !isPatchedFetch(globalThis.fetch);
89
-
90
- if (!shouldUseImpit) {
91
- return fetch(url, init);
92
- }
93
-
94
- try {
95
- const client = getImpitClient({ profile });
96
- return await client.fetch(url, normalizeRequestInit(init));
97
- } catch (error) {
98
- if (clientMode === "impit") {
99
- throw error;
100
- }
101
-
102
- return fetch(url, init);
103
- }
104
- }
@@ -1,141 +0,0 @@
1
- import { env } from "../../envs.js";
2
- import { sha256Hex } from "../core/crypto.js";
3
- import { ApiError } from "../core/errors.js";
4
- import { getStateKv } from "./stateKv.js";
5
- import { logWarn } from "./logger.js";
6
-
7
- const RATE_LIMIT_PREFIX = "rate:v2";
8
- const rateLimitStore = new Map();
9
-
10
- export function resetRateLimitState() {
11
- rateLimitStore.clear();
12
- }
13
-
14
- function pruneExpiredEntries(now) {
15
- if (rateLimitStore.size < 1000) {
16
- return;
17
- }
18
-
19
- for (const [key, entry] of rateLimitStore.entries()) {
20
- if (entry.expiresAt <= now) {
21
- rateLimitStore.delete(key);
22
- }
23
- }
24
- }
25
-
26
- export function getRateLimitClientKey(request, token) {
27
- const clientIp =
28
- request.headers.get("cf-connecting-ip") ||
29
- request.headers.get("x-forwarded-for") ||
30
- "anonymous";
31
-
32
- return token ? `token:${token}` : `ip:${clientIp}`;
33
- }
34
-
35
- async function getRateLimitBucketKey(request, token, bucket, bucketPrefix = RATE_LIMIT_PREFIX) {
36
- const clientKey = getRateLimitClientKey(request, token);
37
- const clientHash = await sha256Hex(clientKey);
38
- return `${bucketPrefix}:${bucket}:${clientHash}`;
39
- }
40
-
41
- function createRateLimitError({ maxRequests, windowSeconds, retryAfter }) {
42
- return new ApiError({
43
- status: 429,
44
- code: "RATE_LIMITED",
45
- category: "rate_limit",
46
- message: "Rate limit exceeded",
47
- details: {
48
- limit: maxRequests,
49
- window_seconds: windowSeconds,
50
- retry_after: retryAfter,
51
- },
52
- });
53
- }
54
-
55
- function getRetryAfter(expiresAt, now) {
56
- return Math.max(1, Math.ceil((expiresAt - now) / 1000));
57
- }
58
-
59
- function incrementMemoryBucket(key, expiresAt) {
60
- const record = rateLimitStore.get(key) || { count: 0, expiresAt };
61
- record.count += 1;
62
- rateLimitStore.set(key, record);
63
- return record.count;
64
- }
65
-
66
- async function incrementKvBucket({ kv, key, expiresAt, windowSeconds }) {
67
- const record = (await kv.get(key, "json")) || { count: 0, expiresAt };
68
- const count = Number.parseInt(record.count || "0", 10) + 1;
69
-
70
- await kv.put(
71
- key,
72
- JSON.stringify({
73
- count,
74
- expiresAt,
75
- }),
76
- {
77
- expirationTtl: windowSeconds + 5,
78
- }
79
- );
80
-
81
- return count;
82
- }
83
-
84
- export async function enforceRateLimit(request, token, options = {}) {
85
- const maxRequests = options.maxRequests ?? Number.parseInt(env.RATE_LIMIT_MAX_REQUESTS || "0", 10);
86
- const windowSeconds = options.windowSeconds ?? Number.parseInt(
87
- env.RATE_LIMIT_WINDOW_SECONDS || "60",
88
- 10
89
- );
90
- const bucketPrefix = options.bucketPrefix ?? RATE_LIMIT_PREFIX;
91
-
92
- if (maxRequests <= 0 || windowSeconds <= 0) {
93
- return;
94
- }
95
-
96
- const now = Date.now();
97
- const windowMs = windowSeconds * 1000;
98
- const bucket = Math.floor(now / windowMs);
99
- const expiresAt = (bucket + 1) * windowMs;
100
- const clientKey = await getRateLimitBucketKey(request, token, bucket, bucketPrefix);
101
- const kv = getStateKv();
102
-
103
- if (kv) {
104
- try {
105
- const count = await incrementKvBucket({
106
- kv,
107
- key: clientKey,
108
- expiresAt,
109
- windowSeconds,
110
- });
111
-
112
- if (count > maxRequests) {
113
- throw createRateLimitError({
114
- maxRequests,
115
- windowSeconds,
116
- retryAfter: getRetryAfter(expiresAt, now),
117
- });
118
- }
119
-
120
- return;
121
- } catch (error) {
122
- if (error instanceof ApiError) {
123
- throw error;
124
- }
125
-
126
- logWarn("rate_limit.kv_fallback", {}, error);
127
- }
128
- }
129
-
130
- pruneExpiredEntries(now);
131
-
132
- const count = incrementMemoryBucket(clientKey, expiresAt);
133
-
134
- if (count > maxRequests) {
135
- throw createRateLimitError({
136
- maxRequests,
137
- windowSeconds,
138
- retryAfter: getRetryAfter(expiresAt, now),
139
- });
140
- }
141
- }
@@ -1 +0,0 @@
1
- export * from "./rateLimit.impl.js";
@@ -1,10 +0,0 @@
1
- export function createRuntimeContext(request, executionCtx) {
2
- return {
3
- request,
4
- executionCtx,
5
- metrics: {
6
- counters: [],
7
- timings: [],
8
- },
9
- };
10
- }
@@ -1 +0,0 @@
1
- export * from "./requestContext.impl.js";
@@ -1,198 +0,0 @@
1
- import { getStateKv } from "./stateKv.js";
2
-
3
- const SESSION_PREFIX = "session:v1";
4
- const SESSION_TTL_SECONDS = 86400; // 24 hours
5
- const SESSION_COOKIE_NAME = "search_mcp_sid";
6
-
7
- // In-memory fallback when KV is unavailable
8
- const memorySessions = new Map();
9
- let lastPruneTime = 0;
10
- const PRUNE_INTERVAL_SECONDS = 3600; // Prune every hour
11
-
12
- function nowSeconds() {
13
- return Math.floor(Date.now() / 1000);
14
- }
15
-
16
- function pruneMemorySessions() {
17
- const now = nowSeconds();
18
- if (now - lastPruneTime < PRUNE_INTERVAL_SECONDS) return;
19
- lastPruneTime = now;
20
-
21
- if (memorySessions.size < 100) return;
22
-
23
- for (const [key, entry] of memorySessions.entries()) {
24
- if (entry.expiresAt <= now) {
25
- memorySessions.delete(key);
26
- }
27
- }
28
- }
29
-
30
- function generateSessionId() {
31
- return crypto.randomUUID();
32
- }
33
-
34
- function kvKey(sessionId) {
35
- return `${SESSION_PREFIX}:${sessionId}`;
36
- }
37
-
38
- export function resetSessionState() {
39
- memorySessions.clear();
40
- }
41
-
42
- /**
43
- * Extract session ID from request cookies.
44
- */
45
- export function getSessionIdFromRequest(request) {
46
- const cookieHeader = request.headers.get("cookie") || "";
47
- const match = cookieHeader.match(
48
- new RegExp(`(?:^|;)\\s*${SESSION_COOKIE_NAME}\\s*=\\s*([^;]+)`)
49
- );
50
- return match ? match[1].trim() : null;
51
- }
52
-
53
- /**
54
- * Build Set-Cookie header value for the session.
55
- */
56
- export function buildSessionCookie(sessionId, { secure = true } = {}) {
57
- const parts = [
58
- `${SESSION_COOKIE_NAME}=${sessionId}`,
59
- "Path=/",
60
- `Max-Age=${SESSION_TTL_SECONDS}`,
61
- "HttpOnly",
62
- "SameSite=Lax",
63
- ];
64
- if (secure) {
65
- parts.push("Secure");
66
- }
67
- return parts.join("; ");
68
- }
69
-
70
- /**
71
- * Load session data from KV or memory fallback.
72
- */
73
- async function loadSession(sessionId) {
74
- pruneMemorySessions();
75
-
76
- const kv = getStateKv();
77
-
78
- if (kv) {
79
- try {
80
- const data = await kv.get(kvKey(sessionId), "json");
81
- return data;
82
- } catch (_) {
83
- // Fall through to memory
84
- }
85
- }
86
-
87
- const mem = memorySessions.get(sessionId);
88
- if (!mem) return null;
89
- if (mem.expiresAt <= nowSeconds()) {
90
- memorySessions.delete(sessionId);
91
- return null;
92
- }
93
- return mem.data;
94
- }
95
-
96
- /**
97
- * Save session data to KV or memory fallback.
98
- */
99
- async function saveSession(sessionId, data) {
100
- const kv = getStateKv();
101
-
102
- if (kv) {
103
- try {
104
- await kv.put(kvKey(sessionId), JSON.stringify(data), {
105
- expirationTtl: SESSION_TTL_SECONDS,
106
- });
107
- return;
108
- } catch (_) {
109
- // Fall through to memory
110
- }
111
- }
112
-
113
- memorySessions.set(sessionId, {
114
- data,
115
- expiresAt: nowSeconds() + SESSION_TTL_SECONDS,
116
- });
117
- }
118
-
119
- /**
120
- * Delete session from KV or memory.
121
- */
122
- async function deleteSession(sessionId) {
123
- const kv = getStateKv();
124
-
125
- if (kv) {
126
- try {
127
- await kv.delete(kvKey(sessionId));
128
- return;
129
- } catch (_) {
130
- // Fall through
131
- }
132
- }
133
-
134
- memorySessions.delete(sessionId);
135
- }
136
-
137
- /**
138
- * Validate and refresh a session.
139
- * Returns { valid, sessionId, setCookie } where setCookie is the updated
140
- * Set-Cookie header value (to extend Max-Age) or null.
141
- */
142
- export async function validateSession(request) {
143
- const sessionId = getSessionIdFromRequest(request);
144
-
145
- if (!sessionId) {
146
- return { valid: false, sessionId: null, setCookie: null };
147
- }
148
-
149
- const session = await loadSession(sessionId);
150
-
151
- if (!session) {
152
- return { valid: false, sessionId: null, setCookie: null };
153
- }
154
-
155
- // Sliding window: update lastUsed
156
- const now = nowSeconds();
157
- session.lastUsed = now;
158
- await saveSession(sessionId, session);
159
-
160
- // Determine if the request is HTTPS (for Secure cookie attribute)
161
- const url = new URL(request.url);
162
- const secure = url.protocol === "https:";
163
-
164
- return {
165
- valid: true,
166
- sessionId,
167
- setCookie: buildSessionCookie(sessionId, { secure }),
168
- };
169
- }
170
-
171
- /**
172
- * Create a new session and return { sessionId, setCookie }.
173
- */
174
- export async function createSession(request) {
175
- const sessionId = generateSessionId();
176
- const now = nowSeconds();
177
-
178
- await saveSession(sessionId, {
179
- createdAt: now,
180
- lastUsed: now,
181
- requestCount: 0,
182
- });
183
-
184
- const url = new URL(request.url);
185
- const secure = url.protocol === "https:";
186
-
187
- return {
188
- sessionId,
189
- setCookie: buildSessionCookie(sessionId, { secure }),
190
- };
191
- }
192
-
193
- /**
194
- * Revoke a session (logout / invalidate).
195
- */
196
- export async function revokeSession(sessionId) {
197
- await deleteSession(sessionId);
198
- }
@@ -1 +0,0 @@
1
- export * from "./session.impl.js";
@@ -1,18 +0,0 @@
1
- import { env } from "../../envs.js";
2
-
3
- export function getStateKv() {
4
- if (env.SEARCH_STATE_KV && typeof env.SEARCH_STATE_KV.get === "function") {
5
- return env.SEARCH_STATE_KV;
6
- }
7
-
8
- return null;
9
- }
10
-
11
- export function normalizeExpirationTtl(value, fallback) {
12
- const parsed = Number.parseInt(value ?? String(fallback), 10);
13
- if (Number.isNaN(parsed) || parsed <= 0) {
14
- return fallback;
15
- }
16
-
17
- return parsed;
18
- }
@@ -1 +0,0 @@
1
- export * from "./stateKv.impl.js";
@@ -1,17 +0,0 @@
1
- import { logWarn } from "./logger.js";
2
-
3
- export function runDeferredTask(runtimeContext, label, task) {
4
- const runner = Promise.resolve()
5
- .then(task)
6
- .catch((error) => {
7
- logWarn("task.background_failed", { task: label }, error, runtimeContext);
8
- });
9
-
10
- const executionCtx = runtimeContext?.executionCtx;
11
- if (executionCtx && typeof executionCtx.waitUntil === "function") {
12
- executionCtx.waitUntil(runner);
13
- return Promise.resolve();
14
- }
15
-
16
- return runner;
17
- }
@@ -1 +0,0 @@
1
- export * from "./tasks.impl.js";
@@ -1,12 +0,0 @@
1
- export function normalizePositiveInteger(value, fallback, { min = 1, max } = {}) {
2
- const parsed = Number.parseInt(value, 10);
3
- if (!Number.isFinite(parsed) || parsed < min) {
4
- return fallback;
5
- }
6
-
7
- if (max !== undefined && parsed > max) {
8
- return max;
9
- }
10
-
11
- return parsed;
12
- }
@@ -1 +0,0 @@
1
- export * from "./requestParams.impl.js";
@@ -1,117 +0,0 @@
1
- import { env } from "../../envs.js";
2
- import { baiduAdapter } from "./engines/baidu.js";
3
- import { bingAdapter } from "./engines/bing.js";
4
- import { braveAdapter } from "./engines/brave.js";
5
- import { duckDuckGoAdapter } from "./engines/duckduckgo.js";
6
- import { mojeekAdapter } from "./engines/mojeek.js";
7
- import { qwantAdapter } from "./engines/qwant.js";
8
- import { startpageAdapter } from "./engines/startpage.js";
9
- import { toutiaoAdapter } from "./engines/toutiao.js";
10
- import { yahooAdapter } from "./engines/yahoo.js";
11
-
12
- const ENGINE_REGISTRY = {
13
- baidu: baiduAdapter,
14
- bing: bingAdapter,
15
- toutiao: toutiaoAdapter,
16
- startpage: startpageAdapter,
17
- mojeek: mojeekAdapter,
18
- duckduckgo: duckDuckGoAdapter,
19
- brave: braveAdapter,
20
- qwant: qwantAdapter,
21
- yahoo: yahooAdapter,
22
- };
23
-
24
- export function getEngineRegistry() {
25
- return ENGINE_REGISTRY;
26
- }
27
-
28
- function getSupportedVerticals(adapter) {
29
- const verticals = adapter?.supports?.verticals;
30
- return Array.isArray(verticals) && verticals.length > 0 ? verticals : ["web"];
31
- }
32
-
33
- function normalizeEngineList(engines) {
34
- if (!engines) {
35
- return [];
36
- }
37
-
38
- if (Array.isArray(engines)) {
39
- return engines;
40
- }
41
-
42
- return String(engines).split(",");
43
- }
44
-
45
- export function normalizeRequestedEngines(engines) {
46
- return normalizeEngineList(engines)
47
- .map((engine) => String(engine).trim().toLowerCase())
48
- .filter(Boolean);
49
- }
50
-
51
- /**
52
- * Resolve the engines the caller explicitly requested.
53
- * Language-specific defaults are resolved before this layer, so this function
54
- * only filters and normalizes the concrete engine list it receives.
55
- * `env.SUPPORTED_ENGINES` is still used to filter out engines the deployment
56
- * does not recognize.
57
- */
58
- export function resolveEngineSelection(engines, options = {}) {
59
- const vertical = String(options.vertical || "web").trim().toLowerCase() || "web";
60
- const requestedEngines = normalizeRequestedEngines(engines);
61
- const supportedEngines = new Set(env.SUPPORTED_ENGINES);
62
- const seen = new Set();
63
- const enabledEngines = [];
64
- const skippedEngines = [];
65
-
66
- for (const engine of requestedEngines) {
67
- if (seen.has(engine)) {
68
- continue;
69
- }
70
-
71
- seen.add(engine);
72
-
73
- const adapter = ENGINE_REGISTRY[engine];
74
- if (!adapter || !supportedEngines.has(engine)) {
75
- skippedEngines.push({
76
- engine,
77
- reason: "unsupported_engine",
78
- });
79
- continue;
80
- }
81
-
82
- if (!getSupportedVerticals(adapter).includes(vertical)) {
83
- skippedEngines.push({
84
- engine,
85
- reason: "unsupported_vertical",
86
- });
87
- continue;
88
- }
89
-
90
- if (adapter.isAvailable && !adapter.isAvailable()) {
91
- skippedEngines.push({
92
- engine,
93
- reason: "unavailable_engine",
94
- });
95
- continue;
96
- }
97
-
98
- enabledEngines.push(engine);
99
- }
100
-
101
- return {
102
- requestedEngines,
103
- enabledEngines,
104
- skippedEngines,
105
- };
106
- }
107
-
108
- export function resolveEngineOrder(engines, options = {}) {
109
- return resolveEngineSelection(engines, options).enabledEngines;
110
- }
111
-
112
- export function getSupportedEnginesForVertical(vertical = "web") {
113
- return Object.keys(ENGINE_REGISTRY).filter((engineName) => {
114
- const adapter = ENGINE_REGISTRY[engineName];
115
- return getSupportedVerticals(adapter).includes(String(vertical).toLowerCase());
116
- });
117
- }
@@ -1 +0,0 @@
1
- export * from "./engineRegistry.impl.js";