Last round of prettier: npx prettier --write src/
This commit is contained in:
@@ -43,7 +43,9 @@ export const delete_object = async function delete_object({
|
||||
// Construct the URL with query parameters
|
||||
const url = new URL(endpoint, api_cfg['base_url']);
|
||||
if (params) {
|
||||
Object.keys(params).forEach((key) => url.searchParams.append(key, params[key]));
|
||||
Object.keys(params).forEach((key) =>
|
||||
url.searchParams.append(key, params[key])
|
||||
);
|
||||
}
|
||||
|
||||
// Clean and merge headers without mutating the original api_cfg
|
||||
@@ -70,8 +72,13 @@ export const delete_object = async function delete_object({
|
||||
}
|
||||
|
||||
// Auto-inject Authorization header if JWT is present but header is missing
|
||||
const jwt = headers_cleaned['jwt'] || headers_cleaned['JWT'] || api_cfg['jwt'];
|
||||
if (jwt && !headers_cleaned['Authorization'] && !headers_cleaned['authorization']) {
|
||||
const jwt =
|
||||
headers_cleaned['jwt'] || headers_cleaned['JWT'] || api_cfg['jwt'];
|
||||
if (
|
||||
jwt &&
|
||||
!headers_cleaned['Authorization'] &&
|
||||
!headers_cleaned['authorization']
|
||||
) {
|
||||
headers_cleaned['Authorization'] = `Bearer ${jwt}`;
|
||||
}
|
||||
|
||||
@@ -93,20 +100,26 @@ export const delete_object = async function delete_object({
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => {
|
||||
console.error(`API DELETE request timed out after ${timeout}ms.`);
|
||||
console.error(
|
||||
`API DELETE request timed out after ${timeout}ms.`
|
||||
);
|
||||
controller.abort();
|
||||
}, timeout);
|
||||
|
||||
const fetchOptions: RequestInit = {
|
||||
method: 'DELETE',
|
||||
headers: headers_cleaned,
|
||||
body: Object.keys(data).length > 0 ? JSON.stringify(data) : undefined,
|
||||
body:
|
||||
Object.keys(data).length > 0
|
||||
? JSON.stringify(data)
|
||||
: undefined,
|
||||
signal: controller.signal
|
||||
};
|
||||
|
||||
const response = await fetch_method(url.toString(), fetchOptions).catch(function (
|
||||
error: any
|
||||
) {
|
||||
const response = await fetch_method(
|
||||
url.toString(),
|
||||
fetchOptions
|
||||
).catch(function (error: any) {
|
||||
console.log(
|
||||
'API DELETE Object *fetch* request was aborted or failed in an unexpected way.',
|
||||
error
|
||||
@@ -121,7 +134,9 @@ export const delete_object = async function delete_object({
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Response: status=${response.status} attempt=${attempt}`);
|
||||
console.log(
|
||||
`Response: status=${response.status} attempt=${attempt}`
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
@@ -129,15 +144,20 @@ export const delete_object = async function delete_object({
|
||||
console.warn('404 Not Found. Returning null.');
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
const errorBody = await response.text();
|
||||
console.error(`HTTP error! status: ${response.status}`, errorBody);
|
||||
console.error(
|
||||
`HTTP error! status: ${response.status}`,
|
||||
errorBody
|
||||
);
|
||||
|
||||
if (response.status >= 400 && response.status < 404) {
|
||||
return false;
|
||||
}
|
||||
|
||||
throw new Error(`HTTP error! status: ${response.status} - ${errorBody}`);
|
||||
throw new Error(
|
||||
`HTTP error! status: ${response.status} - ${errorBody}`
|
||||
);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
@@ -148,7 +168,11 @@ export const delete_object = async function delete_object({
|
||||
|
||||
// Return the response data or metadata
|
||||
// Robustly handle V3 response envelopes
|
||||
return return_meta ? json : (json.data !== undefined ? json.data : json);
|
||||
return return_meta
|
||||
? json
|
||||
: json.data !== undefined
|
||||
? json.data
|
||||
: json;
|
||||
} catch (error) {
|
||||
console.error(`API DELETE error on attempt ${attempt}:`, error);
|
||||
|
||||
|
||||
@@ -44,7 +44,9 @@ export async function get_ae_obj_id_crud({
|
||||
log_lvl?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** get_ae_obj_id_crud() *** Type: ${obj_type} ID: ${obj_id}`);
|
||||
console.log(
|
||||
`*** get_ae_obj_id_crud() *** Type: ${obj_type} ID: ${obj_id}`
|
||||
);
|
||||
}
|
||||
|
||||
// V3 Standard: Unified endpoint for all objects
|
||||
@@ -77,7 +79,10 @@ export async function get_ae_obj_id_crud({
|
||||
log_lvl: log_lvl,
|
||||
return_meta: return_meta
|
||||
}).catch(function (error: any) {
|
||||
console.error(`API GET CRUD object ID request failed for ${obj_type}/${obj_id}`, error);
|
||||
console.error(
|
||||
`API GET CRUD object ID request failed for ${obj_type}/${obj_id}`,
|
||||
error
|
||||
);
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -86,4 +91,4 @@ export async function get_ae_obj_id_crud({
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,10 @@ interface GetAeObjLiV3Params {
|
||||
view?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: Record<string, 'ASC' | 'DESC'> | Record<string, 'ASC' | 'DESC'>[] | null;
|
||||
order_by_li?:
|
||||
| Record<string, 'ASC' | 'DESC'>
|
||||
| Record<string, 'ASC' | 'DESC'>[]
|
||||
| null;
|
||||
delay_ms?: number;
|
||||
params?: key_val;
|
||||
headers?: key_val;
|
||||
@@ -162,7 +165,10 @@ interface GetNestedObjLiV3Params {
|
||||
view?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
order_by_li?: Record<string, 'ASC' | 'DESC'> | Record<string, 'ASC' | 'DESC'>[] | null;
|
||||
order_by_li?:
|
||||
| Record<string, 'ASC' | 'DESC'>
|
||||
| Record<string, 'ASC' | 'DESC'>[]
|
||||
| null;
|
||||
delay_ms?: number;
|
||||
log_lvl?: number;
|
||||
}
|
||||
@@ -206,4 +212,4 @@ export async function get_nested_obj_li({
|
||||
params,
|
||||
log_lvl
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@ export async function get_data_store({
|
||||
log_lvl = 0
|
||||
}: GetDataStoreV3Params): Promise<any> {
|
||||
if (log_lvl) {
|
||||
console.log(`*** get_data_store() *** code=${code} no_account_id=${no_account_id}`);
|
||||
console.log(
|
||||
`*** get_data_store() *** code=${code} no_account_id=${no_account_id}`
|
||||
);
|
||||
}
|
||||
|
||||
const endpoint = `/v3/data_store/code/${code}`;
|
||||
|
||||
@@ -41,7 +41,9 @@ export const get_object = async function get_object({
|
||||
retry_count?: number;
|
||||
}) {
|
||||
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);
|
||||
if (log_lvl > 1) {
|
||||
console.log('Data:', data);
|
||||
@@ -55,7 +57,10 @@ export const get_object = async function get_object({
|
||||
|
||||
// FAIL FAST: Check if we are explicitly offline to avoid long browser timeouts
|
||||
if (typeof navigator !== 'undefined' && !navigator.onLine) {
|
||||
if (log_lvl) console.log('get_object: Browser is offline. Failing fast to allow cache fallback.');
|
||||
if (log_lvl)
|
||||
console.log(
|
||||
'get_object: Browser is offline. Failing fast to allow cache fallback.'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -64,7 +69,9 @@ export const get_object = async function get_object({
|
||||
}
|
||||
|
||||
const url = new URL(endpoint, api_cfg['base_url']);
|
||||
Object.keys(params).forEach((key) => url.searchParams.append(key, params[key]));
|
||||
Object.keys(params).forEach((key) =>
|
||||
url.searchParams.append(key, params[key])
|
||||
);
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
||||
@@ -96,14 +103,19 @@ export const get_object = async function get_object({
|
||||
}
|
||||
|
||||
// Handle "Bootstrap Paradox" for unauthenticated requests
|
||||
const bypass_val = merged_headers['x-no-account-id'] || merged_headers['x_no_account_id'];
|
||||
const is_valid_bypass = bypass_val === 'bypass' ||
|
||||
bypass_val === 'Nothing to See Here' ||
|
||||
params['key'] ||
|
||||
bypass_val === 'direct-download';
|
||||
const bypass_val =
|
||||
merged_headers['x-no-account-id'] || merged_headers['x_no_account_id'];
|
||||
const is_valid_bypass =
|
||||
bypass_val === 'bypass' ||
|
||||
bypass_val === 'Nothing to See Here' ||
|
||||
params['key'] ||
|
||||
bypass_val === 'direct-download';
|
||||
|
||||
if (is_valid_bypass) {
|
||||
if (log_lvl > 1) console.log('api_get_object: Valid bypass detected. Stripping account ID context.');
|
||||
if (log_lvl > 1)
|
||||
console.log(
|
||||
'api_get_object: Valid bypass detected. Stripping account ID context.'
|
||||
);
|
||||
delete merged_headers['x-account-id'];
|
||||
delete merged_headers['x_account_id'];
|
||||
} else {
|
||||
@@ -126,11 +138,12 @@ export const get_object = async function get_object({
|
||||
}
|
||||
|
||||
// Auto-inject Authorization header if JWT is present but header is missing
|
||||
let jwt = headers_cleaned['jwt'] ||
|
||||
headers_cleaned['JWT'] ||
|
||||
api_cfg['jwt'] ||
|
||||
api_cfg['headers']?.['jwt'] ||
|
||||
api_cfg['headers']?.['JWT'];
|
||||
let jwt =
|
||||
headers_cleaned['jwt'] ||
|
||||
headers_cleaned['JWT'] ||
|
||||
api_cfg['jwt'] ||
|
||||
api_cfg['headers']?.['jwt'] ||
|
||||
api_cfg['headers']?.['JWT'];
|
||||
|
||||
// Final Fallback: Direct check of primary ae_loc key
|
||||
if (!jwt && typeof localStorage !== 'undefined') {
|
||||
@@ -145,7 +158,11 @@ export const get_object = async function get_object({
|
||||
}
|
||||
}
|
||||
|
||||
if (jwt && !headers_cleaned['Authorization'] && !headers_cleaned['authorization']) {
|
||||
if (
|
||||
jwt &&
|
||||
!headers_cleaned['Authorization'] &&
|
||||
!headers_cleaned['authorization']
|
||||
) {
|
||||
headers_cleaned['Authorization'] = `Bearer ${jwt}`;
|
||||
}
|
||||
|
||||
@@ -174,18 +191,29 @@ export const get_object = async function get_object({
|
||||
for (let attempt = 1; attempt <= retry_count; attempt++) {
|
||||
// FAIL FAST: Check if we are explicitly offline to avoid long browser timeouts
|
||||
if (typeof navigator !== 'undefined' && !navigator.onLine) {
|
||||
if (log_lvl) console.log(`get_object: Browser is offline (attempt ${attempt}). Failing fast to allow cache fallback.`);
|
||||
if (log_lvl)
|
||||
console.log(
|
||||
`get_object: Browser is offline (attempt ${attempt}). Failing fast to allow cache fallback.`
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch_method(url.toString(), fetchOptions).catch(function (
|
||||
error: any
|
||||
) {
|
||||
const response = await fetch_method(
|
||||
url.toString(),
|
||||
fetchOptions
|
||||
).catch(function (error: any) {
|
||||
// SILENCE NOISE: Aborted requests (common in SWR/Background loads) shouldn't spam logs
|
||||
if (error.name === 'AbortError' || error.message?.includes('aborted') || error.name === 'TypeError') {
|
||||
if (
|
||||
error.name === 'AbortError' ||
|
||||
error.message?.includes('aborted') ||
|
||||
error.name === 'TypeError'
|
||||
) {
|
||||
if (log_lvl > 1) {
|
||||
console.log('API GET: Request was aborted or terminated by browser. This is expected during navigation.', error);
|
||||
console.log(
|
||||
'API GET: Request was aborted or terminated by browser. This is expected during navigation.',
|
||||
error
|
||||
);
|
||||
}
|
||||
return error; // Return error to be handled below
|
||||
}
|
||||
@@ -199,11 +227,19 @@ export const get_object = async function get_object({
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
// Check if we should stop due to abort or network failure
|
||||
if (response instanceof Error || (response && (response.name === 'TypeError' || response.name === 'AbortError'))) {
|
||||
if (
|
||||
response instanceof Error ||
|
||||
(response &&
|
||||
(response.name === 'TypeError' ||
|
||||
response.name === 'AbortError'))
|
||||
) {
|
||||
// If it was an explicit abort, definitely stop
|
||||
if (response.name === 'AbortError') return false;
|
||||
|
||||
if (log_lvl > 1) console.log('API GET Object: Detected NetworkError or TypeError. Failing fast.');
|
||||
if (log_lvl > 1)
|
||||
console.log(
|
||||
'API GET Object: Detected NetworkError or TypeError. Failing fast.'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -231,24 +267,45 @@ export const get_object = async function get_object({
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
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;
|
||||
}
|
||||
|
||||
// FAIL FAST (Section 2D): Do not retry on Auth or Client errors (400, 401, 403, 422)
|
||||
if (response.status === 400 || response.status === 401 || response.status === 403 || response.status === 422) {
|
||||
if (log_lvl) console.error(`API Client Failure (${response.status}). Failing fast.`);
|
||||
if (
|
||||
response.status === 400 ||
|
||||
response.status === 401 ||
|
||||
response.status === 403 ||
|
||||
response.status === 422
|
||||
) {
|
||||
if (log_lvl)
|
||||
console.error(
|
||||
`API Client Failure (${response.status}). Failing fast.`
|
||||
);
|
||||
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
console.warn(`AUTH DIAGNOSTICS: Headers sent for ${endpoint}:`, {
|
||||
has_auth: !!headers_cleaned['Authorization'],
|
||||
has_api_key: !!headers_cleaned['x-aether-api-key'],
|
||||
has_account_id: !!headers_cleaned['x-account-id'],
|
||||
jwt_preview: jwt ? `${jwt.slice(0, 8)}...` : 'MISSING'
|
||||
});
|
||||
console.warn(
|
||||
`AUTH DIAGNOSTICS: Headers sent for ${endpoint}:`,
|
||||
{
|
||||
has_auth: !!headers_cleaned['Authorization'],
|
||||
has_api_key:
|
||||
!!headers_cleaned['x-aether-api-key'],
|
||||
has_account_id:
|
||||
!!headers_cleaned['x-account-id'],
|
||||
jwt_preview: jwt
|
||||
? `${jwt.slice(0, 8)}...`
|
||||
: 'MISSING'
|
||||
}
|
||||
);
|
||||
// Signal the root layout to show the session-expired banner.
|
||||
if (browser) ae_auth_error.set({ type: 'expired', ts: Date.now() });
|
||||
if (browser)
|
||||
ae_auth_error.set({
|
||||
type: 'expired',
|
||||
ts: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
// Structured Error Handling (V3): Attempt to get rich error metadata
|
||||
@@ -259,7 +316,11 @@ export const get_object = async function get_object({
|
||||
// Not JSON
|
||||
}
|
||||
|
||||
if (log_lvl) console.log('The response was not ok. Structured Error Check:', error_json);
|
||||
if (log_lvl)
|
||||
console.log(
|
||||
'The response was not ok. Structured Error Check:',
|
||||
error_json
|
||||
);
|
||||
|
||||
if (error_json?.meta?.details) {
|
||||
return error_json;
|
||||
@@ -273,7 +334,10 @@ export const get_object = async function get_object({
|
||||
status_code: response.status,
|
||||
details: {
|
||||
category: 'validation',
|
||||
message: typeof error_json.detail === 'string' ? error_json.detail : JSON.stringify(error_json.detail),
|
||||
message:
|
||||
typeof error_json.detail === 'string'
|
||||
? error_json.detail
|
||||
: JSON.stringify(error_json.detail),
|
||||
raw: error_json.detail
|
||||
}
|
||||
}
|
||||
@@ -307,7 +371,9 @@ export const get_object = async function get_object({
|
||||
chunks.push(value);
|
||||
receivedLength += value.length;
|
||||
|
||||
const percent_completed = Math.round((receivedLength * 100) / contentLength);
|
||||
const percent_completed = Math.round(
|
||||
(receivedLength * 100) / contentLength
|
||||
);
|
||||
if (log_lvl > 1) {
|
||||
console.log(
|
||||
'GET Blob Progress:',
|
||||
@@ -359,7 +425,10 @@ export const get_object = async function get_object({
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`API GET object request *fetch* error on attempt ${attempt}:`, 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.');
|
||||
|
||||
@@ -45,7 +45,9 @@ export const patch_object = async function patch_object({
|
||||
// Construct the URL with query parameters
|
||||
const url = new URL(endpoint, api_cfg['base_url']);
|
||||
if (params) {
|
||||
Object.keys(params).forEach((key) => url.searchParams.append(key, params[key]));
|
||||
Object.keys(params).forEach((key) =>
|
||||
url.searchParams.append(key, params[key])
|
||||
);
|
||||
}
|
||||
|
||||
// Clean and merge headers without mutating the original api_cfg
|
||||
@@ -75,14 +77,19 @@ export const patch_object = async function patch_object({
|
||||
}
|
||||
|
||||
// Handle "Bootstrap Paradox" for unauthenticated requests
|
||||
const bypass_val = merged_headers['x-no-account-id'] || merged_headers['x_no_account_id'];
|
||||
const is_valid_bypass = bypass_val === 'bypass' ||
|
||||
bypass_val === 'Nothing to See Here' ||
|
||||
params['key'] ||
|
||||
bypass_val === 'direct-download';
|
||||
const bypass_val =
|
||||
merged_headers['x-no-account-id'] || merged_headers['x_no_account_id'];
|
||||
const is_valid_bypass =
|
||||
bypass_val === 'bypass' ||
|
||||
bypass_val === 'Nothing to See Here' ||
|
||||
params['key'] ||
|
||||
bypass_val === 'direct-download';
|
||||
|
||||
if (is_valid_bypass) {
|
||||
if (log_lvl > 1) console.log('api_patch_object: Valid bypass detected. Stripping account ID context.');
|
||||
if (log_lvl > 1)
|
||||
console.log(
|
||||
'api_patch_object: Valid bypass detected. Stripping account ID context.'
|
||||
);
|
||||
delete merged_headers['x-account-id'];
|
||||
delete merged_headers['x_account_id'];
|
||||
} else {
|
||||
@@ -104,11 +111,12 @@ export const patch_object = async function patch_object({
|
||||
}
|
||||
|
||||
// Auto-inject Authorization header if JWT is present but header is missing
|
||||
let jwt = headers_cleaned['jwt'] ||
|
||||
headers_cleaned['JWT'] ||
|
||||
api_cfg['jwt'] ||
|
||||
api_cfg['headers']?.['jwt'] ||
|
||||
api_cfg['headers']?.['JWT'];
|
||||
let jwt =
|
||||
headers_cleaned['jwt'] ||
|
||||
headers_cleaned['JWT'] ||
|
||||
api_cfg['jwt'] ||
|
||||
api_cfg['headers']?.['jwt'] ||
|
||||
api_cfg['headers']?.['JWT'];
|
||||
|
||||
// Final Fallback: Direct check of primary ae_loc key
|
||||
if (!jwt && typeof localStorage !== 'undefined') {
|
||||
@@ -123,7 +131,11 @@ export const patch_object = async function patch_object({
|
||||
}
|
||||
}
|
||||
|
||||
if (jwt && !headers_cleaned['Authorization'] && !headers_cleaned['authorization']) {
|
||||
if (
|
||||
jwt &&
|
||||
!headers_cleaned['Authorization'] &&
|
||||
!headers_cleaned['authorization']
|
||||
) {
|
||||
headers_cleaned['Authorization'] = `Bearer ${jwt}`;
|
||||
}
|
||||
|
||||
@@ -145,7 +157,9 @@ export const patch_object = async function patch_object({
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => {
|
||||
console.error(`API PATCH request timed out after ${timeout}ms.`);
|
||||
console.error(
|
||||
`API PATCH request timed out after ${timeout}ms.`
|
||||
);
|
||||
controller.abort();
|
||||
}, timeout);
|
||||
|
||||
@@ -156,9 +170,10 @@ export const patch_object = async function patch_object({
|
||||
signal: controller.signal
|
||||
};
|
||||
|
||||
const response = await fetch_method(url.toString(), fetchOptions).catch(function (
|
||||
error: any
|
||||
) {
|
||||
const response = await fetch_method(
|
||||
url.toString(),
|
||||
fetchOptions
|
||||
).catch(function (error: any) {
|
||||
console.log(
|
||||
'API PATCH Object *fetch* request was aborted or failed in an unexpected way.',
|
||||
error
|
||||
@@ -173,30 +188,53 @@ export const patch_object = async function patch_object({
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Response: status=${response.status} attempt=${attempt}`);
|
||||
console.log(
|
||||
`Response: status=${response.status} attempt=${attempt}`
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
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;
|
||||
}
|
||||
|
||||
// FAIL FAST (Section 2D): Do not retry on Auth or Client errors (400, 401, 403, 422)
|
||||
if (response.status === 400 || response.status === 401 || response.status === 403 || response.status === 422) {
|
||||
if (log_lvl) console.error(`API Client Failure (${response.status}). Failing fast.`);
|
||||
if (
|
||||
response.status === 400 ||
|
||||
response.status === 401 ||
|
||||
response.status === 403 ||
|
||||
response.status === 422
|
||||
) {
|
||||
if (log_lvl)
|
||||
console.error(
|
||||
`API Client Failure (${response.status}). Failing fast.`
|
||||
);
|
||||
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
console.warn(`AUTH DIAGNOSTICS (PATCH): Headers sent for ${endpoint}:`, {
|
||||
has_auth: !!headers_cleaned['Authorization'],
|
||||
has_api_key: !!headers_cleaned['x-aether-api-key'],
|
||||
has_account_id: !!headers_cleaned['x-account-id'],
|
||||
jwt_preview: jwt ? `${jwt.slice(0, 8)}...` : 'MISSING'
|
||||
});
|
||||
console.warn(
|
||||
`AUTH DIAGNOSTICS (PATCH): Headers sent for ${endpoint}:`,
|
||||
{
|
||||
has_auth: !!headers_cleaned['Authorization'],
|
||||
has_api_key:
|
||||
!!headers_cleaned['x-aether-api-key'],
|
||||
has_account_id:
|
||||
!!headers_cleaned['x-account-id'],
|
||||
jwt_preview: jwt
|
||||
? `${jwt.slice(0, 8)}...`
|
||||
: 'MISSING'
|
||||
}
|
||||
);
|
||||
// Signal the root layout to show the session-expired banner.
|
||||
if (browser) ae_auth_error.set({ type: 'expired', ts: Date.now() });
|
||||
if (browser)
|
||||
ae_auth_error.set({
|
||||
type: 'expired',
|
||||
ts: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
// Structured Error Handling (V3): Attempt to get rich error metadata
|
||||
@@ -207,7 +245,11 @@ export const patch_object = async function patch_object({
|
||||
// Not JSON
|
||||
}
|
||||
|
||||
if (log_lvl) console.log('The response was not ok. Structured Error Check:', error_json);
|
||||
if (log_lvl)
|
||||
console.log(
|
||||
'The response was not ok. Structured Error Check:',
|
||||
error_json
|
||||
);
|
||||
|
||||
if (error_json?.meta?.details) {
|
||||
return error_json;
|
||||
@@ -221,7 +263,10 @@ export const patch_object = async function patch_object({
|
||||
status_code: response.status,
|
||||
details: {
|
||||
category: 'validation',
|
||||
message: typeof error_json.detail === 'string' ? error_json.detail : JSON.stringify(error_json.detail),
|
||||
message:
|
||||
typeof error_json.detail === 'string'
|
||||
? error_json.detail
|
||||
: JSON.stringify(error_json.detail),
|
||||
raw: error_json.detail
|
||||
}
|
||||
}
|
||||
@@ -242,7 +287,11 @@ export const patch_object = async function patch_object({
|
||||
|
||||
// Return the response data or metadata
|
||||
// Robustly handle V3 response envelopes
|
||||
return return_meta ? json : (json.data !== undefined ? json.data : json);
|
||||
return return_meta
|
||||
? json
|
||||
: json.data !== undefined
|
||||
? json.data
|
||||
: json;
|
||||
} catch (error) {
|
||||
console.error(`API PATCH error on attempt ${attempt}:`, error);
|
||||
|
||||
|
||||
@@ -33,7 +33,11 @@ export async function create_ae_obj({
|
||||
// Standard Aether Pattern: Auto-serialize any key ending in _json
|
||||
const cleaned_fields = { ...fields };
|
||||
for (const key in cleaned_fields) {
|
||||
if (key.endsWith('_json') && cleaned_fields[key] !== null && typeof cleaned_fields[key] === 'object') {
|
||||
if (
|
||||
key.endsWith('_json') &&
|
||||
cleaned_fields[key] !== null &&
|
||||
typeof cleaned_fields[key] === 'object'
|
||||
) {
|
||||
if (log_lvl) console.log(`Auto-serializing field: ${key}`);
|
||||
cleaned_fields[key] = JSON.stringify(cleaned_fields[key]);
|
||||
}
|
||||
@@ -94,7 +98,11 @@ export async function create_nested_obj({
|
||||
// Standard Aether Pattern: Auto-serialize any key ending in _json
|
||||
const cleaned_fields = { ...fields };
|
||||
for (const key in cleaned_fields) {
|
||||
if (key.endsWith('_json') && cleaned_fields[key] !== null && typeof cleaned_fields[key] === 'object') {
|
||||
if (
|
||||
key.endsWith('_json') &&
|
||||
cleaned_fields[key] !== null &&
|
||||
typeof cleaned_fields[key] === 'object'
|
||||
) {
|
||||
cleaned_fields[key] = JSON.stringify(cleaned_fields[key]);
|
||||
}
|
||||
}
|
||||
@@ -140,7 +148,11 @@ export async function update_ae_obj({
|
||||
// Standard Aether Pattern: Auto-serialize any key ending in _json
|
||||
const cleaned_fields = { ...fields };
|
||||
for (const key in cleaned_fields) {
|
||||
if (key.endsWith('_json') && cleaned_fields[key] !== null && typeof cleaned_fields[key] === 'object') {
|
||||
if (
|
||||
key.endsWith('_json') &&
|
||||
cleaned_fields[key] !== null &&
|
||||
typeof cleaned_fields[key] === 'object'
|
||||
) {
|
||||
if (log_lvl > 1) console.log(`Auto-serializing field: ${key}`);
|
||||
cleaned_fields[key] = JSON.stringify(cleaned_fields[key]);
|
||||
}
|
||||
@@ -202,7 +214,11 @@ export async function update_nested_obj({
|
||||
// Standard Aether Pattern: Auto-serialize any key ending in _json
|
||||
const cleaned_fields = { ...fields };
|
||||
for (const key in cleaned_fields) {
|
||||
if (key.endsWith('_json') && cleaned_fields[key] !== null && typeof cleaned_fields[key] === 'object') {
|
||||
if (
|
||||
key.endsWith('_json') &&
|
||||
cleaned_fields[key] !== null &&
|
||||
typeof cleaned_fields[key] === 'object'
|
||||
) {
|
||||
cleaned_fields[key] = JSON.stringify(cleaned_fields[key]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,10 @@ interface SearchAeObjV3Params {
|
||||
view?: string;
|
||||
for_obj_type?: string;
|
||||
for_obj_id?: string;
|
||||
order_by_li?: Record<string, 'ASC' | 'DESC'> | Record<string, 'ASC' | 'DESC'>[] | null;
|
||||
order_by_li?:
|
||||
| Record<string, 'ASC' | 'DESC'>
|
||||
| Record<string, 'ASC' | 'DESC'>[]
|
||||
| null;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
delay_ms?: number;
|
||||
@@ -55,7 +58,10 @@ export async function search_ae_obj({
|
||||
|
||||
// Serialize any complex objects in the query params (e.g. ft_qry, lk_qry)
|
||||
for (const key in query_params) {
|
||||
if (typeof query_params[key] === 'object' && query_params[key] !== null) {
|
||||
if (
|
||||
typeof query_params[key] === 'object' &&
|
||||
query_params[key] !== null
|
||||
) {
|
||||
query_params[key] = JSON.stringify(query_params[key]);
|
||||
}
|
||||
}
|
||||
@@ -76,4 +82,4 @@ export async function search_ae_obj({
|
||||
data: search_query,
|
||||
log_lvl
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,9 @@ export const post_object = async function post_object({
|
||||
retry_count?: number;
|
||||
}) {
|
||||
if (log_lvl) {
|
||||
console.log(`*** post_object() *** Endpoint: ${endpoint} Task ID: ${task_id}`);
|
||||
console.log(
|
||||
`*** post_object() *** Endpoint: ${endpoint} Task ID: ${task_id}`
|
||||
);
|
||||
console.log('Params:', params);
|
||||
if (log_lvl > 1) {
|
||||
console.log('Data:', data);
|
||||
@@ -65,7 +67,9 @@ export const post_object = async function post_object({
|
||||
// Construct the URL with query parameters
|
||||
const url = new URL(endpoint, api_cfg['base_url']);
|
||||
if (params) {
|
||||
Object.keys(params).forEach((key) => url.searchParams.append(key, params[key]));
|
||||
Object.keys(params).forEach((key) =>
|
||||
url.searchParams.append(key, params[key])
|
||||
);
|
||||
}
|
||||
|
||||
// Clean and merge headers
|
||||
@@ -95,14 +99,19 @@ export const post_object = async function post_object({
|
||||
}
|
||||
|
||||
// Handle "Bootstrap Paradox" for unauthenticated requests
|
||||
const bypass_val = merged_headers['x-no-account-id'] || merged_headers['x_no_account_id'];
|
||||
const is_valid_bypass = bypass_val === 'bypass' ||
|
||||
bypass_val === 'Nothing to See Here' ||
|
||||
params['key'] ||
|
||||
bypass_val === 'direct-download';
|
||||
const bypass_val =
|
||||
merged_headers['x-no-account-id'] || merged_headers['x_no_account_id'];
|
||||
const is_valid_bypass =
|
||||
bypass_val === 'bypass' ||
|
||||
bypass_val === 'Nothing to See Here' ||
|
||||
params['key'] ||
|
||||
bypass_val === 'direct-download';
|
||||
|
||||
if (is_valid_bypass) {
|
||||
if (log_lvl > 1) console.log('api_post_object: Valid bypass detected. Stripping account ID context.');
|
||||
if (log_lvl > 1)
|
||||
console.log(
|
||||
'api_post_object: Valid bypass detected. Stripping account ID context.'
|
||||
);
|
||||
delete merged_headers['x-account-id'];
|
||||
delete merged_headers['x_account_id'];
|
||||
} else {
|
||||
@@ -124,11 +133,12 @@ export const post_object = async function post_object({
|
||||
}
|
||||
|
||||
// Auto-inject Authorization header if JWT is present but header is missing
|
||||
let jwt = headers_cleaned['jwt'] ||
|
||||
headers_cleaned['JWT'] ||
|
||||
api_cfg['jwt'] ||
|
||||
api_cfg['headers']?.['jwt'] ||
|
||||
api_cfg['headers']?.['JWT'];
|
||||
let jwt =
|
||||
headers_cleaned['jwt'] ||
|
||||
headers_cleaned['JWT'] ||
|
||||
api_cfg['jwt'] ||
|
||||
api_cfg['headers']?.['jwt'] ||
|
||||
api_cfg['headers']?.['JWT'];
|
||||
|
||||
// Final Fallback: Direct check of primary ae_loc key
|
||||
if (!jwt && typeof localStorage !== 'undefined') {
|
||||
@@ -143,7 +153,11 @@ export const post_object = async function post_object({
|
||||
}
|
||||
}
|
||||
|
||||
if (jwt && !headers_cleaned['Authorization'] && !headers_cleaned['authorization']) {
|
||||
if (
|
||||
jwt &&
|
||||
!headers_cleaned['Authorization'] &&
|
||||
!headers_cleaned['authorization']
|
||||
) {
|
||||
headers_cleaned['Authorization'] = `Bearer ${jwt}`;
|
||||
}
|
||||
|
||||
@@ -186,13 +200,21 @@ export const post_object = async function post_object({
|
||||
console.log('Fetch Options:', fetchOptions);
|
||||
}
|
||||
|
||||
const response = await fetch_method(url.toString(), fetchOptions).catch(function (
|
||||
error: any
|
||||
) {
|
||||
const response = await fetch_method(
|
||||
url.toString(),
|
||||
fetchOptions
|
||||
).catch(function (error: any) {
|
||||
// SILENCE NOISE: Aborted requests shouldn't spam logs at log_lvl 0
|
||||
if (error.name === 'AbortError' || error.message?.includes('aborted') || error.name === 'TypeError') {
|
||||
if (
|
||||
error.name === 'AbortError' ||
|
||||
error.message?.includes('aborted') ||
|
||||
error.name === 'TypeError'
|
||||
) {
|
||||
if (log_lvl > 1) {
|
||||
console.log('API POST: Request was aborted or terminated by browser. Expected during navigation.', error);
|
||||
console.log(
|
||||
'API POST: Request was aborted or terminated by browser. Expected during navigation.',
|
||||
error
|
||||
);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
@@ -206,9 +228,17 @@ export const post_object = async function post_object({
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
// Check if we should stop due to abort or network failure
|
||||
if (response instanceof Error || (response && (response.name === 'TypeError' || response.name === 'AbortError'))) {
|
||||
if (
|
||||
response instanceof Error ||
|
||||
(response &&
|
||||
(response.name === 'TypeError' ||
|
||||
response.name === 'AbortError'))
|
||||
) {
|
||||
if (response.name === 'AbortError') return false;
|
||||
if (log_lvl > 1) console.log('API POST Object: Detected NetworkError or TypeError. Failing fast.');
|
||||
if (log_lvl > 1)
|
||||
console.log(
|
||||
'API POST Object: Detected NetworkError or TypeError. Failing fast.'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -219,30 +249,53 @@ export const post_object = async function post_object({
|
||||
}
|
||||
|
||||
if (log_lvl) {
|
||||
console.log(`Response: status=${response.status} attempt=${attempt}`);
|
||||
console.log(
|
||||
`Response: status=${response.status} attempt=${attempt}`
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
if (response.status === 404) {
|
||||
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;
|
||||
}
|
||||
|
||||
// FAIL FAST (Section 2D): Do not retry on Auth or Client errors (400, 401, 403, 422)
|
||||
if (response.status === 400 || response.status === 401 || response.status === 403 || response.status === 422) {
|
||||
if (log_lvl) console.error(`API Client Failure (${response.status}). Failing fast.`);
|
||||
if (
|
||||
response.status === 400 ||
|
||||
response.status === 401 ||
|
||||
response.status === 403 ||
|
||||
response.status === 422
|
||||
) {
|
||||
if (log_lvl)
|
||||
console.error(
|
||||
`API Client Failure (${response.status}). Failing fast.`
|
||||
);
|
||||
|
||||
if (response.status === 401 || response.status === 403) {
|
||||
console.warn(`AUTH DIAGNOSTICS (POST): Headers sent for ${endpoint}:`, {
|
||||
has_auth: !!headers_cleaned['Authorization'],
|
||||
has_api_key: !!headers_cleaned['x-aether-api-key'],
|
||||
has_account_id: !!headers_cleaned['x-account-id'],
|
||||
jwt_preview: jwt ? `${jwt.slice(0, 8)}...` : 'MISSING'
|
||||
});
|
||||
console.warn(
|
||||
`AUTH DIAGNOSTICS (POST): Headers sent for ${endpoint}:`,
|
||||
{
|
||||
has_auth: !!headers_cleaned['Authorization'],
|
||||
has_api_key:
|
||||
!!headers_cleaned['x-aether-api-key'],
|
||||
has_account_id:
|
||||
!!headers_cleaned['x-account-id'],
|
||||
jwt_preview: jwt
|
||||
? `${jwt.slice(0, 8)}...`
|
||||
: 'MISSING'
|
||||
}
|
||||
);
|
||||
// Signal the root layout to show the session-expired banner.
|
||||
if (browser) ae_auth_error.set({ type: 'expired', ts: Date.now() });
|
||||
if (browser)
|
||||
ae_auth_error.set({
|
||||
type: 'expired',
|
||||
ts: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
// Structured Error Handling (V3): Attempt to get rich error metadata
|
||||
@@ -253,7 +306,11 @@ export const post_object = async function post_object({
|
||||
// Not JSON
|
||||
}
|
||||
|
||||
if (log_lvl) console.log('The response was not ok. Structured Error Check:', error_json);
|
||||
if (log_lvl)
|
||||
console.log(
|
||||
'The response was not ok. Structured Error Check:',
|
||||
error_json
|
||||
);
|
||||
|
||||
if (error_json?.meta?.details) {
|
||||
return error_json;
|
||||
@@ -267,7 +324,10 @@ export const post_object = async function post_object({
|
||||
status_code: response.status,
|
||||
details: {
|
||||
category: 'validation',
|
||||
message: typeof error_json.detail === 'string' ? error_json.detail : JSON.stringify(error_json.detail),
|
||||
message:
|
||||
typeof error_json.detail === 'string'
|
||||
? error_json.detail
|
||||
: JSON.stringify(error_json.detail),
|
||||
raw: error_json.detail
|
||||
}
|
||||
}
|
||||
@@ -311,7 +371,11 @@ export const post_object = async function post_object({
|
||||
|
||||
// Return the response data or metadata
|
||||
// Robustly handle V3 response envelopes
|
||||
return return_meta ? json : (json.data !== undefined ? json.data : json);
|
||||
return return_meta
|
||||
? json
|
||||
: json.data !== undefined
|
||||
? json.data
|
||||
: json;
|
||||
} else {
|
||||
const blob = await response.blob();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user