@metalift/sdk
Advanced tools
| export declare const SEARCH_UNAVAILABLE_DOCS = "https://metalift.ai/docs/release-notes"; | ||
| export declare function searchUnavailableMessage(apiUrl: string, statusCode?: number): string; | ||
| export declare function formatSearchApiError(apiUrl: string, body: unknown, status: number): string | null; |
| export const SEARCH_UNAVAILABLE_DOCS = "https://metalift.ai/docs/release-notes"; | ||
| export function searchUnavailableMessage(apiUrl, statusCode) { | ||
| const status = statusCode ? ` (HTTP ${statusCode})` : ""; | ||
| return (`Web search is not available on ${apiUrl}${status}. ` + | ||
| "POST /v1/search was not found or search is disabled on this API host. " + | ||
| "Metalift Cloud (https://api.metalift.ai) may not have search deployed yet — " + | ||
| "use a self-hosted scrape API with SEARCH_ENABLED=true, or check " + | ||
| `${SEARCH_UNAVAILABLE_DOCS} for rollout status.`); | ||
| } | ||
| export function formatSearchApiError(apiUrl, body, status) { | ||
| if (status === 404) { | ||
| return searchUnavailableMessage(apiUrl, status); | ||
| } | ||
| if (status === 503) { | ||
| const detail = typeof body === "object" && body !== null && "detail" in body | ||
| ? String(body.detail ?? "") | ||
| : ""; | ||
| if (/search|searxng/i.test(detail)) { | ||
| return searchUnavailableMessage(apiUrl, status); | ||
| } | ||
| } | ||
| return null; | ||
| } |
| export {}; |
| import assert from "node:assert/strict"; | ||
| import test from "node:test"; | ||
| import { formatSearchApiError, searchUnavailableMessage } from "./search-errors.js"; | ||
| test("searchUnavailableMessage includes api url and docs link", () => { | ||
| const msg = searchUnavailableMessage("https://api.metalift.ai", 404); | ||
| assert.match(msg, /api\.metalift\.ai/); | ||
| assert.match(msg, /404/); | ||
| assert.match(msg, /release-notes/); | ||
| }); | ||
| test("formatSearchApiError maps 404 to search unavailable", () => { | ||
| const msg = formatSearchApiError("https://api.metalift.ai", { detail: "Not Found" }, 404); | ||
| assert.ok(msg); | ||
| assert.match(msg, /Web search is not available/); | ||
| }); |
+8
-0
@@ -39,2 +39,9 @@ export interface MetaliftConfig { | ||
| } | ||
| export interface HealthResponse { | ||
| status: string; | ||
| version?: string; | ||
| search_enabled?: boolean; | ||
| search_ready?: boolean | null; | ||
| browser_ready?: boolean; | ||
| } | ||
| export declare class Metalift { | ||
@@ -69,2 +76,3 @@ private apiUrl; | ||
| search(params: SearchParams): Promise<SearchResponse>; | ||
| health(): Promise<HealthResponse>; | ||
| getJob(jobId: string): Promise<{ | ||
@@ -71,0 +79,0 @@ status: string; |
+8
-2
@@ -0,1 +1,2 @@ | ||
| import { formatSearchApiError } from "./search-errors.js"; | ||
| export class Metalift { | ||
@@ -20,4 +21,6 @@ apiUrl; | ||
| const body = await response.json(); | ||
| if (!response.ok) | ||
| throw new Error(body.detail || body.error || response.statusText); | ||
| if (!response.ok) { | ||
| const searchError = path === "/v1/search" ? formatSearchApiError(this.apiUrl, body, response.status) : null; | ||
| throw new Error(searchError || body.detail || body.error || response.statusText); | ||
| } | ||
| return body; | ||
@@ -47,2 +50,5 @@ } | ||
| } | ||
| health() { | ||
| return this.request("/health"); | ||
| } | ||
| async getJob(jobId) { | ||
@@ -49,0 +55,0 @@ return this.request(`/v1/jobs/${jobId}`); |
+1
-1
| { | ||
| "name": "@metalift/sdk", | ||
| "version": "1.0.5", | ||
| "version": "1.0.6", | ||
| "description": "Metalift TypeScript SDK", | ||
@@ -5,0 +5,0 @@ "license": "SEE LICENSE IN LICENSE", |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
12516
24.84%9
80%194
39.57%