@search1api/client 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.
- package/LICENSE +22 -0
- package/README.md +80 -0
- package/dist/client.d.ts +31 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/errors.d.ts +41 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/generated.d.ts +1269 -0
- package/dist/generated.d.ts.map +1 -0
- package/dist/index.cjs +448 -0
- package/dist/index.cjs.map +7 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +425 -0
- package/dist/index.js.map +7 -0
- package/dist/types.d.ts +199 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +52 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
var Search1APIError = class extends Error {
|
|
3
|
+
constructor(message, options) {
|
|
4
|
+
super(message, options);
|
|
5
|
+
this.name = new.target.name;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
var Search1APIConfigurationError = class extends Search1APIError {
|
|
9
|
+
};
|
|
10
|
+
var APIConnectionError = class extends Search1APIError {
|
|
11
|
+
};
|
|
12
|
+
var APITimeoutError = class extends APIConnectionError {
|
|
13
|
+
};
|
|
14
|
+
var APIStatusError = class extends Search1APIError {
|
|
15
|
+
body;
|
|
16
|
+
headers;
|
|
17
|
+
requestId;
|
|
18
|
+
status;
|
|
19
|
+
constructor(message, status, headers, body) {
|
|
20
|
+
super(message);
|
|
21
|
+
this.status = status;
|
|
22
|
+
this.headers = headers;
|
|
23
|
+
this.body = body;
|
|
24
|
+
this.requestId = headers.get("x-request-id") ?? void 0;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var BadRequestError = class extends APIStatusError {
|
|
28
|
+
};
|
|
29
|
+
var AuthenticationError = class extends APIStatusError {
|
|
30
|
+
};
|
|
31
|
+
var PaymentRequiredError = class extends APIStatusError {
|
|
32
|
+
};
|
|
33
|
+
var NotFoundError = class extends APIStatusError {
|
|
34
|
+
};
|
|
35
|
+
var UnprocessableEntityError = class extends APIStatusError {
|
|
36
|
+
};
|
|
37
|
+
var RateLimitError = class extends APIStatusError {
|
|
38
|
+
};
|
|
39
|
+
var InternalServerError = class extends APIStatusError {
|
|
40
|
+
};
|
|
41
|
+
var DeepcrawlFailedError = class extends Search1APIError {
|
|
42
|
+
response;
|
|
43
|
+
constructor(response) {
|
|
44
|
+
super(
|
|
45
|
+
response.error || response.message || `Deepcrawl task ${response.taskId} failed`
|
|
46
|
+
);
|
|
47
|
+
this.response = response;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
var DeepcrawlTimeoutError = class extends Search1APIError {
|
|
51
|
+
taskId;
|
|
52
|
+
constructor(taskId, timeoutMs) {
|
|
53
|
+
super(`Deepcrawl task ${taskId} did not finish within ${timeoutMs}ms`);
|
|
54
|
+
this.taskId = taskId;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
function apiStatusError(status, headers, body) {
|
|
58
|
+
const message = body?.message || body?.detail || body?.error || body?.title || `Search1API request failed with status ${status}`;
|
|
59
|
+
const ErrorClass = status === 400 ? BadRequestError : status === 401 ? AuthenticationError : status === 402 ? PaymentRequiredError : status === 404 ? NotFoundError : status === 422 ? UnprocessableEntityError : status === 429 ? RateLimitError : status >= 500 ? InternalServerError : APIStatusError;
|
|
60
|
+
return new ErrorClass(message, status, headers, body);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/client.ts
|
|
64
|
+
var DEFAULT_BASE_URL = "https://api.search1api.com";
|
|
65
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
66
|
+
var DEFAULT_MAX_RETRIES = 2;
|
|
67
|
+
var DEFAULT_RETRY_DELAY_MS = 500;
|
|
68
|
+
var DEFAULT_DEEPCRAWL_POLL_INTERVAL_MS = 2e3;
|
|
69
|
+
var DEFAULT_DEEPCRAWL_TIMEOUT_MS = 3e5;
|
|
70
|
+
function environmentApiKey() {
|
|
71
|
+
const processLike = globalThis;
|
|
72
|
+
return processLike.process?.env?.SEARCH1API_API_KEY;
|
|
73
|
+
}
|
|
74
|
+
function compact(value) {
|
|
75
|
+
return Object.fromEntries(
|
|
76
|
+
Object.entries(value).filter(([, item]) => item !== void 0)
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
function searchBody(query, options) {
|
|
80
|
+
return compact({
|
|
81
|
+
query,
|
|
82
|
+
search_service: options.searchService,
|
|
83
|
+
max_results: options.maxResults,
|
|
84
|
+
crawl_results: options.crawlResults,
|
|
85
|
+
image: options.image,
|
|
86
|
+
include_sites: options.includeSites,
|
|
87
|
+
exclude_sites: options.excludeSites,
|
|
88
|
+
language: options.language,
|
|
89
|
+
time_range: options.timeRange
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function newsBody(query, options) {
|
|
93
|
+
return compact({
|
|
94
|
+
query,
|
|
95
|
+
search_service: options.searchService,
|
|
96
|
+
max_results: options.maxResults,
|
|
97
|
+
crawl_results: options.crawlResults,
|
|
98
|
+
image: options.image,
|
|
99
|
+
include_sites: options.includeSites,
|
|
100
|
+
exclude_sites: options.excludeSites,
|
|
101
|
+
language: options.language,
|
|
102
|
+
time_range: options.timeRange
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function retryAfterMs(response) {
|
|
106
|
+
const value = response.headers.get("retry-after");
|
|
107
|
+
if (!value) return void 0;
|
|
108
|
+
const seconds = Number(value);
|
|
109
|
+
if (Number.isFinite(seconds)) return Math.max(0, seconds * 1e3);
|
|
110
|
+
const date = Date.parse(value);
|
|
111
|
+
if (Number.isNaN(date)) return void 0;
|
|
112
|
+
return Math.max(0, date - Date.now());
|
|
113
|
+
}
|
|
114
|
+
function shouldRetry(status) {
|
|
115
|
+
return status === 429 || status >= 500;
|
|
116
|
+
}
|
|
117
|
+
function validateRequestLimits(timeoutMs, maxRetries) {
|
|
118
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
119
|
+
throw new Search1APIConfigurationError("timeoutMs must be positive");
|
|
120
|
+
}
|
|
121
|
+
if (!Number.isInteger(maxRetries) || maxRetries < 0) {
|
|
122
|
+
throw new Search1APIConfigurationError(
|
|
123
|
+
"maxRetries must be a non-negative integer"
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function sleep(ms, signal) {
|
|
128
|
+
if (signal?.aborted) {
|
|
129
|
+
return Promise.reject(
|
|
130
|
+
new APIConnectionError("Search1API request was aborted")
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
if (ms <= 0) return Promise.resolve();
|
|
134
|
+
return new Promise((resolve, reject) => {
|
|
135
|
+
const timeout = setTimeout(() => {
|
|
136
|
+
signal?.removeEventListener("abort", onAbort);
|
|
137
|
+
resolve();
|
|
138
|
+
}, ms);
|
|
139
|
+
const onAbort = () => {
|
|
140
|
+
clearTimeout(timeout);
|
|
141
|
+
reject(new APIConnectionError("Search1API request was aborted"));
|
|
142
|
+
};
|
|
143
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
async function errorBody(response) {
|
|
147
|
+
const text = await response.text();
|
|
148
|
+
if (!text) return void 0;
|
|
149
|
+
try {
|
|
150
|
+
return JSON.parse(text);
|
|
151
|
+
} catch {
|
|
152
|
+
return { message: text };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
var Search1API = class {
|
|
156
|
+
apiKey;
|
|
157
|
+
baseUrl;
|
|
158
|
+
maxRetries;
|
|
159
|
+
timeoutMs;
|
|
160
|
+
defaultHeaders;
|
|
161
|
+
fetchClient;
|
|
162
|
+
retryDelayMs;
|
|
163
|
+
constructor(options = {}) {
|
|
164
|
+
const normalized = typeof options === "string" ? { apiKey: options } : options;
|
|
165
|
+
const apiKey = normalized.apiKey || environmentApiKey();
|
|
166
|
+
if (!apiKey) {
|
|
167
|
+
throw new Search1APIConfigurationError(
|
|
168
|
+
"Missing API key. Pass apiKey or set SEARCH1API_API_KEY."
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
const fetchClient = normalized.fetch || globalThis.fetch;
|
|
172
|
+
if (!fetchClient) {
|
|
173
|
+
throw new Search1APIConfigurationError(
|
|
174
|
+
"No fetch implementation is available. Search1API requires Node.js 18+ or a custom fetch."
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
this.apiKey = apiKey;
|
|
178
|
+
this.baseUrl = (normalized.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
179
|
+
this.fetchClient = fetchClient;
|
|
180
|
+
this.timeoutMs = normalized.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
181
|
+
this.maxRetries = normalized.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
182
|
+
this.retryDelayMs = normalized.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
183
|
+
validateRequestLimits(this.timeoutMs, this.maxRetries);
|
|
184
|
+
if (!Number.isFinite(this.retryDelayMs) || this.retryDelayMs < 0) {
|
|
185
|
+
throw new Search1APIConfigurationError(
|
|
186
|
+
"retryDelayMs must be non-negative"
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
this.defaultHeaders = normalized.headers ?? {};
|
|
190
|
+
}
|
|
191
|
+
async search(query, options = {}, requestOptions = {}) {
|
|
192
|
+
return this.requestJson("/search", {
|
|
193
|
+
...requestOptions,
|
|
194
|
+
method: "POST",
|
|
195
|
+
body: searchBody(query, options)
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
async searchBatch(requests, requestOptions = {}) {
|
|
199
|
+
return this.requestJson("/search", {
|
|
200
|
+
...requestOptions,
|
|
201
|
+
method: "POST",
|
|
202
|
+
body: requests.map(({ query, ...options }) => searchBody(query, options))
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
async news(query, options = {}, requestOptions = {}) {
|
|
206
|
+
return this.requestJson("/news", {
|
|
207
|
+
...requestOptions,
|
|
208
|
+
method: "POST",
|
|
209
|
+
body: newsBody(query, options)
|
|
210
|
+
});
|
|
211
|
+
}
|
|
212
|
+
async newsBatch(requests, requestOptions = {}) {
|
|
213
|
+
return this.requestJson("/news", {
|
|
214
|
+
...requestOptions,
|
|
215
|
+
method: "POST",
|
|
216
|
+
body: requests.map(({ query, ...options }) => newsBody(query, options))
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
async crawl(url, options = {}, requestOptions = {}) {
|
|
220
|
+
return this.requestJson("/crawl", {
|
|
221
|
+
...requestOptions,
|
|
222
|
+
method: "POST",
|
|
223
|
+
body: compact({ url, enableFallback: options.enableFallback })
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
async crawlBatch(requests, requestOptions = {}) {
|
|
227
|
+
return this.requestJson("/crawl", {
|
|
228
|
+
...requestOptions,
|
|
229
|
+
method: "POST",
|
|
230
|
+
body: requests.map(
|
|
231
|
+
({ url, enableFallback }) => compact({ url, enableFallback })
|
|
232
|
+
)
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
async sitemap(url, options = {}, requestOptions = {}) {
|
|
236
|
+
return this.requestJson("/sitemap", {
|
|
237
|
+
...requestOptions,
|
|
238
|
+
method: "POST",
|
|
239
|
+
body: compact({ url, type: options.type })
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
async trending(searchService, options = {}, requestOptions = {}) {
|
|
243
|
+
return this.requestJson("/trending", {
|
|
244
|
+
...requestOptions,
|
|
245
|
+
method: "POST",
|
|
246
|
+
body: compact({
|
|
247
|
+
search_service: searchService,
|
|
248
|
+
max_results: options.maxResults
|
|
249
|
+
})
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
async extract(url, options = {}, requestOptions = {}) {
|
|
253
|
+
return this.requestJson("/extract", {
|
|
254
|
+
...requestOptions,
|
|
255
|
+
method: "POST",
|
|
256
|
+
body: compact({
|
|
257
|
+
url,
|
|
258
|
+
prompt: options.prompt,
|
|
259
|
+
response_format: options.responseFormat
|
|
260
|
+
})
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
async startDeepcrawl(url, options = {}, requestOptions = {}) {
|
|
264
|
+
return this.requestJson("/deepcrawl", {
|
|
265
|
+
...requestOptions,
|
|
266
|
+
// Starting a task is not idempotent. A lost response could otherwise
|
|
267
|
+
// enqueue and charge a duplicate crawl.
|
|
268
|
+
maxRetries: requestOptions.maxRetries ?? 0,
|
|
269
|
+
method: "POST",
|
|
270
|
+
body: compact({ url, type: options.type })
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
async getDeepcrawlStatus(taskId, requestOptions = {}) {
|
|
274
|
+
return this.requestJson(
|
|
275
|
+
`/deepcrawl/status/${encodeURIComponent(taskId)}`,
|
|
276
|
+
requestOptions
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
async waitForDeepcrawl(taskId, options = {}) {
|
|
280
|
+
const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_DEEPCRAWL_POLL_INTERVAL_MS;
|
|
281
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_DEEPCRAWL_TIMEOUT_MS;
|
|
282
|
+
const deadline = Date.now() + timeoutMs;
|
|
283
|
+
while (true) {
|
|
284
|
+
const response = await this.getDeepcrawlStatus(taskId, {
|
|
285
|
+
signal: options.signal
|
|
286
|
+
});
|
|
287
|
+
if (response.success === true || response.status === "completed") {
|
|
288
|
+
return response;
|
|
289
|
+
}
|
|
290
|
+
if (response.success === false || response.status === "failed" || response.status === "not_found") {
|
|
291
|
+
throw new DeepcrawlFailedError(response);
|
|
292
|
+
}
|
|
293
|
+
if (Date.now() + pollIntervalMs > deadline) {
|
|
294
|
+
throw new DeepcrawlTimeoutError(taskId, timeoutMs);
|
|
295
|
+
}
|
|
296
|
+
await sleep(pollIntervalMs, options.signal);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
async deepcrawl(url, options = {}, waitOptions = {}, requestOptions = {}) {
|
|
300
|
+
const task = await this.startDeepcrawl(url, options, requestOptions);
|
|
301
|
+
return this.waitForDeepcrawl(task.taskId, waitOptions);
|
|
302
|
+
}
|
|
303
|
+
async usage(period, requestOptions = {}) {
|
|
304
|
+
return this.requestJson("/usage", {
|
|
305
|
+
...requestOptions,
|
|
306
|
+
query: { period }
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
async health(requestOptions = {}) {
|
|
310
|
+
return this.requestJson("/health", requestOptions);
|
|
311
|
+
}
|
|
312
|
+
async requestJson(path, options = {}) {
|
|
313
|
+
const response = await this.request(path, options);
|
|
314
|
+
const text = await response.text();
|
|
315
|
+
try {
|
|
316
|
+
return JSON.parse(text);
|
|
317
|
+
} catch (error) {
|
|
318
|
+
throw new Search1APIError(
|
|
319
|
+
`Search1API returned invalid JSON for ${path}`,
|
|
320
|
+
{ cause: error }
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
async request(path, options = {}) {
|
|
325
|
+
const maxRetries = options.maxRetries ?? this.maxRetries;
|
|
326
|
+
validateRequestLimits(options.timeoutMs ?? this.timeoutMs, maxRetries);
|
|
327
|
+
const url = new URL(`${this.baseUrl}${path}`);
|
|
328
|
+
for (const [name, value] of Object.entries(options.query || {})) {
|
|
329
|
+
if (value !== void 0) url.searchParams.set(name, value);
|
|
330
|
+
}
|
|
331
|
+
for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
|
|
332
|
+
let response;
|
|
333
|
+
try {
|
|
334
|
+
response = await this.fetchOnce(url, options);
|
|
335
|
+
} catch (error) {
|
|
336
|
+
if (attempt < maxRetries && !options.signal?.aborted && (error instanceof APIConnectionError || error instanceof APITimeoutError)) {
|
|
337
|
+
await sleep(this.retryDelay(attempt), options.signal);
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
if (response.ok) return response;
|
|
343
|
+
if (attempt < maxRetries && shouldRetry(response.status)) {
|
|
344
|
+
await sleep(
|
|
345
|
+
retryAfterMs(response) ?? this.retryDelay(attempt),
|
|
346
|
+
options.signal
|
|
347
|
+
);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
throw apiStatusError(
|
|
351
|
+
response.status,
|
|
352
|
+
response.headers,
|
|
353
|
+
await errorBody(response)
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
throw new Search1APIError("Search1API request exhausted its retry budget");
|
|
357
|
+
}
|
|
358
|
+
async fetchOnce(url, options) {
|
|
359
|
+
const controller = new AbortController();
|
|
360
|
+
let timedOut = false;
|
|
361
|
+
const timeout = setTimeout(() => {
|
|
362
|
+
timedOut = true;
|
|
363
|
+
controller.abort();
|
|
364
|
+
}, options.timeoutMs ?? this.timeoutMs);
|
|
365
|
+
const onAbort = () => controller.abort(options.signal?.reason);
|
|
366
|
+
options.signal?.addEventListener("abort", onAbort, { once: true });
|
|
367
|
+
const headers = new Headers({
|
|
368
|
+
Accept: "application/json",
|
|
369
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
370
|
+
"X-Search1API-Client": "typescript/0.1.0",
|
|
371
|
+
...this.defaultHeaders,
|
|
372
|
+
...options.headers
|
|
373
|
+
});
|
|
374
|
+
if (options.body !== void 0)
|
|
375
|
+
headers.set("Content-Type", "application/json");
|
|
376
|
+
try {
|
|
377
|
+
return await this.fetchClient(url, {
|
|
378
|
+
method: options.method || "GET",
|
|
379
|
+
headers,
|
|
380
|
+
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
381
|
+
signal: controller.signal
|
|
382
|
+
});
|
|
383
|
+
} catch (error) {
|
|
384
|
+
if (timedOut) {
|
|
385
|
+
throw new APITimeoutError(
|
|
386
|
+
`Search1API request timed out after ${options.timeoutMs ?? this.timeoutMs}ms`,
|
|
387
|
+
{ cause: error }
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
if (options.signal?.aborted) {
|
|
391
|
+
throw new APIConnectionError("Search1API request was aborted", {
|
|
392
|
+
cause: error
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
throw new APIConnectionError("Unable to connect to Search1API", {
|
|
396
|
+
cause: error
|
|
397
|
+
});
|
|
398
|
+
} finally {
|
|
399
|
+
clearTimeout(timeout);
|
|
400
|
+
options.signal?.removeEventListener("abort", onAbort);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
retryDelay(attempt) {
|
|
404
|
+
const base = this.retryDelayMs * 2 ** attempt;
|
|
405
|
+
return base + Math.floor(Math.random() * base * 0.25);
|
|
406
|
+
}
|
|
407
|
+
};
|
|
408
|
+
export {
|
|
409
|
+
APIConnectionError,
|
|
410
|
+
APIStatusError,
|
|
411
|
+
APITimeoutError,
|
|
412
|
+
AuthenticationError,
|
|
413
|
+
BadRequestError,
|
|
414
|
+
DeepcrawlFailedError,
|
|
415
|
+
DeepcrawlTimeoutError,
|
|
416
|
+
InternalServerError,
|
|
417
|
+
NotFoundError,
|
|
418
|
+
PaymentRequiredError,
|
|
419
|
+
RateLimitError,
|
|
420
|
+
Search1API,
|
|
421
|
+
Search1APIConfigurationError,
|
|
422
|
+
Search1APIError,
|
|
423
|
+
UnprocessableEntityError
|
|
424
|
+
};
|
|
425
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/errors.ts", "../src/client.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ApiErrorBody, DeepcrawlStatusResponse } from './types.js';\n\nexport class Search1APIError extends Error {\n constructor(message: string, options?: ErrorOptions) {\n super(message, options);\n this.name = new.target.name;\n }\n}\n\nexport class Search1APIConfigurationError extends Search1APIError {}\n\nexport class APIConnectionError extends Search1APIError {}\n\nexport class APITimeoutError extends APIConnectionError {}\n\nexport class APIStatusError extends Search1APIError {\n readonly body?: ApiErrorBody;\n readonly headers: Headers;\n readonly requestId?: string;\n readonly status: number;\n\n constructor(\n message: string,\n status: number,\n headers: Headers,\n body?: ApiErrorBody\n ) {\n super(message);\n this.status = status;\n this.headers = headers;\n this.body = body;\n this.requestId = headers.get('x-request-id') ?? undefined;\n }\n}\n\nexport class BadRequestError extends APIStatusError {}\nexport class AuthenticationError extends APIStatusError {}\nexport class PaymentRequiredError extends APIStatusError {}\nexport class NotFoundError extends APIStatusError {}\nexport class UnprocessableEntityError extends APIStatusError {}\nexport class RateLimitError extends APIStatusError {}\nexport class InternalServerError extends APIStatusError {}\n\nexport class DeepcrawlFailedError extends Search1APIError {\n readonly response: DeepcrawlStatusResponse;\n\n constructor(response: DeepcrawlStatusResponse) {\n super(\n response.error ||\n response.message ||\n `Deepcrawl task ${response.taskId} failed`\n );\n this.response = response;\n }\n}\n\nexport class DeepcrawlTimeoutError extends Search1APIError {\n readonly taskId: string;\n\n constructor(taskId: string, timeoutMs: number) {\n super(`Deepcrawl task ${taskId} did not finish within ${timeoutMs}ms`);\n this.taskId = taskId;\n }\n}\n\nexport function apiStatusError(\n status: number,\n headers: Headers,\n body?: ApiErrorBody\n): APIStatusError {\n const message =\n body?.message ||\n body?.detail ||\n body?.error ||\n body?.title ||\n `Search1API request failed with status ${status}`;\n const ErrorClass =\n status === 400\n ? BadRequestError\n : status === 401\n ? AuthenticationError\n : status === 402\n ? PaymentRequiredError\n : status === 404\n ? NotFoundError\n : status === 422\n ? UnprocessableEntityError\n : status === 429\n ? RateLimitError\n : status >= 500\n ? InternalServerError\n : APIStatusError;\n\n return new ErrorClass(message, status, headers, body);\n}\n", "import {\n APIConnectionError,\n APITimeoutError,\n DeepcrawlFailedError,\n DeepcrawlTimeoutError,\n Search1APIConfigurationError,\n Search1APIError,\n apiStatusError,\n} from './errors.js';\nimport type {\n ApiErrorBody,\n BatchResponse,\n CrawlOptions,\n CrawlRequest,\n CrawlResponse,\n DeepcrawlAcceptedResponse,\n DeepcrawlOptions,\n DeepcrawlStatusResponse,\n ExtractOptions,\n ExtractResponse,\n HealthResponse,\n JsonValue,\n NewsOptions,\n NewsRequest,\n NewsResponse,\n RequestOptions,\n Search1APIOptions,\n SearchOptions,\n SearchRequest,\n SearchResponse,\n SitemapOptions,\n SitemapResponse,\n TimeRange,\n TrendingOptions,\n TrendingResponse,\n UsageResponse,\n WaitForDeepcrawlOptions,\n} from './types.js';\n\nconst DEFAULT_BASE_URL = 'https://api.search1api.com';\nconst DEFAULT_TIMEOUT_MS = 30_000;\nconst DEFAULT_MAX_RETRIES = 2;\nconst DEFAULT_RETRY_DELAY_MS = 500;\nconst DEFAULT_DEEPCRAWL_POLL_INTERVAL_MS = 2_000;\nconst DEFAULT_DEEPCRAWL_TIMEOUT_MS = 300_000;\n\ntype RequestBody = JsonValue | Record<string, unknown> | unknown[];\n\ninterface InternalRequestOptions extends RequestOptions {\n body?: RequestBody;\n method?: 'GET' | 'POST';\n query?: Record<string, string | undefined>;\n}\n\nfunction environmentApiKey(): string | undefined {\n const processLike = globalThis as typeof globalThis & {\n process?: { env?: Record<string, string | undefined> };\n };\n return processLike.process?.env?.SEARCH1API_API_KEY;\n}\n\nfunction compact<T extends Record<string, unknown>>(value: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(value).filter(([, item]) => item !== undefined)\n ) as Partial<T>;\n}\n\nfunction searchBody(query: string, options: SearchOptions) {\n return compact({\n query,\n search_service: options.searchService,\n max_results: options.maxResults,\n crawl_results: options.crawlResults,\n image: options.image,\n include_sites: options.includeSites,\n exclude_sites: options.excludeSites,\n language: options.language,\n time_range: options.timeRange,\n });\n}\n\nfunction newsBody(query: string, options: NewsOptions) {\n return compact({\n query,\n search_service: options.searchService,\n max_results: options.maxResults,\n crawl_results: options.crawlResults,\n image: options.image,\n include_sites: options.includeSites,\n exclude_sites: options.excludeSites,\n language: options.language,\n time_range: options.timeRange,\n });\n}\n\nfunction retryAfterMs(response: Response): number | undefined {\n const value = response.headers.get('retry-after');\n if (!value) return undefined;\n\n const seconds = Number(value);\n if (Number.isFinite(seconds)) return Math.max(0, seconds * 1_000);\n\n const date = Date.parse(value);\n if (Number.isNaN(date)) return undefined;\n return Math.max(0, date - Date.now());\n}\n\nfunction shouldRetry(status: number): boolean {\n return status === 429 || status >= 500;\n}\n\nfunction validateRequestLimits(timeoutMs: number, maxRetries: number): void {\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new Search1APIConfigurationError('timeoutMs must be positive');\n }\n if (!Number.isInteger(maxRetries) || maxRetries < 0) {\n throw new Search1APIConfigurationError(\n 'maxRetries must be a non-negative integer'\n );\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n return Promise.reject(\n new APIConnectionError('Search1API request was aborted')\n );\n }\n if (ms <= 0) return Promise.resolve();\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timeout);\n reject(new APIConnectionError('Search1API request was aborted'));\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\nasync function errorBody(\n response: Response\n): Promise<ApiErrorBody | undefined> {\n const text = await response.text();\n if (!text) return undefined;\n try {\n return JSON.parse(text) as ApiErrorBody;\n } catch {\n return { message: text };\n }\n}\n\nexport class Search1API {\n readonly apiKey: string;\n readonly baseUrl: string;\n readonly maxRetries: number;\n readonly timeoutMs: number;\n\n private readonly defaultHeaders: Record<string, string>;\n private readonly fetchClient: typeof fetch;\n private readonly retryDelayMs: number;\n\n constructor(options: Search1APIOptions | string = {}) {\n const normalized =\n typeof options === 'string' ? { apiKey: options } : options;\n const apiKey = normalized.apiKey || environmentApiKey();\n if (!apiKey) {\n throw new Search1APIConfigurationError(\n 'Missing API key. Pass apiKey or set SEARCH1API_API_KEY.'\n );\n }\n\n const fetchClient = normalized.fetch || globalThis.fetch;\n if (!fetchClient) {\n throw new Search1APIConfigurationError(\n 'No fetch implementation is available. Search1API requires Node.js 18+ or a custom fetch.'\n );\n }\n\n this.apiKey = apiKey;\n this.baseUrl = (normalized.baseUrl || DEFAULT_BASE_URL).replace(/\\/+$/, '');\n this.fetchClient = fetchClient;\n this.timeoutMs = normalized.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n this.maxRetries = normalized.maxRetries ?? DEFAULT_MAX_RETRIES;\n this.retryDelayMs = normalized.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;\n validateRequestLimits(this.timeoutMs, this.maxRetries);\n if (!Number.isFinite(this.retryDelayMs) || this.retryDelayMs < 0) {\n throw new Search1APIConfigurationError(\n 'retryDelayMs must be non-negative'\n );\n }\n this.defaultHeaders = normalized.headers ?? {};\n }\n\n async search(\n query: string,\n options: SearchOptions = {},\n requestOptions: RequestOptions = {}\n ): Promise<SearchResponse> {\n return this.requestJson<SearchResponse>('/search', {\n ...requestOptions,\n method: 'POST',\n body: searchBody(query, options),\n });\n }\n\n async searchBatch(\n requests: SearchRequest[],\n requestOptions: RequestOptions = {}\n ): Promise<BatchResponse<SearchResponse>> {\n return this.requestJson<BatchResponse<SearchResponse>>('/search', {\n ...requestOptions,\n method: 'POST',\n body: requests.map(({ query, ...options }) => searchBody(query, options)),\n });\n }\n\n async news(\n query: string,\n options: NewsOptions = {},\n requestOptions: RequestOptions = {}\n ): Promise<NewsResponse> {\n return this.requestJson<NewsResponse>('/news', {\n ...requestOptions,\n method: 'POST',\n body: newsBody(query, options),\n });\n }\n\n async newsBatch(\n requests: NewsRequest[],\n requestOptions: RequestOptions = {}\n ): Promise<BatchResponse<NewsResponse>> {\n return this.requestJson<BatchResponse<NewsResponse>>('/news', {\n ...requestOptions,\n method: 'POST',\n body: requests.map(({ query, ...options }) => newsBody(query, options)),\n });\n }\n\n async crawl(\n url: string,\n options: CrawlOptions = {},\n requestOptions: RequestOptions = {}\n ): Promise<CrawlResponse> {\n return this.requestJson<CrawlResponse>('/crawl', {\n ...requestOptions,\n method: 'POST',\n body: compact({ url, enableFallback: options.enableFallback }),\n });\n }\n\n async crawlBatch(\n requests: CrawlRequest[],\n requestOptions: RequestOptions = {}\n ): Promise<CrawlResponse[]> {\n return this.requestJson<CrawlResponse[]>('/crawl', {\n ...requestOptions,\n method: 'POST',\n body: requests.map(({ url, enableFallback }) =>\n compact({ url, enableFallback })\n ),\n });\n }\n\n async sitemap(\n url: string,\n options: SitemapOptions = {},\n requestOptions: RequestOptions = {}\n ): Promise<SitemapResponse> {\n return this.requestJson<SitemapResponse>('/sitemap', {\n ...requestOptions,\n method: 'POST',\n body: compact({ url, type: options.type }),\n });\n }\n\n async trending(\n searchService: string,\n options: TrendingOptions = {},\n requestOptions: RequestOptions = {}\n ): Promise<TrendingResponse> {\n return this.requestJson<TrendingResponse>('/trending', {\n ...requestOptions,\n method: 'POST',\n body: compact({\n search_service: searchService,\n max_results: options.maxResults,\n }),\n });\n }\n\n async extract<T = JsonValue>(\n url: string,\n options: ExtractOptions = {},\n requestOptions: RequestOptions = {}\n ): Promise<ExtractResponse<T>> {\n return this.requestJson<ExtractResponse<T>>('/extract', {\n ...requestOptions,\n method: 'POST',\n body: compact({\n url,\n prompt: options.prompt,\n response_format: options.responseFormat,\n }),\n });\n }\n\n async startDeepcrawl(\n url: string,\n options: DeepcrawlOptions = {},\n requestOptions: RequestOptions = {}\n ): Promise<DeepcrawlAcceptedResponse> {\n return this.requestJson<DeepcrawlAcceptedResponse>('/deepcrawl', {\n ...requestOptions,\n // Starting a task is not idempotent. A lost response could otherwise\n // enqueue and charge a duplicate crawl.\n maxRetries: requestOptions.maxRetries ?? 0,\n method: 'POST',\n body: compact({ url, type: options.type }),\n });\n }\n\n async getDeepcrawlStatus(\n taskId: string,\n requestOptions: RequestOptions = {}\n ): Promise<DeepcrawlStatusResponse> {\n return this.requestJson<DeepcrawlStatusResponse>(\n `/deepcrawl/status/${encodeURIComponent(taskId)}`,\n requestOptions\n );\n }\n\n async waitForDeepcrawl(\n taskId: string,\n options: WaitForDeepcrawlOptions = {}\n ): Promise<DeepcrawlStatusResponse> {\n const pollIntervalMs =\n options.pollIntervalMs ?? DEFAULT_DEEPCRAWL_POLL_INTERVAL_MS;\n const timeoutMs = options.timeoutMs ?? DEFAULT_DEEPCRAWL_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n\n while (true) {\n const response = await this.getDeepcrawlStatus(taskId, {\n signal: options.signal,\n });\n if (response.success === true || response.status === 'completed') {\n return response;\n }\n if (\n response.success === false ||\n response.status === 'failed' ||\n response.status === 'not_found'\n ) {\n throw new DeepcrawlFailedError(response);\n }\n if (Date.now() + pollIntervalMs > deadline) {\n throw new DeepcrawlTimeoutError(taskId, timeoutMs);\n }\n await sleep(pollIntervalMs, options.signal);\n }\n }\n\n async deepcrawl(\n url: string,\n options: DeepcrawlOptions = {},\n waitOptions: WaitForDeepcrawlOptions = {},\n requestOptions: RequestOptions = {}\n ): Promise<DeepcrawlStatusResponse> {\n const task = await this.startDeepcrawl(url, options, requestOptions);\n return this.waitForDeepcrawl(task.taskId, waitOptions);\n }\n\n async usage(\n period?: TimeRange,\n requestOptions: RequestOptions = {}\n ): Promise<UsageResponse> {\n return this.requestJson<UsageResponse>('/usage', {\n ...requestOptions,\n query: { period },\n });\n }\n\n async health(requestOptions: RequestOptions = {}): Promise<HealthResponse> {\n return this.requestJson<HealthResponse>('/health', requestOptions);\n }\n\n private async requestJson<T>(\n path: string,\n options: InternalRequestOptions = {}\n ): Promise<T> {\n const response = await this.request(path, options);\n const text = await response.text();\n try {\n return JSON.parse(text) as T;\n } catch (error) {\n throw new Search1APIError(\n `Search1API returned invalid JSON for ${path}`,\n { cause: error }\n );\n }\n }\n\n private async request(\n path: string,\n options: InternalRequestOptions = {}\n ): Promise<Response> {\n const maxRetries = options.maxRetries ?? this.maxRetries;\n validateRequestLimits(options.timeoutMs ?? this.timeoutMs, maxRetries);\n const url = new URL(`${this.baseUrl}${path}`);\n for (const [name, value] of Object.entries(options.query || {})) {\n if (value !== undefined) url.searchParams.set(name, value);\n }\n\n for (let attempt = 0; attempt <= maxRetries; attempt += 1) {\n let response: Response;\n try {\n response = await this.fetchOnce(url, options);\n } catch (error) {\n if (\n attempt < maxRetries &&\n !options.signal?.aborted &&\n (error instanceof APIConnectionError ||\n error instanceof APITimeoutError)\n ) {\n await sleep(this.retryDelay(attempt), options.signal);\n continue;\n }\n throw error;\n }\n\n if (response.ok) return response;\n if (attempt < maxRetries && shouldRetry(response.status)) {\n await sleep(\n retryAfterMs(response) ?? this.retryDelay(attempt),\n options.signal\n );\n continue;\n }\n\n throw apiStatusError(\n response.status,\n response.headers,\n await errorBody(response)\n );\n }\n\n throw new Search1APIError('Search1API request exhausted its retry budget');\n }\n\n private async fetchOnce(\n url: URL,\n options: InternalRequestOptions\n ): Promise<Response> {\n const controller = new AbortController();\n let timedOut = false;\n const timeout = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, options.timeoutMs ?? this.timeoutMs);\n const onAbort = () => controller.abort(options.signal?.reason);\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n const headers = new Headers({\n Accept: 'application/json',\n Authorization: `Bearer ${this.apiKey}`,\n 'X-Search1API-Client': 'typescript/0.1.0',\n ...this.defaultHeaders,\n ...options.headers,\n });\n if (options.body !== undefined)\n headers.set('Content-Type', 'application/json');\n\n try {\n return await this.fetchClient(url, {\n method: options.method || 'GET',\n headers,\n body:\n options.body === undefined ? undefined : JSON.stringify(options.body),\n signal: controller.signal,\n });\n } catch (error) {\n if (timedOut) {\n throw new APITimeoutError(\n `Search1API request timed out after ${options.timeoutMs ?? this.timeoutMs}ms`,\n { cause: error }\n );\n }\n if (options.signal?.aborted) {\n throw new APIConnectionError('Search1API request was aborted', {\n cause: error,\n });\n }\n throw new APIConnectionError('Unable to connect to Search1API', {\n cause: error,\n });\n } finally {\n clearTimeout(timeout);\n options.signal?.removeEventListener('abort', onAbort);\n }\n }\n\n private retryDelay(attempt: number): number {\n const base = this.retryDelayMs * 2 ** attempt;\n return base + Math.floor(Math.random() * base * 0.25);\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
export type JsonPrimitive = boolean | number | string | null;
|
|
2
|
+
export type JsonValue = JsonPrimitive | JsonValue[] | {
|
|
3
|
+
[key: string]: JsonValue;
|
|
4
|
+
};
|
|
5
|
+
export type TimeRange = 'day' | 'week' | 'month' | 'year';
|
|
6
|
+
export type SearchEngine = 'google' | 'bing' | 'duckduckgo' | 'yahoo' | 'youtube' | 'x' | 'reddit' | 'github' | 'arxiv' | 'wechat' | 'bilibili' | 'imdb' | 'wikipedia' | 'sogou' | 'baidu' | '360' | 'quark';
|
|
7
|
+
export type NewsEngine = 'google' | 'bing' | 'duckduckgo' | 'yahoo' | 'hackernews' | 'reuters';
|
|
8
|
+
export interface SearchOptions {
|
|
9
|
+
searchService?: SearchEngine;
|
|
10
|
+
maxResults?: number;
|
|
11
|
+
crawlResults?: number;
|
|
12
|
+
image?: boolean;
|
|
13
|
+
includeSites?: string[];
|
|
14
|
+
excludeSites?: string[];
|
|
15
|
+
language?: string;
|
|
16
|
+
timeRange?: TimeRange;
|
|
17
|
+
}
|
|
18
|
+
export interface SearchRequest extends SearchOptions {
|
|
19
|
+
query: string;
|
|
20
|
+
}
|
|
21
|
+
export interface NewsOptions {
|
|
22
|
+
searchService?: NewsEngine;
|
|
23
|
+
maxResults?: number;
|
|
24
|
+
crawlResults?: number;
|
|
25
|
+
image?: boolean;
|
|
26
|
+
includeSites?: string[];
|
|
27
|
+
excludeSites?: string[];
|
|
28
|
+
language?: string;
|
|
29
|
+
timeRange?: TimeRange;
|
|
30
|
+
}
|
|
31
|
+
export interface NewsRequest extends NewsOptions {
|
|
32
|
+
query: string;
|
|
33
|
+
}
|
|
34
|
+
export interface SearchParameters {
|
|
35
|
+
query: string;
|
|
36
|
+
search_service?: SearchEngine;
|
|
37
|
+
max_results: number;
|
|
38
|
+
crawl_results: number;
|
|
39
|
+
image: boolean;
|
|
40
|
+
include_sites: string[];
|
|
41
|
+
exclude_sites: string[];
|
|
42
|
+
language?: string;
|
|
43
|
+
time_range?: TimeRange;
|
|
44
|
+
}
|
|
45
|
+
export interface NewsParameters extends Omit<SearchParameters, 'search_service'> {
|
|
46
|
+
search_service?: NewsEngine;
|
|
47
|
+
}
|
|
48
|
+
export interface SearchResult {
|
|
49
|
+
title: string;
|
|
50
|
+
link: string;
|
|
51
|
+
snippet: string;
|
|
52
|
+
content?: string;
|
|
53
|
+
[key: string]: unknown;
|
|
54
|
+
}
|
|
55
|
+
export interface SearchResponse {
|
|
56
|
+
searchParameters: SearchParameters;
|
|
57
|
+
results: SearchResult[];
|
|
58
|
+
images?: string[];
|
|
59
|
+
}
|
|
60
|
+
export interface NewsResponse {
|
|
61
|
+
searchParameters: NewsParameters;
|
|
62
|
+
results: SearchResult[];
|
|
63
|
+
images?: string[];
|
|
64
|
+
}
|
|
65
|
+
export interface BatchItem<T> {
|
|
66
|
+
success: boolean;
|
|
67
|
+
data?: T;
|
|
68
|
+
error?: {
|
|
69
|
+
message: string;
|
|
70
|
+
statusCode: number;
|
|
71
|
+
};
|
|
72
|
+
cost: number;
|
|
73
|
+
}
|
|
74
|
+
export interface BatchSummary {
|
|
75
|
+
total: number;
|
|
76
|
+
successful: number;
|
|
77
|
+
failed: number;
|
|
78
|
+
totalCost: number;
|
|
79
|
+
}
|
|
80
|
+
export interface BatchResponse<T> {
|
|
81
|
+
results: BatchItem<T>[];
|
|
82
|
+
summary: BatchSummary;
|
|
83
|
+
}
|
|
84
|
+
export interface CrawlOptions {
|
|
85
|
+
enableFallback?: boolean;
|
|
86
|
+
}
|
|
87
|
+
export interface CrawlRequest extends CrawlOptions {
|
|
88
|
+
url: string;
|
|
89
|
+
}
|
|
90
|
+
export interface CrawlResult {
|
|
91
|
+
title: string;
|
|
92
|
+
link: string;
|
|
93
|
+
content: string;
|
|
94
|
+
metadata?: Record<string, unknown>;
|
|
95
|
+
[key: string]: unknown;
|
|
96
|
+
}
|
|
97
|
+
export interface CrawlResponse {
|
|
98
|
+
crawlParameters: {
|
|
99
|
+
url: string;
|
|
100
|
+
};
|
|
101
|
+
results: CrawlResult;
|
|
102
|
+
}
|
|
103
|
+
export interface SitemapOptions {
|
|
104
|
+
type?: 'sitemap' | 'all';
|
|
105
|
+
}
|
|
106
|
+
export interface SitemapResponse {
|
|
107
|
+
links: string[];
|
|
108
|
+
}
|
|
109
|
+
export interface TrendingOptions {
|
|
110
|
+
maxResults?: number;
|
|
111
|
+
}
|
|
112
|
+
export interface TrendingResult {
|
|
113
|
+
title: string;
|
|
114
|
+
url: string;
|
|
115
|
+
description?: string | null;
|
|
116
|
+
}
|
|
117
|
+
export interface TrendingResponse {
|
|
118
|
+
trendingParameters: {
|
|
119
|
+
search_service: string;
|
|
120
|
+
max_results?: number;
|
|
121
|
+
};
|
|
122
|
+
results: TrendingResult[];
|
|
123
|
+
}
|
|
124
|
+
export interface ExtractOptions {
|
|
125
|
+
prompt?: string;
|
|
126
|
+
responseFormat?: Record<string, JsonValue>;
|
|
127
|
+
}
|
|
128
|
+
export interface ExtractResponse<T = JsonValue> {
|
|
129
|
+
success: true;
|
|
130
|
+
extractParameters: {
|
|
131
|
+
url: string;
|
|
132
|
+
};
|
|
133
|
+
results: T;
|
|
134
|
+
}
|
|
135
|
+
export interface DeepcrawlOptions {
|
|
136
|
+
type?: 'sitemap' | 'all';
|
|
137
|
+
}
|
|
138
|
+
export interface DeepcrawlAcceptedResponse {
|
|
139
|
+
taskId: string;
|
|
140
|
+
status: 'queued' | string;
|
|
141
|
+
}
|
|
142
|
+
export type DeepcrawlStatus = 'queued' | 'waiting' | 'processing' | 'completed' | 'failed' | 'not_found';
|
|
143
|
+
export interface DeepcrawlStatusResponse {
|
|
144
|
+
taskId: string;
|
|
145
|
+
status?: DeepcrawlStatus | string;
|
|
146
|
+
success?: boolean;
|
|
147
|
+
message?: string;
|
|
148
|
+
error?: string | null;
|
|
149
|
+
r2Key?: string;
|
|
150
|
+
zipUrl?: string | null;
|
|
151
|
+
[key: string]: unknown;
|
|
152
|
+
}
|
|
153
|
+
export interface WaitForDeepcrawlOptions {
|
|
154
|
+
pollIntervalMs?: number;
|
|
155
|
+
timeoutMs?: number;
|
|
156
|
+
signal?: AbortSignal;
|
|
157
|
+
}
|
|
158
|
+
export interface UsageResponse {
|
|
159
|
+
usage: number;
|
|
160
|
+
user_id: string | null;
|
|
161
|
+
credential_type: 'api_key' | 'oauth' | string;
|
|
162
|
+
client_id: string | null;
|
|
163
|
+
}
|
|
164
|
+
export interface HealthResponse {
|
|
165
|
+
status: string;
|
|
166
|
+
timestamp?: string;
|
|
167
|
+
version?: string;
|
|
168
|
+
}
|
|
169
|
+
export interface RequestOptions {
|
|
170
|
+
headers?: Record<string, string>;
|
|
171
|
+
maxRetries?: number;
|
|
172
|
+
signal?: AbortSignal;
|
|
173
|
+
timeoutMs?: number;
|
|
174
|
+
}
|
|
175
|
+
export interface Search1APIOptions {
|
|
176
|
+
apiKey?: string;
|
|
177
|
+
baseUrl?: string;
|
|
178
|
+
fetch?: typeof fetch;
|
|
179
|
+
headers?: Record<string, string>;
|
|
180
|
+
maxRetries?: number;
|
|
181
|
+
retryDelayMs?: number;
|
|
182
|
+
timeoutMs?: number;
|
|
183
|
+
}
|
|
184
|
+
export interface ApiErrorBody {
|
|
185
|
+
ok?: false;
|
|
186
|
+
error?: string;
|
|
187
|
+
message?: string;
|
|
188
|
+
errors?: Array<{
|
|
189
|
+
field?: string;
|
|
190
|
+
message: string;
|
|
191
|
+
code?: string;
|
|
192
|
+
}>;
|
|
193
|
+
type?: string;
|
|
194
|
+
title?: string;
|
|
195
|
+
status?: number;
|
|
196
|
+
detail?: string;
|
|
197
|
+
[key: string]: unknown;
|
|
198
|
+
}
|
|
199
|
+
//# sourceMappingURL=types.d.ts.map
|