@openserp/sdk 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/README.md +268 -0
- package/dist/generated/oss.cjs +19 -0
- package/dist/generated/oss.cjs.map +1 -0
- package/dist/generated/oss.d.cts +1587 -0
- package/dist/generated/oss.d.ts +1587 -0
- package/dist/generated/oss.js +1 -0
- package/dist/generated/oss.js.map +1 -0
- package/dist/index.cjs +453 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +202 -0
- package/dist/index.d.ts +202 -0
- package/dist/index.js +415 -0
- package/dist/index.js.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=oss.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
CLOUD_BASE_URL: () => CLOUD_BASE_URL,
|
|
24
|
+
CaptchaError: () => CaptchaError,
|
|
25
|
+
CloudOnlyError: () => CloudOnlyError,
|
|
26
|
+
OSS_BASE_URL: () => OSS_BASE_URL,
|
|
27
|
+
OpenSERP: () => OpenSERP,
|
|
28
|
+
OssOnlyError: () => OssOnlyError,
|
|
29
|
+
RateLimitError: () => RateLimitError,
|
|
30
|
+
SERPError: () => SERPError,
|
|
31
|
+
TimeoutError: () => TimeoutError,
|
|
32
|
+
inferBackend: () => inferBackend,
|
|
33
|
+
normalizeBaseUrl: () => normalizeBaseUrl,
|
|
34
|
+
resolveBaseUrl: () => resolveBaseUrl
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/backend.ts
|
|
39
|
+
var OSS_BASE_URL = "http://localhost:7000";
|
|
40
|
+
var CLOUD_BASE_URL = "https://api.openserp.org/v1";
|
|
41
|
+
function normalizeBaseUrl(baseUrl) {
|
|
42
|
+
return baseUrl.replace(/\/+$/, "");
|
|
43
|
+
}
|
|
44
|
+
function resolveBaseUrl(config) {
|
|
45
|
+
if (config.baseUrl) {
|
|
46
|
+
return normalizeBaseUrl(config.baseUrl);
|
|
47
|
+
}
|
|
48
|
+
if (config.apiKey) {
|
|
49
|
+
return CLOUD_BASE_URL;
|
|
50
|
+
}
|
|
51
|
+
return OSS_BASE_URL;
|
|
52
|
+
}
|
|
53
|
+
function inferBackend(config) {
|
|
54
|
+
if (config.backend) {
|
|
55
|
+
return config.backend;
|
|
56
|
+
}
|
|
57
|
+
if (config.baseUrl) {
|
|
58
|
+
try {
|
|
59
|
+
if (new URL(config.baseUrl).hostname === "api.openserp.org") {
|
|
60
|
+
return "cloud";
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
if (config.baseUrl.includes("api.openserp.org")) {
|
|
64
|
+
return "cloud";
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (config.apiKey) {
|
|
69
|
+
return "cloud";
|
|
70
|
+
}
|
|
71
|
+
return "oss";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/errors.ts
|
|
75
|
+
var SERPError = class extends Error {
|
|
76
|
+
status;
|
|
77
|
+
code;
|
|
78
|
+
reason;
|
|
79
|
+
requestId;
|
|
80
|
+
meta;
|
|
81
|
+
response;
|
|
82
|
+
constructor(message, options = {}) {
|
|
83
|
+
super(message, { cause: options.cause });
|
|
84
|
+
this.name = "SERPError";
|
|
85
|
+
this.status = options.status ?? 0;
|
|
86
|
+
this.code = options.code;
|
|
87
|
+
this.reason = options.reason;
|
|
88
|
+
this.requestId = options.requestId;
|
|
89
|
+
this.meta = options.meta;
|
|
90
|
+
this.response = options.response;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
var RateLimitError = class extends SERPError {
|
|
94
|
+
constructor(message, options = {}) {
|
|
95
|
+
super(message, options);
|
|
96
|
+
this.name = "RateLimitError";
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
var CaptchaError = class extends SERPError {
|
|
100
|
+
constructor(message, options = {}) {
|
|
101
|
+
super(message, options);
|
|
102
|
+
this.name = "CaptchaError";
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
var CloudOnlyError = class extends SERPError {
|
|
106
|
+
constructor(method) {
|
|
107
|
+
super(`${method} is only available against OpenSERP Cloud. Configure apiKey/baseUrl for https://api.openserp.org/v1 or set client.config.backend = "cloud".`);
|
|
108
|
+
this.name = "CloudOnlyError";
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var OssOnlyError = class extends SERPError {
|
|
112
|
+
constructor(method) {
|
|
113
|
+
super(`${method} is only available against a self-hosted OpenSERP server. Configure baseUrl for your OSS server or set client.config.backend = "oss".`);
|
|
114
|
+
this.name = "OssOnlyError";
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
var TimeoutError = class extends SERPError {
|
|
118
|
+
constructor(timeoutMs, cause) {
|
|
119
|
+
super(`OpenSERP request timed out after ${timeoutMs}ms`, {
|
|
120
|
+
code: "request_timeout",
|
|
121
|
+
cause
|
|
122
|
+
});
|
|
123
|
+
this.name = "TimeoutError";
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
function errorFromResponse(status, body, requestId) {
|
|
127
|
+
const data = isErrorResponse(body) ? body : void 0;
|
|
128
|
+
const code = data?.error;
|
|
129
|
+
const message = data?.message ?? `OpenSERP request failed with status ${status}`;
|
|
130
|
+
const options = {
|
|
131
|
+
status,
|
|
132
|
+
code,
|
|
133
|
+
reason: data?.reason,
|
|
134
|
+
requestId: data?.request_id ?? requestId,
|
|
135
|
+
meta: data?.meta,
|
|
136
|
+
response: body
|
|
137
|
+
};
|
|
138
|
+
if (status === 429 || code === "rate_limited") {
|
|
139
|
+
return new RateLimitError(message, options);
|
|
140
|
+
}
|
|
141
|
+
if (code === "captcha_detected") {
|
|
142
|
+
return new CaptchaError(message, options);
|
|
143
|
+
}
|
|
144
|
+
return new SERPError(message, options);
|
|
145
|
+
}
|
|
146
|
+
function isErrorResponse(body) {
|
|
147
|
+
return typeof body === "object" && body !== null && "error" in body;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// src/request.ts
|
|
151
|
+
async function request(context, options) {
|
|
152
|
+
let attempt = 0;
|
|
153
|
+
for (; ; ) {
|
|
154
|
+
try {
|
|
155
|
+
return await requestOnce(context, options);
|
|
156
|
+
} catch (err) {
|
|
157
|
+
const shouldRetry = await context.config.retry?.(err, attempt);
|
|
158
|
+
if (!shouldRetry) {
|
|
159
|
+
throw err;
|
|
160
|
+
}
|
|
161
|
+
attempt += 1;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
async function requestOnce({ baseUrl, config, setLastResponse }, options) {
|
|
166
|
+
const fetchImpl = config.fetch ?? globalThis.fetch;
|
|
167
|
+
if (!fetchImpl) {
|
|
168
|
+
throw new TypeError("OpenSERP SDK requires a fetch implementation.");
|
|
169
|
+
}
|
|
170
|
+
const url = new URL(`${baseUrl}${options.path}`);
|
|
171
|
+
appendQuery(url, options.query);
|
|
172
|
+
const headers = new Headers(config.headers);
|
|
173
|
+
if (config.apiKey) {
|
|
174
|
+
headers.set("Authorization", `Bearer ${config.apiKey}`);
|
|
175
|
+
}
|
|
176
|
+
for (const [key, value] of new Headers(options.headers)) {
|
|
177
|
+
headers.set(key, value);
|
|
178
|
+
}
|
|
179
|
+
const timeoutMs = config.timeoutMs ?? 3e4;
|
|
180
|
+
const controller = new AbortController();
|
|
181
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
182
|
+
let response;
|
|
183
|
+
try {
|
|
184
|
+
const init = {
|
|
185
|
+
method: options.method ?? "GET",
|
|
186
|
+
headers,
|
|
187
|
+
signal: controller.signal
|
|
188
|
+
};
|
|
189
|
+
if (options.body !== void 0) {
|
|
190
|
+
init.body = options.body;
|
|
191
|
+
}
|
|
192
|
+
response = await fetchImpl(url, init);
|
|
193
|
+
} catch (err) {
|
|
194
|
+
if (isAbortError(err)) {
|
|
195
|
+
throw new TimeoutError(timeoutMs, err);
|
|
196
|
+
}
|
|
197
|
+
throw err;
|
|
198
|
+
} finally {
|
|
199
|
+
clearTimeout(timer);
|
|
200
|
+
}
|
|
201
|
+
setLastResponse(readLastResponse(response));
|
|
202
|
+
const body = await readBody(response, options.format);
|
|
203
|
+
if (!response.ok) {
|
|
204
|
+
throw errorFromResponse(response.status, body, response.headers.get("x-request-id") ?? void 0);
|
|
205
|
+
}
|
|
206
|
+
return body;
|
|
207
|
+
}
|
|
208
|
+
function appendQuery(url, query) {
|
|
209
|
+
if (!query) {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
for (const [key, value] of Object.entries(query)) {
|
|
213
|
+
if (value === void 0 || value === null) {
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
const encoded = Array.isArray(value) ? value.join(",") : String(value);
|
|
217
|
+
url.searchParams.set(key, encoded);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async function readBody(response, format) {
|
|
221
|
+
if (response.status === 204) {
|
|
222
|
+
return void 0;
|
|
223
|
+
}
|
|
224
|
+
if (format && format !== "json") {
|
|
225
|
+
return response.text();
|
|
226
|
+
}
|
|
227
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
228
|
+
if (contentType.includes("application/json")) {
|
|
229
|
+
return response.json();
|
|
230
|
+
}
|
|
231
|
+
const text = await response.text();
|
|
232
|
+
if (!text) {
|
|
233
|
+
return void 0;
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
return JSON.parse(text);
|
|
237
|
+
} catch {
|
|
238
|
+
return text;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
function readLastResponse(response) {
|
|
242
|
+
const credits = {
|
|
243
|
+
used: numberHeader(response.headers, "x-credits-used"),
|
|
244
|
+
remaining: numberHeader(response.headers, "x-credits-remaining")
|
|
245
|
+
};
|
|
246
|
+
const hasCredits = credits.used !== void 0 || credits.remaining !== void 0;
|
|
247
|
+
return {
|
|
248
|
+
status: response.status,
|
|
249
|
+
requestId: response.headers.get("x-request-id") ?? void 0,
|
|
250
|
+
credits: hasCredits ? credits : void 0,
|
|
251
|
+
engineUsed: response.headers.get("x-engine-used") ?? void 0,
|
|
252
|
+
fallbackEngine: response.headers.get("x-fallback-engine") ?? void 0,
|
|
253
|
+
cache: response.headers.get("x-cache") ?? void 0,
|
|
254
|
+
proxyMode: response.headers.get("x-proxy-mode") ?? void 0,
|
|
255
|
+
proxyTag: response.headers.get("x-proxy-tag") ?? void 0,
|
|
256
|
+
proxyUsed: response.headers.get("x-proxy-used") ?? void 0,
|
|
257
|
+
networkBytes: numberHeader(response.headers, "x-network-bytes"),
|
|
258
|
+
browserProfileId: response.headers.get("x-browser-profile-id") ?? void 0,
|
|
259
|
+
headers: response.headers
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function numberHeader(headers, name) {
|
|
263
|
+
const value = headers.get(name);
|
|
264
|
+
if (value === null || value === "") {
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
267
|
+
const parsed = Number(value);
|
|
268
|
+
return Number.isFinite(parsed) ? parsed : void 0;
|
|
269
|
+
}
|
|
270
|
+
function isAbortError(err) {
|
|
271
|
+
return err instanceof DOMException && err.name === "AbortError";
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/client.ts
|
|
275
|
+
var OpenSERP = class {
|
|
276
|
+
config;
|
|
277
|
+
lastResponse;
|
|
278
|
+
constructor(config = {}) {
|
|
279
|
+
this.config = { ...config };
|
|
280
|
+
}
|
|
281
|
+
get backend() {
|
|
282
|
+
return inferBackend(this.config);
|
|
283
|
+
}
|
|
284
|
+
get baseUrl() {
|
|
285
|
+
return resolveBaseUrl(this.config);
|
|
286
|
+
}
|
|
287
|
+
search(params) {
|
|
288
|
+
const { engine, format, ...query } = params;
|
|
289
|
+
return this.get(`/${engine}/search`, query, format);
|
|
290
|
+
}
|
|
291
|
+
image(params) {
|
|
292
|
+
const { engine, format, ...query } = params;
|
|
293
|
+
return this.get(`/${engine}/image`, query, format);
|
|
294
|
+
}
|
|
295
|
+
megaSearch(params) {
|
|
296
|
+
const { format, ...query } = params;
|
|
297
|
+
return this.get("/mega/search", query, format);
|
|
298
|
+
}
|
|
299
|
+
fastSearch(params) {
|
|
300
|
+
return this.megaSearch({ ...params, mode: "fast" });
|
|
301
|
+
}
|
|
302
|
+
anySearch(params) {
|
|
303
|
+
return this.megaSearch({ ...params, mode: "any" });
|
|
304
|
+
}
|
|
305
|
+
megaImage(params) {
|
|
306
|
+
const { format, ...query } = params;
|
|
307
|
+
return this.get("/mega/image", query, format);
|
|
308
|
+
}
|
|
309
|
+
fastImage(params) {
|
|
310
|
+
return this.megaImage({ ...params, mode: "fast" });
|
|
311
|
+
}
|
|
312
|
+
anyImage(params) {
|
|
313
|
+
return this.megaImage({ ...params, mode: "any" });
|
|
314
|
+
}
|
|
315
|
+
parseGoogle(params) {
|
|
316
|
+
this.assertOss("parseGoogle");
|
|
317
|
+
return this.parse("/google/parse", params);
|
|
318
|
+
}
|
|
319
|
+
parseBing(params) {
|
|
320
|
+
this.assertOss("parseBing");
|
|
321
|
+
return this.parse("/bing/parse", params);
|
|
322
|
+
}
|
|
323
|
+
health() {
|
|
324
|
+
this.assertOss("health");
|
|
325
|
+
return this.get("/health");
|
|
326
|
+
}
|
|
327
|
+
ready() {
|
|
328
|
+
this.assertOss("ready");
|
|
329
|
+
return this.get("/ready");
|
|
330
|
+
}
|
|
331
|
+
stats() {
|
|
332
|
+
this.assertOss("stats");
|
|
333
|
+
return this.get("/stats");
|
|
334
|
+
}
|
|
335
|
+
cacheStats() {
|
|
336
|
+
this.assertOss("cacheStats");
|
|
337
|
+
return this.get("/stats/cache");
|
|
338
|
+
}
|
|
339
|
+
proxyStats() {
|
|
340
|
+
this.assertOss("proxyStats");
|
|
341
|
+
return this.get("/stats/proxy");
|
|
342
|
+
}
|
|
343
|
+
circuitBreakerStats() {
|
|
344
|
+
this.assertOss("circuitBreakerStats");
|
|
345
|
+
return this.get("/stats/cb");
|
|
346
|
+
}
|
|
347
|
+
engines() {
|
|
348
|
+
this.assertOss("engines");
|
|
349
|
+
return this.get("/mega/engines");
|
|
350
|
+
}
|
|
351
|
+
me() {
|
|
352
|
+
this.assertCloud("me");
|
|
353
|
+
return this.get("/me");
|
|
354
|
+
}
|
|
355
|
+
pricing() {
|
|
356
|
+
this.assertCloud("pricing");
|
|
357
|
+
return this.get("/pricing");
|
|
358
|
+
}
|
|
359
|
+
enginesStatus() {
|
|
360
|
+
this.assertCloud("enginesStatus");
|
|
361
|
+
return this.get("/engines/status");
|
|
362
|
+
}
|
|
363
|
+
enginesCapabilities() {
|
|
364
|
+
this.assertCloud("enginesCapabilities");
|
|
365
|
+
return this.get("/engines/capabilities");
|
|
366
|
+
}
|
|
367
|
+
parse(path, params) {
|
|
368
|
+
return request(this.requestContext(), {
|
|
369
|
+
method: "POST",
|
|
370
|
+
path,
|
|
371
|
+
query: params.format ? { format: params.format } : void 0,
|
|
372
|
+
headers: {
|
|
373
|
+
"Content-Type": "text/html; charset=utf-8"
|
|
374
|
+
},
|
|
375
|
+
body: params.html,
|
|
376
|
+
format: params.format
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
get(path, query, format) {
|
|
380
|
+
const { query: cleanQuery, headers } = splitQueryAndHeaders({
|
|
381
|
+
...query,
|
|
382
|
+
format
|
|
383
|
+
});
|
|
384
|
+
return request(this.requestContext(), {
|
|
385
|
+
path,
|
|
386
|
+
query: cleanQuery,
|
|
387
|
+
headers,
|
|
388
|
+
format
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
requestContext() {
|
|
392
|
+
return {
|
|
393
|
+
baseUrl: this.baseUrl,
|
|
394
|
+
config: this.config,
|
|
395
|
+
setLastResponse: (response) => {
|
|
396
|
+
this.lastResponse = response;
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
assertCloud(method) {
|
|
401
|
+
if (this.backend !== "cloud") {
|
|
402
|
+
throw new CloudOnlyError(method);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
assertOss(method) {
|
|
406
|
+
if (this.backend !== "oss") {
|
|
407
|
+
throw new OssOnlyError(method);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
function splitQueryAndHeaders(query) {
|
|
412
|
+
const {
|
|
413
|
+
useProxy,
|
|
414
|
+
proxyUrl,
|
|
415
|
+
proxyCountry,
|
|
416
|
+
proxyClass,
|
|
417
|
+
proxyProvider,
|
|
418
|
+
proxySessionId,
|
|
419
|
+
tenant,
|
|
420
|
+
...cleanQuery
|
|
421
|
+
} = query;
|
|
422
|
+
const headers = {};
|
|
423
|
+
addHeader(headers, "X-Use-Proxy", useProxy);
|
|
424
|
+
addHeader(headers, "X-Proxy-URL", proxyUrl);
|
|
425
|
+
addHeader(headers, "X-Proxy-Country", proxyCountry);
|
|
426
|
+
addHeader(headers, "X-Proxy-Class", proxyClass);
|
|
427
|
+
addHeader(headers, "X-Proxy-Provider", proxyProvider);
|
|
428
|
+
addHeader(headers, "X-Proxy-Session-ID", proxySessionId);
|
|
429
|
+
addHeader(headers, "X-Tenant", tenant);
|
|
430
|
+
return { query: cleanQuery, headers };
|
|
431
|
+
}
|
|
432
|
+
function addHeader(headers, name, value) {
|
|
433
|
+
if (value === void 0 || value === null) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
headers[name] = Array.isArray(value) ? value.join(",") : String(value);
|
|
437
|
+
}
|
|
438
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
439
|
+
0 && (module.exports = {
|
|
440
|
+
CLOUD_BASE_URL,
|
|
441
|
+
CaptchaError,
|
|
442
|
+
CloudOnlyError,
|
|
443
|
+
OSS_BASE_URL,
|
|
444
|
+
OpenSERP,
|
|
445
|
+
OssOnlyError,
|
|
446
|
+
RateLimitError,
|
|
447
|
+
SERPError,
|
|
448
|
+
TimeoutError,
|
|
449
|
+
inferBackend,
|
|
450
|
+
normalizeBaseUrl,
|
|
451
|
+
resolveBaseUrl
|
|
452
|
+
});
|
|
453
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/backend.ts","../src/errors.ts","../src/request.ts","../src/client.ts"],"sourcesContent":["export { OpenSERP } from \"./client\";\nexport {\n CLOUD_BASE_URL,\n OSS_BASE_URL,\n inferBackend,\n normalizeBaseUrl,\n resolveBaseUrl,\n} from \"./backend\";\nexport {\n CaptchaError,\n CloudOnlyError,\n OssOnlyError,\n RateLimitError,\n SERPError,\n TimeoutError,\n} from \"./errors\";\nexport type {\n Backend,\n CacheStats,\n CircuitBreakerStatsResponse,\n Engine,\n ErrorResponse,\n HealthStatus,\n ImageEnvelope,\n ImageParams,\n LastResponse,\n MegaEnginesResponse,\n MegaImageParams,\n MegaMode,\n MegaSearchEnvelope,\n MegaSearchParams,\n OpenSERPConfig,\n ParseParams,\n ProxyStats,\n ReadinessStatus,\n ResponseFormat,\n SearchEnvelope,\n SearchParams,\n StatsResponse,\n} from \"./types/public\";\nexport type {\n CloudAccount,\n CreditInfo,\n EngineCapability,\n EngineStatus,\n EnginesCapabilities,\n EnginesStatus,\n ModeCapability,\n OverallStatus,\n Price,\n Pricing,\n} from \"./types/cloud\";\n","import type { Backend, OpenSERPConfig } from \"./types/public\";\n\nexport const OSS_BASE_URL = \"http://localhost:7000\";\nexport const CLOUD_BASE_URL = \"https://api.openserp.org/v1\";\n\nexport function normalizeBaseUrl(baseUrl: string): string {\n return baseUrl.replace(/\\/+$/, \"\");\n}\n\nexport function resolveBaseUrl(config: OpenSERPConfig): string {\n if (config.baseUrl) {\n return normalizeBaseUrl(config.baseUrl);\n }\n\n if (config.apiKey) {\n return CLOUD_BASE_URL;\n }\n\n return OSS_BASE_URL;\n}\n\nexport function inferBackend(config: Pick<OpenSERPConfig, \"apiKey\" | \"baseUrl\" | \"backend\">): Backend {\n if (config.backend) {\n return config.backend;\n }\n\n if (config.baseUrl) {\n try {\n if (new URL(config.baseUrl).hostname === \"api.openserp.org\") {\n return \"cloud\";\n }\n } catch {\n if (config.baseUrl.includes(\"api.openserp.org\")) {\n return \"cloud\";\n }\n }\n }\n\n if (config.apiKey) {\n return \"cloud\";\n }\n\n return \"oss\";\n}\n","import type { ErrorResponse } from \"./types/public\";\n\nexport class SERPError extends Error {\n readonly status: number;\n readonly code?: string | undefined;\n readonly reason?: string | undefined;\n readonly requestId?: string | undefined;\n readonly meta?: Record<string, unknown> | undefined;\n readonly response?: ErrorResponse | unknown | undefined;\n\n constructor(message: string, options: {\n status?: number | undefined;\n code?: string | undefined;\n reason?: string | undefined;\n requestId?: string | undefined;\n meta?: Record<string, unknown> | undefined;\n response?: ErrorResponse | unknown | undefined;\n cause?: unknown | undefined;\n } = {}) {\n super(message, { cause: options.cause });\n this.name = \"SERPError\";\n this.status = options.status ?? 0;\n this.code = options.code;\n this.reason = options.reason;\n this.requestId = options.requestId;\n this.meta = options.meta;\n this.response = options.response;\n }\n}\n\nexport class RateLimitError extends SERPError {\n constructor(message: string, options: ConstructorParameters<typeof SERPError>[1] = {}) {\n super(message, options);\n this.name = \"RateLimitError\";\n }\n}\n\nexport class CaptchaError extends SERPError {\n constructor(message: string, options: ConstructorParameters<typeof SERPError>[1] = {}) {\n super(message, options);\n this.name = \"CaptchaError\";\n }\n}\n\nexport class CloudOnlyError extends SERPError {\n constructor(method: string) {\n super(`${method} is only available against OpenSERP Cloud. Configure apiKey/baseUrl for https://api.openserp.org/v1 or set client.config.backend = \"cloud\".`);\n this.name = \"CloudOnlyError\";\n }\n}\n\nexport class OssOnlyError extends SERPError {\n constructor(method: string) {\n super(`${method} is only available against a self-hosted OpenSERP server. Configure baseUrl for your OSS server or set client.config.backend = \"oss\".`);\n this.name = \"OssOnlyError\";\n }\n}\n\nexport class TimeoutError extends SERPError {\n constructor(timeoutMs: number, cause?: unknown) {\n super(`OpenSERP request timed out after ${timeoutMs}ms`, {\n code: \"request_timeout\",\n cause,\n });\n this.name = \"TimeoutError\";\n }\n}\n\nexport function errorFromResponse(status: number, body: unknown, requestId?: string): SERPError {\n const data = isErrorResponse(body) ? body : undefined;\n const code = data?.error;\n const message = data?.message ?? `OpenSERP request failed with status ${status}`;\n const options = {\n status,\n code,\n reason: data?.reason,\n requestId: data?.request_id ?? requestId,\n meta: data?.meta as Record<string, unknown> | undefined,\n response: body,\n };\n\n if (status === 429 || code === \"rate_limited\") {\n return new RateLimitError(message, options);\n }\n\n if (code === \"captcha_detected\") {\n return new CaptchaError(message, options);\n }\n\n return new SERPError(message, options);\n}\n\nfunction isErrorResponse(body: unknown): body is ErrorResponse {\n return typeof body === \"object\" && body !== null && \"error\" in body;\n}\n","import { TimeoutError, errorFromResponse } from \"./errors\";\nimport type { LastResponse, OpenSERPConfig, ResponseFormat } from \"./types/public\";\n\nexport type QueryValue =\n | string\n | number\n | boolean\n | readonly string[]\n | undefined\n | null;\n\nexport interface RequestOptions {\n method?: \"GET\" | \"POST\" | undefined;\n path: string;\n query?: Record<string, QueryValue> | undefined;\n headers?: HeadersInit | undefined;\n body?: BodyInit | null | undefined;\n format?: ResponseFormat | undefined;\n}\n\nexport interface RequestContext {\n baseUrl: string;\n config: OpenSERPConfig;\n setLastResponse(response: LastResponse): void;\n}\n\nexport async function request<T>(\n context: RequestContext,\n options: RequestOptions,\n): Promise<T> {\n let attempt = 0;\n\n for (;;) {\n try {\n return await requestOnce<T>(context, options);\n } catch (err) {\n const shouldRetry = await context.config.retry?.(err, attempt);\n if (!shouldRetry) {\n throw err;\n }\n attempt += 1;\n }\n }\n}\n\nasync function requestOnce<T>(\n { baseUrl, config, setLastResponse }: RequestContext,\n options: RequestOptions,\n): Promise<T> {\n const fetchImpl = config.fetch ?? globalThis.fetch;\n if (!fetchImpl) {\n throw new TypeError(\"OpenSERP SDK requires a fetch implementation.\");\n }\n\n const url = new URL(`${baseUrl}${options.path}`);\n appendQuery(url, options.query);\n\n const headers = new Headers(config.headers);\n if (config.apiKey) {\n headers.set(\"Authorization\", `Bearer ${config.apiKey}`);\n }\n for (const [key, value] of new Headers(options.headers)) {\n headers.set(key, value);\n }\n\n const timeoutMs = config.timeoutMs ?? 30_000;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let response: Response;\n try {\n const init: RequestInit = {\n method: options.method ?? \"GET\",\n headers,\n signal: controller.signal,\n };\n if (options.body !== undefined) {\n init.body = options.body;\n }\n\n response = await fetchImpl(url, init);\n } catch (err) {\n if (isAbortError(err)) {\n throw new TimeoutError(timeoutMs, err);\n }\n throw err;\n } finally {\n clearTimeout(timer);\n }\n\n setLastResponse(readLastResponse(response));\n\n const body = await readBody(response, options.format);\n if (!response.ok) {\n throw errorFromResponse(response.status, body, response.headers.get(\"x-request-id\") ?? undefined);\n }\n\n return body as T;\n}\n\nfunction appendQuery(url: URL, query: Record<string, QueryValue> | undefined): void {\n if (!query) {\n return;\n }\n\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null) {\n continue;\n }\n const encoded = Array.isArray(value) ? value.join(\",\") : String(value);\n url.searchParams.set(key, encoded);\n }\n}\n\nasync function readBody(response: Response, format?: ResponseFormat): Promise<unknown> {\n if (response.status === 204) {\n return undefined;\n }\n\n if (format && format !== \"json\") {\n return response.text();\n }\n\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n if (contentType.includes(\"application/json\")) {\n return response.json();\n }\n\n const text = await response.text();\n if (!text) {\n return undefined;\n }\n\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\nfunction readLastResponse(response: Response): LastResponse {\n const credits = {\n used: numberHeader(response.headers, \"x-credits-used\"),\n remaining: numberHeader(response.headers, \"x-credits-remaining\"),\n };\n const hasCredits = credits.used !== undefined || credits.remaining !== undefined;\n\n return {\n status: response.status,\n requestId: response.headers.get(\"x-request-id\") ?? undefined,\n credits: hasCredits ? credits : undefined,\n engineUsed: response.headers.get(\"x-engine-used\") ?? undefined,\n fallbackEngine: response.headers.get(\"x-fallback-engine\") ?? undefined,\n cache: response.headers.get(\"x-cache\") ?? undefined,\n proxyMode: response.headers.get(\"x-proxy-mode\") ?? undefined,\n proxyTag: response.headers.get(\"x-proxy-tag\") ?? undefined,\n proxyUsed: response.headers.get(\"x-proxy-used\") ?? undefined,\n networkBytes: numberHeader(response.headers, \"x-network-bytes\"),\n browserProfileId: response.headers.get(\"x-browser-profile-id\") ?? undefined,\n headers: response.headers,\n };\n}\n\nfunction numberHeader(headers: Headers, name: string): number | undefined {\n const value = headers.get(name);\n if (value === null || value === \"\") {\n return undefined;\n }\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : undefined;\n}\n\nfunction isAbortError(err: unknown): boolean {\n return err instanceof DOMException && err.name === \"AbortError\";\n}\n","import { inferBackend, resolveBaseUrl } from \"./backend\";\nimport { CloudOnlyError, OssOnlyError } from \"./errors\";\nimport { request, type QueryValue } from \"./request\";\nimport type {\n CacheStats,\n CircuitBreakerStatsResponse,\n HealthStatus,\n ImageEnvelope,\n ImageParams,\n LastResponse,\n MegaEnginesResponse,\n MegaImageParams,\n MegaSearchEnvelope,\n MegaSearchParams,\n OpenSERPConfig,\n ParseParams,\n ReadinessStatus,\n SearchEnvelope,\n SearchParams,\n StatsResponse,\n ProxyStats,\n} from \"./types/public\";\nimport type {\n CloudAccount,\n EnginesCapabilities,\n EnginesStatus,\n Pricing,\n} from \"./types/cloud\";\n\nexport class OpenSERP {\n readonly config: OpenSERPConfig;\n lastResponse?: LastResponse;\n\n constructor(config: OpenSERPConfig = {}) {\n this.config = { ...config };\n }\n\n get backend() {\n return inferBackend(this.config);\n }\n\n get baseUrl() {\n return resolveBaseUrl(this.config);\n }\n\n search(params: SearchParams): Promise<SearchEnvelope | string> {\n const { engine, format, ...query } = params;\n return this.get<SearchEnvelope | string>(`/${engine}/search`, query, format);\n }\n\n image(params: ImageParams): Promise<ImageEnvelope | string> {\n const { engine, format, ...query } = params;\n return this.get<ImageEnvelope | string>(`/${engine}/image`, query, format);\n }\n\n megaSearch(params: MegaSearchParams): Promise<MegaSearchEnvelope | string> {\n const { format, ...query } = params;\n return this.get<MegaSearchEnvelope | string>(\"/mega/search\", query, format);\n }\n\n fastSearch(params: Omit<MegaSearchParams, \"mode\">): Promise<MegaSearchEnvelope | string> {\n return this.megaSearch({ ...params, mode: \"fast\" });\n }\n\n anySearch(params: Omit<MegaSearchParams, \"mode\">): Promise<MegaSearchEnvelope | string> {\n return this.megaSearch({ ...params, mode: \"any\" });\n }\n\n megaImage(params: MegaImageParams): Promise<ImageEnvelope | string> {\n const { format, ...query } = params;\n return this.get<ImageEnvelope | string>(\"/mega/image\", query, format);\n }\n\n fastImage(params: Omit<MegaImageParams, \"mode\">): Promise<ImageEnvelope | string> {\n return this.megaImage({ ...params, mode: \"fast\" });\n }\n\n anyImage(params: Omit<MegaImageParams, \"mode\">): Promise<ImageEnvelope | string> {\n return this.megaImage({ ...params, mode: \"any\" });\n }\n\n parseGoogle(params: ParseParams): Promise<SearchEnvelope | string> {\n this.assertOss(\"parseGoogle\");\n return this.parse(\"/google/parse\", params);\n }\n\n parseBing(params: ParseParams): Promise<SearchEnvelope | string> {\n this.assertOss(\"parseBing\");\n return this.parse(\"/bing/parse\", params);\n }\n\n health(): Promise<HealthStatus> {\n this.assertOss(\"health\");\n return this.get<HealthStatus>(\"/health\");\n }\n\n ready(): Promise<ReadinessStatus> {\n this.assertOss(\"ready\");\n return this.get<ReadinessStatus>(\"/ready\");\n }\n\n stats(): Promise<StatsResponse> {\n this.assertOss(\"stats\");\n return this.get<StatsResponse>(\"/stats\");\n }\n\n cacheStats(): Promise<CacheStats> {\n this.assertOss(\"cacheStats\");\n return this.get<CacheStats>(\"/stats/cache\");\n }\n\n proxyStats(): Promise<ProxyStats> {\n this.assertOss(\"proxyStats\");\n return this.get<ProxyStats>(\"/stats/proxy\");\n }\n\n circuitBreakerStats(): Promise<CircuitBreakerStatsResponse> {\n this.assertOss(\"circuitBreakerStats\");\n return this.get<CircuitBreakerStatsResponse>(\"/stats/cb\");\n }\n\n engines(): Promise<MegaEnginesResponse> {\n this.assertOss(\"engines\");\n return this.get<MegaEnginesResponse>(\"/mega/engines\");\n }\n\n me(): Promise<CloudAccount> {\n this.assertCloud(\"me\");\n return this.get<CloudAccount>(\"/me\");\n }\n\n pricing(): Promise<Pricing> {\n this.assertCloud(\"pricing\");\n return this.get<Pricing>(\"/pricing\");\n }\n\n enginesStatus(): Promise<EnginesStatus> {\n this.assertCloud(\"enginesStatus\");\n return this.get<EnginesStatus>(\"/engines/status\");\n }\n\n enginesCapabilities(): Promise<EnginesCapabilities> {\n this.assertCloud(\"enginesCapabilities\");\n return this.get<EnginesCapabilities>(\"/engines/capabilities\");\n }\n\n private parse(path: string, params: ParseParams): Promise<SearchEnvelope | string> {\n return request<SearchEnvelope | string>(this.requestContext(), {\n method: \"POST\",\n path,\n query: params.format ? { format: params.format } : undefined,\n headers: {\n \"Content-Type\": \"text/html; charset=utf-8\",\n },\n body: params.html,\n format: params.format,\n });\n }\n\n private get<T>(\n path: string,\n query?: Record<string, QueryValue>,\n format?: SearchParams[\"format\"],\n ): Promise<T> {\n const { query: cleanQuery, headers } = splitQueryAndHeaders({\n ...query,\n format,\n });\n\n return request<T>(this.requestContext(), {\n path,\n query: cleanQuery,\n headers,\n format,\n });\n }\n\n private requestContext() {\n return {\n baseUrl: this.baseUrl,\n config: this.config,\n setLastResponse: (response: LastResponse) => {\n this.lastResponse = response;\n },\n };\n }\n\n private assertCloud(method: string): void {\n if (this.backend !== \"cloud\") {\n throw new CloudOnlyError(method);\n }\n }\n\n private assertOss(method: string): void {\n if (this.backend !== \"oss\") {\n throw new OssOnlyError(method);\n }\n }\n}\n\nfunction splitQueryAndHeaders(query: Record<string, QueryValue>): {\n query: Record<string, QueryValue>;\n headers: HeadersInit;\n} {\n const {\n useProxy,\n proxyUrl,\n proxyCountry,\n proxyClass,\n proxyProvider,\n proxySessionId,\n tenant,\n ...cleanQuery\n } = query;\n const headers: Record<string, string> = {};\n\n addHeader(headers, \"X-Use-Proxy\", useProxy);\n addHeader(headers, \"X-Proxy-URL\", proxyUrl);\n addHeader(headers, \"X-Proxy-Country\", proxyCountry);\n addHeader(headers, \"X-Proxy-Class\", proxyClass);\n addHeader(headers, \"X-Proxy-Provider\", proxyProvider);\n addHeader(headers, \"X-Proxy-Session-ID\", proxySessionId);\n addHeader(headers, \"X-Tenant\", tenant);\n\n return { query: cleanQuery, headers };\n}\n\nfunction addHeader(headers: Record<string, string>, name: string, value: QueryValue): void {\n if (value === undefined || value === null) {\n return;\n }\n headers[name] = Array.isArray(value) ? value.join(\",\") : String(value);\n}\n"],"mappings":"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","names":[]}
|