205 lines
7.4 KiB
TypeScript
205 lines
7.4 KiB
TypeScript
import type { key_val } from '$lib/ae_stores';
|
|
|
|
export let temp_get_blob_percent_completed = 0;
|
|
export let get_blob_percent_completed = temp_get_blob_percent_completed;
|
|
|
|
export let temp_get_object_percent_completed = 0;
|
|
export let get_object_percent_completed = temp_get_object_percent_completed;
|
|
|
|
export let get_object = async function get_object(
|
|
{
|
|
api_cfg = null,
|
|
endpoint = '',
|
|
headers = {},
|
|
params = {},
|
|
data = {},
|
|
timeout = 60000,
|
|
// return_meta = false,
|
|
return_blob = false,
|
|
filename = '',
|
|
auto_download = false,
|
|
as_list = false, // Is this still really needed?
|
|
// The task_id value should be a random string that is unique to the task. This is used to identify the task in the message event.
|
|
task_id = crypto.randomUUID(),
|
|
log_lvl = 0,
|
|
retry_count = 5 // Number of retry attempts
|
|
}: {
|
|
api_cfg: any,
|
|
endpoint: string,
|
|
headers?: any,
|
|
params?: any,
|
|
data?: any,
|
|
timeout?: number,
|
|
// return_meta?: boolean,
|
|
return_blob?: boolean,
|
|
filename?: null | string,
|
|
auto_download?: boolean,
|
|
as_list?: boolean,
|
|
task_id?: string,
|
|
log_lvl?: number,
|
|
retry_count?: number
|
|
}
|
|
) {
|
|
if (log_lvl) {
|
|
console.log(`*** get_object() *** Endpoint: ${endpoint} AE Task ID: ${task_id}`);
|
|
console.log('Params:', params);
|
|
if (log_lvl > 1) {
|
|
console.log('Data:', data);
|
|
}
|
|
}
|
|
|
|
if (!api_cfg) {
|
|
console.log('No API Config was provided. Returning false.');
|
|
return false;
|
|
}
|
|
|
|
const url = new URL(endpoint, api_cfg['base_url']);
|
|
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
|
|
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
|
|
// Remove a header parameter if it is set to null
|
|
if (api_cfg['headers'].hasOwnProperty('x-no-account-id') && api_cfg['headers']['x-no-account-id'] === null) {
|
|
delete api_cfg['headers']['x-no-account-id'];
|
|
}
|
|
|
|
// Clean the headers
|
|
let headers_cleaned: key_val = {};
|
|
for (const prop in headers) {
|
|
let prop_cleaned = prop.replaceAll('_', '-');
|
|
if (typeof headers[prop] != 'string') {
|
|
headers[prop] = JSON.stringify(headers[prop]);
|
|
}
|
|
headers_cleaned[prop_cleaned] = headers[prop];
|
|
if (log_lvl > 1) {
|
|
console.log(`${prop_cleaned}: ${headers_cleaned[prop_cleaned]}`);
|
|
}
|
|
}
|
|
headers = headers_cleaned;
|
|
if (log_lvl > 1) {
|
|
console.log('All headers cleaned:', headers);
|
|
}
|
|
|
|
const fetchOptions: RequestInit = {
|
|
method: 'GET',
|
|
headers: {
|
|
...api_cfg['headers'],
|
|
...headers
|
|
},
|
|
signal: controller.signal
|
|
};
|
|
|
|
if (log_lvl > 1) {
|
|
console.log('Fetch options:', fetchOptions);
|
|
}
|
|
|
|
for (let attempt = 1; attempt <= retry_count; attempt++) {
|
|
try {
|
|
const response = await fetch(url.toString(), fetchOptions)
|
|
.catch(function (error) {
|
|
console.log('API GET Object *fetch* request was aborted or failed in an unexpected way.', error);
|
|
});
|
|
clearTimeout(timeoutId);
|
|
|
|
if (!response) {
|
|
if (log_lvl > 1) {
|
|
console.log('API GET Object: Something went wrong with *fetch* request. Returning false? Throwing an error!');
|
|
}
|
|
throw new Error(`HTTP fetch request was aborted or failed in an unexpected way! URL = ${url.toString()}`); // This will allow it to retry
|
|
// return false; // This will stop the retries
|
|
}
|
|
|
|
if (log_lvl) {
|
|
console.log(`Response: status=${response.status} statusText=${response.statusText} url=${response.url} attempt=${attempt}`);
|
|
}
|
|
if (log_lvl > 1) {
|
|
console.log('Response:', response);
|
|
}
|
|
|
|
if (!response.ok) {
|
|
if (response.status === 404) {
|
|
if (log_lvl) {
|
|
console.log('The response was a 404 not found "error". Returning null.');
|
|
}
|
|
return null;
|
|
}
|
|
console.log('The response was not ok. Throwing an error!');
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
if (!return_blob) {
|
|
const json = await response.json();
|
|
if (log_lvl > 1) {
|
|
console.log('Response JSON:', json);
|
|
}
|
|
if (!Array.isArray(json.data) && as_list) {
|
|
return [json.data];
|
|
}
|
|
return json.data || json;
|
|
} else {
|
|
const reader = response.body?.getReader();
|
|
const contentLength = +response.headers.get('Content-Length')!;
|
|
let receivedLength = 0;
|
|
const chunks = [];
|
|
|
|
while (true) {
|
|
const { done, value } = await reader!.read();
|
|
if (done) break;
|
|
chunks.push(value);
|
|
receivedLength += value.length;
|
|
|
|
const percent_completed = Math.round((receivedLength * 100) / contentLength);
|
|
if (log_lvl > 1) {
|
|
console.log('GET Blob Progress:', percent_completed, 'Total:', contentLength, 'Loaded:', receivedLength, 'Percent Completed', percent_completed);
|
|
}
|
|
|
|
temp_get_blob_percent_completed = percent_completed;
|
|
|
|
try {
|
|
if (typeof window !== 'undefined') {
|
|
window.postMessage({
|
|
type: 'api_download_blob',
|
|
status: 'downloading',
|
|
task_id: task_id,
|
|
endpoint: endpoint,
|
|
filename: filename,
|
|
size_total: contentLength,
|
|
size_loaded: receivedLength,
|
|
percent_completed: percent_completed
|
|
}, '*');
|
|
}
|
|
} catch (e) {
|
|
console.error('Error posting message:', e);
|
|
}
|
|
}
|
|
|
|
const blob = new Blob(chunks);
|
|
if (auto_download) {
|
|
const downloadUrl = window.URL.createObjectURL(blob);
|
|
const link = document.createElement('a');
|
|
link.href = downloadUrl;
|
|
link.setAttribute('download', filename || 'download');
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
link.remove();
|
|
return true;
|
|
} else {
|
|
return blob;
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.log(`API GET object request *fetch* error on attempt ${attempt}:`, error);
|
|
|
|
if (attempt === retry_count) {
|
|
console.log('Max retry attempts reached. Returning false.');
|
|
return false;
|
|
}
|
|
|
|
// Log retry information
|
|
if (log_lvl) {
|
|
console.log(`Retrying... (${attempt}/${retry_count})`);
|
|
}
|
|
}
|
|
}
|
|
}; |