Getting rid of Axios. Using (Svelte) fetch for get_object()...

This commit is contained in:
Scott Idem
2024-11-20 12:56:11 -05:00
parent e220653f45
commit fd602a46ac
4 changed files with 632 additions and 431 deletions

View File

@@ -178,7 +178,8 @@ export async function get_ae_obj_li_for_obj_id_crud_v2(
// NOTE: The order_by_li variable is in the "headers" because if is a the URL GET params do not handle multiple values very well. Maybe base64 encore in the future or something? Reminder that GET requests should not have a body (no JSON). // NOTE: The order_by_li variable is in the "headers" because if is a the URL GET params do not handle multiple values very well. Maybe base64 encore in the future or something? Reminder that GET requests should not have a body (no JSON).
// NOTE: The order_by_li should be a key value pair of the property/DB field to sort and how to sort (ASC or DESC) // NOTE: The order_by_li should be a key value pair of the property/DB field to sort and how to sort (ASC or DESC)
if (order_by_li) { if (order_by_li) {
headers['order_by_li'] = order_by_li; // headers['order_by_li'] = order_by_li;
headers['order_by_li'] = JSON.stringify(order_by_li);
} }
if (limit >= 0) { if (limit >= 0) {

View File

@@ -1,32 +1,29 @@
import axios from 'axios';
import type { key_val } from '$lib/ae_stores'; import type { key_val } from '$lib/ae_stores';
export let temp_get_blob_percent_completed = 0; export let temp_get_blob_percent_completed = 0;
// export let get_blob_percent_completed = readable(temp_get_blob_percent_completed);
export let get_blob_percent_completed = temp_get_blob_percent_completed; export let get_blob_percent_completed = temp_get_blob_percent_completed;
export let temp_get_object_percent_completed = 0; export let temp_get_object_percent_completed = 0;
// export let get_object_percent_completed = readable(temp_get_object_percent_completed);
export let get_object_percent_completed = temp_get_object_percent_completed; export let get_object_percent_completed = temp_get_object_percent_completed;
// Updated 2024-05-23 // This is now a complete re-write without Axios. This is a simple fetch API call.
// Updated 2024-11-20
export let get_object = async function get_object( export let get_object = async function get_object(
{ {
api_cfg=null, api_cfg = null,
endpoint='', endpoint = '',
headers={}, headers = {},
params={}, params = {},
data={}, data = {},
timeout=60000, timeout = 60000,
return_meta=false, // return_meta = false,
return_blob=false, return_blob = false,
filename='', filename = '',
auto_download=false, auto_download = false,
as_list=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. // 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(), task_id = crypto.randomUUID(),
log_lvl=0 log_lvl = 0
}: { }: {
api_cfg: any, api_cfg: any,
endpoint: string, endpoint: string,
@@ -34,25 +31,20 @@ export let get_object = async function get_object(
params?: any, params?: any,
data?: any, data?: any,
timeout?: number, timeout?: number,
return_meta?: boolean, // return_meta?: boolean,
return_blob?: boolean, return_blob?: boolean,
filename?: null|string, filename?: null | string,
auto_download?: boolean, auto_download?: boolean,
as_list?: boolean, as_list?: boolean,
task_id?: string, task_id?: string,
log_lvl?: number log_lvl?: number
} }
) { ) {
if (log_lvl) { if (log_lvl) {
console.log(`*** get_object() *** Endpoint: ${endpoint} AE Task ID: ${task_id}`); console.log(`*** get_object() *** Endpoint: ${endpoint} AE Task ID: ${task_id}`);
console.log('Params:', params); console.log('Params:', params);
if (log_lvl > 1) { if (log_lvl > 1) {
console.log('Data:', data); console.log('Data:', data);
console.log(`Base URL: ${api_cfg['base_url']}; Timeout: ${timeout}`);
console.log('API Config:', api_cfg);
}
if (log_lvl > 2) {
console.log(`Return Meta: ${return_meta}; Return Blob: ${return_blob}; Filename: ${filename}; Auto Download: ${auto_download}`);
} }
} }
@@ -61,15 +53,15 @@ export let get_object = async function get_object(
return false; return false;
} }
let axios_api = axios.create({ const url = new URL(endpoint, api_cfg['base_url']);
baseURL: api_cfg['base_url'], Object.keys(params).forEach(key => url.searchParams.append(key, params[key]));
timeout: timeout, // in milliseconds; 60000 = 60 seconds
/* other custom settings */ const controller = new AbortController();
}); const timeoutId = setTimeout(() => controller.abort(), timeout);
axios_api.defaults.headers = api_cfg['headers'];
if (log_lvl) { // Remove a header parameter if it is set to null
console.log('axios_api.defaults.headers:', axios_api.defaults.headers); if (api_cfg['headers'].hasOwnProperty('x-no-account-id') && api_cfg['headers']['x-no-account-id'] === null) {
console.log('Additional headers:', headers); delete api_cfg['headers']['x-no-account-id'];
} }
// console.log('Clean the headers. No _underscores_!') // console.log('Clean the headers. No _underscores_!')
@@ -94,230 +86,65 @@ export let get_object = async function get_object(
console.log('All headers cleaned:', headers); console.log('All headers cleaned:', headers);
} }
if (log_lvl) { const fetchOptions: RequestInit = {
console.log('URL params:'); method: 'GET',
} headers: {
for (const prop in params) { ...api_cfg['headers'],
if (log_lvl > 1) { ...headers
console.log(`URL param: ${prop}: ${params[prop]}`);
}
if (params[prop] === null ) {
params[prop] = 'null';
}
}
// Handle the case where there is no Blob expected to be returned. Mainly JSON and text data.
if (!return_blob) {
let response_data_promise = await axios_api.get(
endpoint,
{
headers: headers,
params: params,
onDownloadProgress: (progressEvent) => {
let percent_completed = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
if (log_lvl > 1) {
console.log('GET Data Progress:', progressEvent.progress, 'Total:', progressEvent.total, 'Loaded:', progressEvent.loaded, 'Percent Completed', percent_completed);
}
temp_get_object_percent_completed = percent_completed;
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
try {
// Check if window is defined. This is to prevent errors in SvelteKit.
if (typeof window !== 'undefined') {
window.postMessage({
type: 'api_download_data',
status: 'downloading',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: progressEvent.total,
size_loaded: progressEvent.loaded,
percent_completed: percent_completed,
}, },
'*' signal: controller.signal
); };
}
} catch (error) {
console.log('Error posting message to window:', error);
}
}
}
)
.then(function (response) {
if (log_lvl) { if (log_lvl) {
console.log(`GET Response: status=${response.status} statusText=${response.statusText} baseURL=${response.config.baseURL} url=${response.config.url} method=${response.config.method} headers=${response.config.headers} params=${JSON.stringify(response.config.params)}`); console.log('Fetch options:', fetchOptions);
}
if (log_lvl > 1) {
console.log('GET Response:', response);
} }
// Post file download message
try { try {
if (typeof window !== 'undefined') { const response = await fetch(url.toString(), fetchOptions);
window.postMessage({ clearTimeout(timeoutId);
type: 'api_download_data',
status: 'complete', if (log_lvl) {
task_id: task_id, console.log(`Response: status=${response.status} statusText=${response.statusText} url=${response.url}`);
endpoint: endpoint,
filename: filename,
size_total: 0,
size_loaded: 0,
percent_completed: 100,
},
'*'
);
}
} catch (error) {
console.log('Error posting message to window:', error);
} }
if (!Array.isArray(response.data['data']) && as_list) { if (!response.ok) {
if (log_lvl) { if (response.status === 404) {
console.log('Data result is a dictionary/object, not an array/list. Forcing return as an array/list');
}
let return_data = [];
return_data.push(response.data['data']);
return return_data;
} else if (response.data['data']) {
let return_data = response.data['data'];
if (log_lvl) {
if (Array.isArray(return_data)) {
console.log(`Data result is an array/list. Array length: ${return_data.length}`);
} else {
console.log(`Data result is a dictionary/object, not an array/list.`);
}
}
return return_data;
} else {
let return_data = response.data;
if (log_lvl) {
if (Array.isArray(return_data)) {
console.log(`Not a standard response from Aether's API. Data result is an array/list. Array length: ${return_data.length}`);
} else {
console.log(`Not a standard response from Aether's API. Data result is a dictionary/object, not an array/list.`);
}
}
return return_data;
}
})
.catch(function (error) {
// Handle the common and expected 404 "error" first
if (error.response && error.response.status === 404) {
if (log_lvl) { if (log_lvl) {
console.log('The response was a 404 not found "error". Returning null.'); console.log('The response was a 404 not found "error". Returning null.');
} }
return null;
}
throw new Error(`HTTP error! status: ${response.status}`);
}
if (!return_blob) {
const json = await response.json();
if (log_lvl > 1) { if (log_lvl > 1) {
console.log(error.response); console.log('Response JSON:', json);
} }
if (log_lvl > 2) { if (!Array.isArray(json.data) && as_list) {
console.log(error); 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 = [];
// Post file download message while (true) {
try { const { done, value } = await reader!.read();
if (typeof window !== 'undefined') { if (done) break;
window.postMessage({ chunks.push(value);
type: 'api_download_data', receivedLength += value.length;
status: 'complete',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: 0,
size_loaded: 0,
percent_completed: 0,
},
'*'
);
}
} catch (error) {
console.log('Error posting message to window:', error);
}
return null; // Returning null since there were no results
}
if (log_lvl) { const percent_completed = Math.round((receivedLength * 100) / contentLength);
console.log(`Base URL: ${api_cfg['base_url']} | Endpoint: ${endpoint}`);
console.log('Error Message:', error.message); // Is this needed here or below in the in the else portion???
if (error.response) {
// The request was made and the server responded with a status code that falls out of the range of 2xx
console.log('Error Response Data', error.response.data);
console.log('Error Response Status', error.response.status);
console.log('Error Response Headers', error.response.headers);
} else if (error.request) {
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js
if (log_lvl > 1) { if (log_lvl > 1) {
console.log('Error Request', error.request); console.log('GET Blob Progress:', percent_completed, 'Total:', contentLength, 'Loaded:', receivedLength, 'Percent Completed', percent_completed);
} }
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error Message', error.message);
}
}
if (log_lvl > 2) {
console.log('Error:', error);
console.log(error.config);
}
if (error.code === 'ECONNABORTED') {
// Timeout Error (You can implement retry here where suitable)
console.log('Timeout Error: ', error.message);
}
if (log_lvl) {
console.log('The response was an error. Returning false.');
}
return false; // Returning false since something may have gone wrong. This includes timeouts. Also more in line with what the API returns.
// return error;
});
if (log_lvl > 1) {
// console.log(`Response Data: ${response_data_promise}`);
console.log(`Response Data:`, response_data_promise);
// console.log(response_data_promise);
}
if (response_data_promise) {
// The most common and expected response.
// console.log('Returning result. This is generally expected.');
return response_data_promise;
} else if (response_data_promise === null) {
// Less common, but expected response if no results were returned.
if (log_lvl) {
console.log('Returning null. This is expected if no results were found. (404)');
}
return response_data_promise;
} else if (response_data_promise === false) {
// Not common, but expected response if the request to the API had an issue.
console.log('Returning false. There may have been an issue with this request.');
return response_data_promise;
} else {
// This generally should not happen. It likely means the query was bad or an API issue.
console.log('Returning (JSON/text) unknown. This should not happen in most cases.');
Promise.reject(new Error('fail')).then(resolved, rejected);
}
// Handle the case where a Blob is expected to be returned.
} else {
// console.log('Expecting a Blob to be returned...');
let response_data_promise = await axios_api.get(
endpoint,
{
params: params,
responseType: 'blob',
onDownloadProgress: (progressEvent) => {
let percent_completed = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log('GET Blob Progress:', progressEvent.progress, 'Total:', progressEvent.total, 'Loaded:', progressEvent.loaded, 'Percent Completed', percent_completed);
temp_get_blob_percent_completed = percent_completed; temp_get_blob_percent_completed = percent_completed;
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
try { try {
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
window.postMessage({ window.postMessage({
@@ -326,171 +153,34 @@ export let get_object = async function get_object(
task_id: task_id, task_id: task_id,
endpoint: endpoint, endpoint: endpoint,
filename: filename, filename: filename,
size_total: progressEvent.total, size_total: contentLength,
size_loaded: progressEvent.loaded, size_loaded: receivedLength,
percent_completed: percent_completed, percent_completed: percent_completed
}, }, '*');
'*'
);
} }
} catch (error) { } catch (e) {
console.log('Error posting message to window:', error); console.error('Error posting message:', e);
} }
} }
}
)
.then(function (response) {
if (log_lvl) {
console.log(`GET (blob) Response: status=${response.status} statusText=${response.statusText} baseURL=${response.config.baseURL} url=${response.config.url} method=${response.config.method} headers=${response.config.headers} params=${response.config.params}`);
}
if (log_lvl > 1) {
console.log('GET (blob) Response:', response);
}
const { data, headers } = response;
// Careful if this download filename needs to be changed to a different file extension. The browser/client may not know how to handle it.
if (filename) {
} else if (headers['content-disposition']) {
filename = headers['content-disposition'].replace(/\w+;filename=(.*)/, '$1');
} else {
filename = 'unknown_file.ext';
}
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
try {
if (typeof window !== 'undefined') {
window.postMessage({
type: 'api_download_blob',
status: 'complete',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: 0,
size_loaded: 0,
percent_completed: 100,
},
'*'
);
}
} catch (error) {
console.log('Error posting message to window:', error);
}
const blob = new Blob(chunks);
if (auto_download) { if (auto_download) {
if (log_lvl) { const downloadUrl = window.URL.createObjectURL(blob);
console.log(`Auto Download: ${filename}`);
}
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a'); const link = document.createElement('a');
link.href = url; link.href = downloadUrl;
link.setAttribute('download', filename); link.setAttribute('download', filename || 'download');
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
link.remove();
return true; return true;
} else { } else {
return response; return blob;
} }
})
.catch(function (error) {
// Handle the common and expected 404 "error" first
if (error.response && error.response.status === 404) {
if (log_lvl) {
console.log('The response was a 404 not found "error". Returning null.');
}
if (log_lvl > 1) {
console.log(error.response);
}
if (log_lvl > 2) {
console.log(error);
}
// Post file download message
try {
if (typeof window !== 'undefined') {
window.postMessage({
type: 'api_download_blob',
status: 'complete',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: 0,
size_loaded: 0,
percent_completed: 0,
},
'*'
);
} }
} catch (error) { } catch (error) {
console.log('Error posting message to window:', error);
}
return null; // Returning null since there were no results
}
if (log_lvl) { if (log_lvl) {
console.log(`Base URL: ${api_cfg['base_url']} | Endpoint: ${endpoint}`); console.log('Fetch error:', error);
console.log('Error Message:', error.message); // Is this needed here or below in the in the else portion???
if (error.response) {
// The request was made and the server responded with a status code that falls out of the range of 2xx
console.log('Error Response Data', error.response.data);
console.log('Error Response Status', error.response.status);
console.log('Error Response Headers', error.response.headers);
} else if (error.request) {
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js
if (log_lvl > 1) {
console.log('Error Request', error.request);
} }
} else { return false;
// Something happened in setting up the request that triggered an Error
console.log('Error Message', error.message);
} }
} };
if (error.code === 'ECONNABORTED') {
// Timeout Error (You can implement retry here where suitable)
console.log('Timeout Error: ', error.message);
}
if (log_lvl) {
console.log('The response was an error. Returning false.');
}
return false; // Returning false since something may have gone wrong. This includes timeouts. Also more in line with what the API returns.
// return error;
});
if (response_data_promise) {
// The most common and expected response.
// console.log('Returning result. This is generally expected.');
// let test_blob = new Blob([response_data_promise.data]);
// console.log(test_blob);
// return test_blob;
// console.log(response_data_promise.blob());
return response_data_promise;
} else if (response_data_promise === null) {
// Less common, but expected response if no results were returned.
if (log_lvl) {
console.log('Returning null. This is expected if no results were found. (404)');
}
return response_data_promise;
} else if (response_data_promise === false) {
// Not common, but expected response if the request to the API had an issue.
console.log('Returning false. There may have been an issue with this request.');
return response_data_promise;
} else {
// This generally should not happen. It likely means the query was bad or an API issue.
console.log('Returning (blob) unknown. This should not happen in most cases.');
Promise.reject(new Error('fail')).then(resolved, rejected);
}
}
}
function resolved(result: any) {
console.log('Resolved');
}
function rejected(result: any) {
console.error(result);
}

View File

@@ -0,0 +1,496 @@
import axios from 'axios';
import type { key_val } from '$lib/ae_stores';
export let temp_get_blob_percent_completed = 0;
// export let get_blob_percent_completed = readable(temp_get_blob_percent_completed);
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 = readable(temp_get_object_percent_completed);
export let get_object_percent_completed = temp_get_object_percent_completed;
// Updated 2024-05-23
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,
// 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
}: {
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
}
) {
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);
console.log(`Base URL: ${api_cfg['base_url']}; Timeout: ${timeout}`);
console.log('API Config:', api_cfg);
}
if (log_lvl > 2) {
console.log(`Return Meta: ${return_meta}; Return Blob: ${return_blob}; Filename: ${filename}; Auto Download: ${auto_download}`);
}
}
if (!api_cfg) {
console.log('No API Config was provided. Returning false.');
return false;
}
let axios_api = axios.create({
baseURL: api_cfg['base_url'],
timeout: timeout, // in milliseconds; 60000 = 60 seconds
/* other custom settings */
});
axios_api.defaults.headers = api_cfg['headers'];
if (log_lvl) {
console.log('axios_api.defaults.headers:', axios_api.defaults.headers);
console.log('Additional headers:', headers);
}
// console.log('Clean the headers. No _underscores_!')
let headers_cleaned: key_val = {};
for (const prop in headers) {
// No underscores allowed in the header parameters!
let prop_cleaned = prop.replaceAll('_', '-');
// The value must be a string for the header!
if (typeof headers[prop] != 'string') {
headers[prop] = JSON.stringify(headers[prop]);
}
headers_cleaned[prop_cleaned] = headers[prop];
if (log_lvl) {
console.log(`${prop_cleaned}: ${headers_cleaned[prop_cleaned]}`);
}
}
headers = headers_cleaned;
if (log_lvl) {
console.log('All headers cleaned:', headers);
}
if (log_lvl) {
console.log('URL params:');
}
for (const prop in params) {
if (log_lvl > 1) {
console.log(`URL param: ${prop}: ${params[prop]}`);
}
if (params[prop] === null ) {
params[prop] = 'null';
}
}
// Handle the case where there is no Blob expected to be returned. Mainly JSON and text data.
if (!return_blob) {
let response_data_promise = await axios_api.get(
endpoint,
{
headers: headers,
params: params,
onDownloadProgress: (progressEvent) => {
let percent_completed = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
if (log_lvl > 1) {
console.log('GET Data Progress:', progressEvent.progress, 'Total:', progressEvent.total, 'Loaded:', progressEvent.loaded, 'Percent Completed', percent_completed);
}
temp_get_object_percent_completed = percent_completed;
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
try {
// Check if window is defined. This is to prevent errors in SvelteKit.
if (typeof window !== 'undefined') {
window.postMessage({
type: 'api_download_data',
status: 'downloading',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: progressEvent.total,
size_loaded: progressEvent.loaded,
percent_completed: percent_completed,
},
'*'
);
}
} catch (error) {
console.log('Error posting message to window:', error);
}
}
}
)
.then(function (response) {
if (log_lvl) {
console.log(`GET Response: status=${response.status} statusText=${response.statusText} baseURL=${response.config.baseURL} url=${response.config.url} method=${response.config.method} headers=${response.config.headers} params=${JSON.stringify(response.config.params)}`);
}
if (log_lvl > 1) {
console.log('GET Response:', response);
}
// Post file download message
try {
if (typeof window !== 'undefined') {
window.postMessage({
type: 'api_download_data',
status: 'complete',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: 0,
size_loaded: 0,
percent_completed: 100,
},
'*'
);
}
} catch (error) {
console.log('Error posting message to window:', error);
}
if (!Array.isArray(response.data['data']) && as_list) {
if (log_lvl) {
console.log('Data result is a dictionary/object, not an array/list. Forcing return as an array/list');
}
let return_data = [];
return_data.push(response.data['data']);
return return_data;
} else if (response.data['data']) {
let return_data = response.data['data'];
if (log_lvl) {
if (Array.isArray(return_data)) {
console.log(`Data result is an array/list. Array length: ${return_data.length}`);
} else {
console.log(`Data result is a dictionary/object, not an array/list.`);
}
}
return return_data;
} else {
let return_data = response.data;
if (log_lvl) {
if (Array.isArray(return_data)) {
console.log(`Not a standard response from Aether's API. Data result is an array/list. Array length: ${return_data.length}`);
} else {
console.log(`Not a standard response from Aether's API. Data result is a dictionary/object, not an array/list.`);
}
}
return return_data;
}
})
.catch(function (error) {
// Handle the common and expected 404 "error" first
if (error.response && error.response.status === 404) {
if (log_lvl) {
console.log('The response was a 404 not found "error". Returning null.');
}
if (log_lvl > 1) {
console.log(error.response);
}
if (log_lvl > 2) {
console.log(error);
}
// Post file download message
try {
if (typeof window !== 'undefined') {
window.postMessage({
type: 'api_download_data',
status: 'complete',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: 0,
size_loaded: 0,
percent_completed: 0,
},
'*'
);
}
} catch (error) {
console.log('Error posting message to window:', error);
}
return null; // Returning null since there were no results
}
if (log_lvl) {
console.log(`Base URL: ${api_cfg['base_url']} | Endpoint: ${endpoint}`);
console.log('Error Message:', error.message); // Is this needed here or below in the in the else portion???
if (error.response) {
// The request was made and the server responded with a status code that falls out of the range of 2xx
console.log('Error Response Data', error.response.data);
console.log('Error Response Status', error.response.status);
console.log('Error Response Headers', error.response.headers);
} else if (error.request) {
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js
if (log_lvl > 1) {
console.log('Error Request', error.request);
}
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error Message', error.message);
}
}
if (log_lvl > 2) {
console.log('Error:', error);
console.log(error.config);
}
if (error.code === 'ECONNABORTED') {
// Timeout Error (You can implement retry here where suitable)
console.log('Timeout Error: ', error.message);
}
if (log_lvl) {
console.log('The response was an error. Returning false.');
}
return false; // Returning false since something may have gone wrong. This includes timeouts. Also more in line with what the API returns.
// return error;
});
if (log_lvl > 1) {
// console.log(`Response Data: ${response_data_promise}`);
console.log(`Response Data:`, response_data_promise);
// console.log(response_data_promise);
}
if (response_data_promise) {
// The most common and expected response.
// console.log('Returning result. This is generally expected.');
return response_data_promise;
} else if (response_data_promise === null) {
// Less common, but expected response if no results were returned.
if (log_lvl) {
console.log('Returning null. This is expected if no results were found. (404)');
}
return response_data_promise;
} else if (response_data_promise === false) {
// Not common, but expected response if the request to the API had an issue.
console.log('Returning false. There may have been an issue with this request.');
return response_data_promise;
} else {
// This generally should not happen. It likely means the query was bad or an API issue.
console.log('Returning (JSON/text) unknown. This should not happen in most cases.');
Promise.reject(new Error('fail')).then(resolved, rejected);
}
// Handle the case where a Blob is expected to be returned.
} else {
// console.log('Expecting a Blob to be returned...');
let response_data_promise = await axios_api.get(
endpoint,
{
params: params,
responseType: 'blob',
onDownloadProgress: (progressEvent) => {
let percent_completed = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
console.log('GET Blob Progress:', progressEvent.progress, 'Total:', progressEvent.total, 'Loaded:', progressEvent.loaded, 'Percent Completed', percent_completed);
temp_get_blob_percent_completed = percent_completed;
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
try {
if (typeof window !== 'undefined') {
window.postMessage({
type: 'api_download_blob',
status: 'downloading',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: progressEvent.total,
size_loaded: progressEvent.loaded,
percent_completed: percent_completed,
},
'*'
);
}
} catch (error) {
console.log('Error posting message to window:', error);
}
}
}
)
.then(function (response) {
if (log_lvl) {
console.log(`GET (blob) Response: status=${response.status} statusText=${response.statusText} baseURL=${response.config.baseURL} url=${response.config.url} method=${response.config.method} headers=${response.config.headers} params=${response.config.params}`);
}
if (log_lvl > 1) {
console.log('GET (blob) Response:', response);
}
const { data, headers } = response;
// Careful if this download filename needs to be changed to a different file extension. The browser/client may not know how to handle it.
if (filename) {
} else if (headers['content-disposition']) {
filename = headers['content-disposition'].replace(/\w+;filename=(.*)/, '$1');
} else {
filename = 'unknown_file.ext';
}
// WARNING: This needs to be tied to an object type and ID. This is a temporary solution.
try {
if (typeof window !== 'undefined') {
window.postMessage({
type: 'api_download_blob',
status: 'complete',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: 0,
size_loaded: 0,
percent_completed: 100,
},
'*'
);
}
} catch (error) {
console.log('Error posting message to window:', error);
}
if (auto_download) {
if (log_lvl) {
console.log(`Auto Download: ${filename}`);
}
const url = window.URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', filename);
document.body.appendChild(link);
link.click();
return true;
} else {
return response;
}
})
.catch(function (error) {
// Handle the common and expected 404 "error" first
if (error.response && error.response.status === 404) {
if (log_lvl) {
console.log('The response was a 404 not found "error". Returning null.');
}
if (log_lvl > 1) {
console.log(error.response);
}
if (log_lvl > 2) {
console.log(error);
}
// Post file download message
try {
if (typeof window !== 'undefined') {
window.postMessage({
type: 'api_download_blob',
status: 'complete',
task_id: task_id,
endpoint: endpoint,
filename: filename,
size_total: 0,
size_loaded: 0,
percent_completed: 0,
},
'*'
);
}
} catch (error) {
console.log('Error posting message to window:', error);
}
return null; // Returning null since there were no results
}
if (log_lvl) {
console.log(`Base URL: ${api_cfg['base_url']} | Endpoint: ${endpoint}`);
console.log('Error Message:', error.message); // Is this needed here or below in the in the else portion???
if (error.response) {
// The request was made and the server responded with a status code that falls out of the range of 2xx
console.log('Error Response Data', error.response.data);
console.log('Error Response Status', error.response.status);
console.log('Error Response Headers', error.response.headers);
} else if (error.request) {
// The request was made but no response was received `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js
if (log_lvl > 1) {
console.log('Error Request', error.request);
}
} else {
// Something happened in setting up the request that triggered an Error
console.log('Error Message', error.message);
}
}
if (error.code === 'ECONNABORTED') {
// Timeout Error (You can implement retry here where suitable)
console.log('Timeout Error: ', error.message);
}
if (log_lvl) {
console.log('The response was an error. Returning false.');
}
return false; // Returning false since something may have gone wrong. This includes timeouts. Also more in line with what the API returns.
// return error;
});
if (response_data_promise) {
// The most common and expected response.
// console.log('Returning result. This is generally expected.');
// let test_blob = new Blob([response_data_promise.data]);
// console.log(test_blob);
// return test_blob;
// console.log(response_data_promise.blob());
return response_data_promise;
} else if (response_data_promise === null) {
// Less common, but expected response if no results were returned.
if (log_lvl) {
console.log('Returning null. This is expected if no results were found. (404)');
}
return response_data_promise;
} else if (response_data_promise === false) {
// Not common, but expected response if the request to the API had an issue.
console.log('Returning false. There may have been an issue with this request.');
return response_data_promise;
} else {
// This generally should not happen. It likely means the query was bad or an API issue.
console.log('Returning (blob) unknown. This should not happen in most cases.');
Promise.reject(new Error('fail')).then(resolved, rejected);
}
}
}
function resolved(result: any) {
console.log('Resolved');
}
function rejected(result: any) {
console.error(result);
}

View File

@@ -58,7 +58,9 @@ $: lq_new__event_obj_li = liveQuery(async () => {
if (log_lvl) { if (log_lvl) {
console.log(`Trying where: ${link_to_type}; equals: ${link_to_id}`); console.log(`Trying where: ${link_to_type}; equals: ${link_to_id}`);
} }
let results = await db_events.events let results: any = null;
if ($idaa_loc.recovery_meetings.qry__order_by == 'name') {
results = await db_events.events
.where(`${link_to_type}_id`) .where(`${link_to_type}_id`)
.equals(link_to_id) .equals(link_to_id)
.and((event) => { .and((event) => {
@@ -68,6 +70,18 @@ $: lq_new__event_obj_li = liveQuery(async () => {
return event.enable == true; return event.enable == true;
}) })
.sortBy('name') .sortBy('name')
} else {
results = await db_events.events
.where(`${link_to_type}_id`)
.equals(link_to_id)
.and((event) => {
return event.hide == false;
})
.and((event) => {
return event.enable == true;
})
.sortBy('updated_on')
}
return results; return results;
} else { } else {
@@ -198,7 +212,7 @@ $: if ($idaa_trig.event_li_qry) {
qry_str: $idaa_loc.recovery_meetings.qry__fulltext_str, qry_str: $idaa_loc.recovery_meetings.qry__fulltext_str,
params: params, params: params,
try_cache: try_cache, try_cache: try_cache,
log_lvl: log_lvl, log_lvl: 2,
}) })
.then(function (search_results) { .then(function (search_results) {
// Processing the results from the search. // Processing the results from the search.