@translated/lara
Version:
Official Lara SDK for JavaScript and Node.js
230 lines (229 loc) • 8.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BrowserClient = exports.BrowserLaraClient = void 0;
const errors_1 = require("../../errors");
const client_1 = require("./client");
function hasDefaultPort(port, secure) {
return (port === 80 && !secure) || (port === 443 && secure);
}
/** @internal */
class BrowserLaraClient extends client_1.LaraClient {
constructor(baseUrl, auth, _keepAlive, timeout) {
super(auth);
let url = `${baseUrl.secure ? "https" : "http"}://${baseUrl.hostname}`;
if (!hasDefaultPort(baseUrl.port, baseUrl.secure))
url += `:${baseUrl.port}`;
this.baseUrl = url;
this.timeout = timeout;
}
async send(method, path, headers, body, streamResponse) {
var _a;
let requestBody;
if (body) {
if (headers["Content-Type"] === "multipart/form-data") {
delete headers["Content-Type"]; // browser will set it automatically
const formBody = new FormData();
for (const [key, value] of Object.entries(body)) {
if (!value)
continue;
if (Array.isArray(value)) {
for (const v of value)
formBody.append(key, v);
}
else {
formBody.append(key, value);
}
}
requestBody = formBody;
}
else {
requestBody = JSON.stringify(body, undefined, 0);
}
}
const signal = this.timeout && this.timeout > 0 ? AbortSignal.timeout(this.timeout) : undefined;
try {
const response = await fetch(this.baseUrl + path, {
headers,
method,
body: requestBody,
signal
});
if (streamResponse && response.status >= 200 && response.status < 300) {
return {
statusCode: response.status,
body: response.body,
headers: Object.fromEntries(response.headers)
};
}
if ((_a = response.headers.get("Content-Type")) === null || _a === void 0 ? void 0 : _a.includes("text/csv")) {
return {
statusCode: response.status,
body: {
content: await response.text()
},
headers: Object.fromEntries(response.headers)
};
}
return {
statusCode: response.status,
body: await response.json(),
headers: Object.fromEntries(response.headers)
};
}
catch (err) {
if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
throw new errors_1.TimeoutError(`Request timed out after ${this.timeout}ms`);
}
throw err;
}
}
async *sendAndGetStream(method, path, headers, body) {
let requestBody;
if (body) {
if (headers["Content-Type"] === "multipart/form-data") {
delete headers["Content-Type"]; // browser will set it automatically
const formBody = new FormData();
for (const [key, value] of Object.entries(body)) {
if (!value)
continue;
if (Array.isArray(value)) {
for (const v of value)
formBody.append(key, v);
}
else {
formBody.append(key, value);
}
}
requestBody = formBody;
}
else {
requestBody = JSON.stringify(body, undefined, 0);
}
}
const signal = this.timeout && this.timeout > 0 ? AbortSignal.timeout(this.timeout) : undefined;
let response;
try {
response = await fetch(this.baseUrl + path, {
headers,
method,
body: requestBody,
signal
});
}
catch (err) {
if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
throw new errors_1.TimeoutError(`Request timed out after ${this.timeout}ms`);
}
throw err;
}
if (!response.body) {
throw new Error("Response body is not available for streaming");
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
try {
while (true) {
let readResult;
try {
readResult = await reader.read();
}
catch (err) {
if (err instanceof Error && (err.name === "AbortError" || err.name === "TimeoutError")) {
throw new errors_1.TimeoutError(`Request timed out after ${this.timeout}ms`);
}
throw err;
}
const { done, value } = readResult;
if (done) {
// Process any remaining data in buffer
if (buffer.trim()) {
try {
const json = JSON.parse(buffer);
yield {
statusCode: json.status || response.status,
body: json.data || json,
headers: Object.fromEntries(response.headers)
};
}
catch (_e) {
// Skip invalid JSON
}
}
break;
}
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop() || ""; // Keep incomplete line in buffer
for (const line of lines) {
if (line.trim()) {
try {
const json = JSON.parse(line);
yield {
statusCode: json.status || response.status,
body: json.data || json,
headers: Object.fromEntries(response.headers)
};
}
catch (_e) {
// Skip invalid JSON lines
}
}
}
}
}
finally {
reader.releaseLock();
}
}
wrapMultiPartFile(file) {
if (file instanceof File)
return file;
throw new TypeError(`Invalid file input in the browser. Expected an instance of File but received ${typeof file}.`);
}
}
exports.BrowserLaraClient = BrowserLaraClient;
// biome-ignore lint/complexity/noStaticOnlyClass: used as a namespace for HTTP client methods
class BrowserClient {
static async get(url, headers) {
return BrowserClient.send("GET", url, headers);
}
static async send(method, url, headers, body) {
var _a;
let requestBody;
if (body) {
if (headers && headers["Content-Type"] === "multipart/form-data") {
delete headers["Content-Type"]; // browser will set it automatically
const formBody = new FormData();
for (const [key, value] of Object.entries(body)) {
if (!value)
continue;
if (Array.isArray(value)) {
for (const v of value)
formBody.append(key, v);
}
else {
formBody.append(key, value);
}
}
requestBody = formBody;
}
else {
requestBody = JSON.stringify(body, undefined, 0);
}
}
const response = await fetch(url, {
headers,
method,
body: requestBody
});
return {
statusCode: response.status,
headers: Object.fromEntries(response.headers),
body: ((_a = response.headers.get("Content-Type")) === null || _a === void 0 ? void 0 : _a.includes("application/json"))
? await response.json()
: await response.text()
};
}
}
exports.BrowserClient = BrowserClient;