Saving a quick snapshot after Gemini changes to Dexie function and processing functions.
This commit is contained in:
@@ -11,10 +11,10 @@ Core Aether modules
|
|||||||
|
|
||||||
Additional Aether modules
|
Additional Aether modules
|
||||||
* events
|
* events
|
||||||
* presentation management - import the program data (events, session, presentations, presenters, evnet files, locations/rooms, devices)
|
* presentation management - import the program data (events, session, presentations, presenters, event files, locations/rooms, devices)
|
||||||
* launcher - Technically this is used with presentation management. It is part of the native app that uses Electron. One of the libraries is for functions that only work when the site is opened in an Electron app. For example the regular browser can not move files around on the local computer or run local commands.
|
* launcher - Technically this is used with presentation management. It is part of the native app that uses Electron. One of the libraries is for functions that only work when the site is opened in an Electron app. For example the regular browser can not move files around on the local computer or run local commands.
|
||||||
* badge printing
|
* badge printing
|
||||||
* lead retreavl - attendee tracking; QR codes
|
* lead retrieval - attendee tracking; QR codes
|
||||||
* journals - journal, documentation, notes, diary, blog, etc
|
* journals - journal, documentation, notes, diary, blog, etc
|
||||||
* idaa - One of my clients
|
* idaa - One of my clients
|
||||||
|
|
||||||
|
|||||||
@@ -1,248 +1,174 @@
|
|||||||
import type { key_val } from '$lib/ae_stores';
|
import type { key_val } from '$lib/ae_stores';
|
||||||
import { get_object } from './api_get_object';
|
import { get_object } from './api_get_object';
|
||||||
|
|
||||||
// The lookup "obj_type" should broken out into a separate function. - 2024-08-07
|
// Refactored 2025-11-13 to use a lookup map for endpoints.
|
||||||
// Updated 2023-11-15
|
const objTypeToEndpointMap: Record<string, string> = {
|
||||||
export async function get_ae_obj_li_for_obj_id_crud_v2(
|
account: '/crud/account/list',
|
||||||
{
|
address: '/crud/address/list',
|
||||||
api_cfg,
|
archive: '/crud/archive/list',
|
||||||
obj_type,
|
archive_content: '/crud/archive/content/list',
|
||||||
for_obj_type,
|
contact: '/crud/contact/list',
|
||||||
for_obj_id, // NOTE: Changed 2023-12-06 to no longer required
|
data_store: '/crud/data_store/list',
|
||||||
use_alt_tbl = false, // Alternate table or view name
|
event: '/crud/event/list',
|
||||||
use_alt_mdl = false, // Alternate model name
|
event_abstract: '/crud/event/abstract/list',
|
||||||
use_alt_exp = false, // Alternate export table or view name
|
event_badge: '/crud/event/badge/list',
|
||||||
inc = {},
|
event_badge_template: '/crud/event/badge/template/list',
|
||||||
enabled = 'enabled',
|
event_device: '/crud/event/device/list',
|
||||||
hidden = 'not_hidden',
|
event_exhibit: '/crud/event/exhibit/list',
|
||||||
order_by_li = null,
|
event_exhibit_tracking: '/crud/event/exhibit/tracking/list',
|
||||||
limit = 999999,
|
event_file: '/crud/event/file/list',
|
||||||
offset = 0,
|
event_location: '/crud/event/location/list',
|
||||||
// key,
|
event_person: '/crud/event/person/list',
|
||||||
// jwt = null,
|
event_presentation: '/crud/event/presentation/list',
|
||||||
headers = {},
|
event_presenter: '/crud/event/presenter/list',
|
||||||
params_json = null, // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the API endpoint. Example: { "fulltext_search": { "default_qry_str": "Search string for default", "address_default_qry_str": "Search string for address", "contact_1_default_qry_str": "Search string for contact_1" } }
|
event_session: '/crud/event/session/list',
|
||||||
// json_obj = null, // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
|
event_track: '/crud/event/track/list',
|
||||||
params = {},
|
grant: '/crud/grant/list',
|
||||||
// return_meta = false,
|
hosted_file: '/crud/hosted_file/list',
|
||||||
log_lvl = 0
|
journal: '/crud/journal/list',
|
||||||
}: {
|
journal_entry: '/crud/journal/entry/list',
|
||||||
api_cfg: any,
|
order: '/crud/order/list',
|
||||||
obj_type: string,
|
order_line: '/crud/order/line/list',
|
||||||
for_obj_type: string,
|
page: '/crud/page/list',
|
||||||
for_obj_id?: string,
|
person: '/crud/person/list',
|
||||||
use_alt_tbl?: boolean|string,
|
post: '/crud/post/list',
|
||||||
use_alt_mdl?: boolean|string,
|
post_comment: '/crud/post/comment/list',
|
||||||
use_alt_exp?: boolean|string,
|
site: '/crud/site/list',
|
||||||
inc?: key_val
|
sponsorship_cfg: '/crud/sponsorship/cfg/list',
|
||||||
enabled?: string,
|
sponsorship: '/crud/sponsorship/list',
|
||||||
hidden?: string,
|
// user: '/crud/user/list',
|
||||||
order_by_li?: any,
|
'lu-country_subdivision': '/crud/lu/country_subdivision/list',
|
||||||
limit?: number,
|
'lu-country': '/crud/lu/country/list',
|
||||||
offset?: number,
|
'lu-time_zone': '/crud/lu/time_zone/list'
|
||||||
// key: string,
|
};
|
||||||
// jwt?: string,
|
|
||||||
headers?: any,
|
|
||||||
params_json?: any,
|
|
||||||
// json_obj?: any,
|
|
||||||
params?: key_val,
|
|
||||||
// return_meta?: boolean,
|
|
||||||
log_lvl?: number
|
|
||||||
}
|
|
||||||
) {
|
|
||||||
if (log_lvl) {
|
|
||||||
console.log('*** get_ae_obj_li_for_obj_id_crud() ***');
|
|
||||||
}
|
|
||||||
|
|
||||||
// data = {};
|
function getEndpointForObjType(obj_type: string, for_obj_type?: string): string {
|
||||||
// data['super_key'] = key;
|
if (obj_type === 'lu' && for_obj_type) {
|
||||||
// data['jwt'] = jwt;
|
const key = `lu-${for_obj_type}`;
|
||||||
// NOTE: The key and or JWT should be in the header of the DELETE, GET, PATCH, POST
|
const endpoint = objTypeToEndpointMap[key];
|
||||||
|
if (endpoint) return endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
// const endpoint = `/crud/${obj_type}/list`;
|
const endpoint = objTypeToEndpointMap[obj_type];
|
||||||
|
if (endpoint) return endpoint;
|
||||||
|
|
||||||
let endpoint = '';
|
throw new Error(`Unknown object type: ${obj_type}`);
|
||||||
if (obj_type == 'account') {
|
}
|
||||||
endpoint = `/crud/account/list`;
|
|
||||||
} else if (obj_type == 'address') {
|
|
||||||
endpoint = `/crud/address/list`;
|
|
||||||
} else if (obj_type == 'archive') {
|
|
||||||
endpoint = `/crud/archive/list`;
|
|
||||||
} else if (obj_type == 'archive_content') {
|
|
||||||
endpoint = `/crud/archive/content/list`;
|
|
||||||
} else if (obj_type == 'contact') {
|
|
||||||
endpoint = `/crud/contact/list`;
|
|
||||||
} else if (obj_type == 'data_store') {
|
|
||||||
endpoint = `/crud/data_store/list`;
|
|
||||||
} else if (obj_type == 'event') {
|
|
||||||
endpoint = `/crud/event/list`;
|
|
||||||
} else if (obj_type == 'event_abstract') {
|
|
||||||
endpoint = `/crud/event/abstract/list`;
|
|
||||||
} else if (obj_type == 'event_badge') {
|
|
||||||
endpoint = `/crud/event/badge/list`;
|
|
||||||
} else if (obj_type == 'event_badge_template') {
|
|
||||||
endpoint = `/crud/event/badge/template/list`;
|
|
||||||
} else if (obj_type == 'event_device') {
|
|
||||||
endpoint = `/crud/event/device/list`;
|
|
||||||
} else if (obj_type == 'event_exhibit') {
|
|
||||||
endpoint = `/crud/event/exhibit/list`;
|
|
||||||
} else if (obj_type == 'event_exhibit_tracking') {
|
|
||||||
endpoint = `/crud/event/exhibit/tracking/list`;
|
|
||||||
} else if (obj_type == 'event_file') {
|
|
||||||
endpoint = `/crud/event/file/list`;
|
|
||||||
} else if (obj_type == 'event_location') {
|
|
||||||
endpoint = `/crud/event/location/list`;
|
|
||||||
} else if (obj_type == 'event_person') {
|
|
||||||
endpoint = `/crud/event/person/list`;
|
|
||||||
} else if (obj_type == 'event_presentation') {
|
|
||||||
endpoint = `/crud/event/presentation/list`;
|
|
||||||
} else if (obj_type == 'event_presenter') {
|
|
||||||
endpoint = `/crud/event/presenter/list`;
|
|
||||||
} else if (obj_type == 'event_session') {
|
|
||||||
endpoint = `/crud/event/session/list`;
|
|
||||||
} else if (obj_type == 'event_track') {
|
|
||||||
endpoint = `/crud/event/track/list`;
|
|
||||||
} else if (obj_type == 'grant') {
|
|
||||||
endpoint = `/crud/grant/list`;
|
|
||||||
} else if (obj_type == 'hosted_file') {
|
|
||||||
endpoint = `/crud/hosted_file/list`;
|
|
||||||
} else if (obj_type == 'journal') {
|
|
||||||
endpoint = `/crud/journal/list`;
|
|
||||||
} else if (obj_type == 'journal_entry') {
|
|
||||||
endpoint = `/crud/journal/entry/list`;
|
|
||||||
} else if (obj_type == 'order') {
|
|
||||||
endpoint = `/crud/order/list`;
|
|
||||||
} else if (obj_type == 'order_line') {
|
|
||||||
endpoint = `/crud/order/line/list`;
|
|
||||||
} else if (obj_type == 'page') {
|
|
||||||
endpoint = `/crud/page/list`;
|
|
||||||
} else if (obj_type == 'person') {
|
|
||||||
endpoint = `/crud/person/list`;
|
|
||||||
} else if (obj_type == 'post') {
|
|
||||||
endpoint = `/crud/post/list`;
|
|
||||||
} else if (obj_type == 'post_comment') {
|
|
||||||
endpoint = `/crud/post/comment/list`;
|
|
||||||
} else if (obj_type == 'site') {
|
|
||||||
endpoint = `/crud/site/list`;
|
|
||||||
} else if (obj_type == 'sponsorship_cfg') {
|
|
||||||
endpoint = `/crud/sponsorship/cfg/list`;
|
|
||||||
} else if (obj_type == 'sponsorship') {
|
|
||||||
endpoint = `/crud/sponsorship/list`;
|
|
||||||
// } else if (obj_type == 'user') {
|
|
||||||
// endpoint = `/crud/user/list`;
|
|
||||||
} else if (obj_type == 'lu' && for_obj_type == 'country_subdivision') {
|
|
||||||
endpoint = `/crud/lu/country_subdivision/list`;
|
|
||||||
// for_obj_type = null;
|
|
||||||
} else if (obj_type == 'lu' && for_obj_type == 'country') {
|
|
||||||
endpoint = `/crud/lu/country/list`;
|
|
||||||
// for_obj_type = null;
|
|
||||||
} else if (obj_type == 'lu' && for_obj_type == 'time_zone') {
|
|
||||||
endpoint = `/crud/lu/time_zone/list`;
|
|
||||||
// for_obj_type = null;
|
|
||||||
} else {
|
|
||||||
console.log(`Unknown object type: ${obj_type}`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
endpoint = `/v2${endpoint}`;
|
|
||||||
if (log_lvl) {
|
|
||||||
console.log('Endpoint:', endpoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to remove a few parameters from the params object that are not allowed.
|
type OrderBy = { [key: string]: 'ASC' | 'DESC' };
|
||||||
delete params['qry__enabled'];
|
|
||||||
delete params['qry__hidden'];
|
|
||||||
delete params['qry__limit'];
|
|
||||||
delete params['qry__offset'];
|
|
||||||
|
|
||||||
|
interface GetAeObjLiForObjIdCrudV2Params {
|
||||||
|
api_cfg: any; // Consider defining a specific type for api_cfg
|
||||||
|
obj_type: string;
|
||||||
|
for_obj_type: string;
|
||||||
|
for_obj_id?: string;
|
||||||
|
use_alt_tbl?: boolean | string;
|
||||||
|
use_alt_mdl?: boolean | string;
|
||||||
|
use_alt_exp?: boolean | string;
|
||||||
|
inc?: key_val;
|
||||||
|
enabled?: 'all' | 'enabled' | 'not_enabled';
|
||||||
|
hidden?: 'all' | 'hidden' | 'not_hidden';
|
||||||
|
order_by_li?: OrderBy[] | null;
|
||||||
|
limit?: number;
|
||||||
|
offset?: number;
|
||||||
|
headers?: Record<string, string>;
|
||||||
|
params_json?: any;
|
||||||
|
params?: key_val;
|
||||||
|
log_lvl?: number;
|
||||||
|
}
|
||||||
|
|
||||||
if (for_obj_type) {
|
export async function get_ae_obj_li_for_obj_id_crud_v2({
|
||||||
params['for_obj_type'] = for_obj_type;
|
api_cfg,
|
||||||
}
|
obj_type,
|
||||||
if (for_obj_id) {
|
for_obj_type,
|
||||||
params['for_obj_id'] = for_obj_id;
|
for_obj_id,
|
||||||
}
|
use_alt_tbl = false,
|
||||||
|
use_alt_mdl = false,
|
||||||
|
use_alt_exp = false,
|
||||||
|
enabled = 'enabled',
|
||||||
|
hidden = 'not_hidden',
|
||||||
|
order_by_li = null,
|
||||||
|
limit = 999999,
|
||||||
|
offset = 0,
|
||||||
|
headers = {},
|
||||||
|
params_json = null,
|
||||||
|
params = {},
|
||||||
|
log_lvl = 0
|
||||||
|
}: GetAeObjLiForObjIdCrudV2Params) {
|
||||||
|
if (log_lvl) {
|
||||||
|
console.log('*** get_ae_obj_li_for_obj_id_crud_v2() ***');
|
||||||
|
}
|
||||||
|
|
||||||
if (use_alt_tbl === true) {
|
try {
|
||||||
params['tbl_alt'] = 'alt'; // Use alternate table or view name
|
const endpoint = `/v2${getEndpointForObjType(obj_type, for_obj_type)}`;
|
||||||
}
|
if (log_lvl) {
|
||||||
if (use_alt_mdl === true) {
|
console.log('Endpoint:', endpoint);
|
||||||
params['mdl_alt'] = 'alt'; // Use alternate model name
|
}
|
||||||
}
|
|
||||||
if (use_alt_exp === true) {
|
|
||||||
params['exp_alt'] = 'alt'; // Use alternate export table or view name
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// We need to remove a few parameters from the params object that are not allowed.
|
||||||
|
delete params['qry__enabled'];
|
||||||
|
delete params['qry__hidden'];
|
||||||
|
delete params['qry__limit'];
|
||||||
|
delete params['qry__offset'];
|
||||||
|
|
||||||
// Need to deal with inc params here???
|
if (for_obj_type) params['for_obj_type'] = for_obj_type;
|
||||||
|
if (for_obj_id) params['for_obj_id'] = for_obj_id;
|
||||||
|
|
||||||
|
if (use_alt_tbl === true) params['tbl_alt'] = 'alt';
|
||||||
|
if (use_alt_mdl === true) params['mdl_alt'] = 'alt';
|
||||||
|
if (use_alt_exp === true) params['exp_alt'] = 'alt';
|
||||||
|
|
||||||
let allowed_enabled_list = ['all', 'enabled', 'not_enabled']
|
const allowed_enabled_list = ['all', 'enabled', 'not_enabled'];
|
||||||
if (allowed_enabled_list.includes(enabled) ) {
|
if (allowed_enabled_list.includes(enabled)) {
|
||||||
params['enabled'] = enabled;
|
params['enabled'] = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
let allowed_hidden_list = ['all', 'hidden', 'not_hidden'];
|
const allowed_hidden_list = ['all', 'hidden', 'not_hidden'];
|
||||||
if (allowed_hidden_list.includes(hidden) ) {
|
if (allowed_hidden_list.includes(hidden)) {
|
||||||
params['hidden'] = hidden;
|
params['hidden'] = hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 URL GET params do not handle complex objects very well.
|
||||||
// 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'] = JSON.stringify(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) params['limit'] = limit;
|
||||||
params['limit'] = limit;
|
if (offset > 0) params['offset'] = offset;
|
||||||
}
|
|
||||||
|
|
||||||
if (offset > 0) {
|
if (params_json) {
|
||||||
params['offset'] = offset;
|
// NOTE: "jp" stands for "JSON Params". This is a JSON object that needs to be safely converted to a string for the params.
|
||||||
}
|
// Max characters for a GET request is ~2000. This is a limitation of the browser.
|
||||||
|
const json_params_str = encodeURIComponent(JSON.stringify(params_json));
|
||||||
|
if (json_params_str.length > 2083) {
|
||||||
|
// Using console.error instead of throwing an error to avoid crashing the app for a known limitation.
|
||||||
|
console.error(
|
||||||
|
`The JSON object is too large to be used as a GET parameter. Max length is 2083 characters. Length = ${json_params_str.length}`
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
params['jp'] = json_params_str;
|
||||||
|
}
|
||||||
|
|
||||||
if (params_json) {
|
if (log_lvl) {
|
||||||
// NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
|
console.log('Params:', params);
|
||||||
// Max characters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
|
}
|
||||||
if (log_lvl) {
|
|
||||||
console.log('JSON Object:', params_json);
|
|
||||||
console.log(JSON.stringify(params_json));
|
|
||||||
}
|
|
||||||
// NOTE: "jp" stands for "JSON Params"
|
|
||||||
params['jp'] = encodeURIComponent(JSON.stringify(params_json));
|
|
||||||
if (params['jp'].length > 2083) {
|
|
||||||
console.log(`The JSON object is too large to be used as a GET parameter. The overall max URL length is 2083 characters. Please use the POST endpoint instead. Length = ${params['jp'].length} [THIS DOES NOT EXIST YET]`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (json_obj) {
|
const object_li_get_promise = await get_object({
|
||||||
// // NOTE: This is a JSON object that needs to be safely converted to a string for the params. This is used for the search endpoint.
|
api_cfg: api_cfg,
|
||||||
// // Max characters for a GET request is 2083. This is a limitation of the browser (Microsoft IE and Edge).
|
endpoint: endpoint,
|
||||||
// console.log('JSON Object:', json_obj);
|
headers: headers,
|
||||||
// params['json_str'] = encodeURIComponent(JSON.stringify(json_obj));
|
params: params,
|
||||||
// if (params['json_str'].length > 2083) {
|
log_lvl: log_lvl
|
||||||
// console.log(`The JSON object is too large to be used as a GET parameter. The overall max URL length is 2083 characters. Please use the POST endpoint instead. Length = ${params['json_str'].length} [THIS DOES NOT EXIST YET]`);
|
});
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (log_lvl) {
|
if (log_lvl > 1) {
|
||||||
console.log('Params:', params);
|
console.log(object_li_get_promise);
|
||||||
}
|
}
|
||||||
|
|
||||||
let object_li_get_promise = await get_object({
|
return object_li_get_promise;
|
||||||
api_cfg: api_cfg,
|
} catch (error) {
|
||||||
endpoint: endpoint,
|
console.error('Error in get_ae_obj_li_for_obj_id_crud_v2:', error);
|
||||||
headers: headers,
|
return false; // Or handle the error as appropriate
|
||||||
params: params,
|
}
|
||||||
// return_meta: return_meta,
|
}
|
||||||
log_lvl: log_lvl
|
|
||||||
});
|
|
||||||
|
|
||||||
if (log_lvl > 1) {
|
|
||||||
console.log(object_li_get_promise);
|
|
||||||
}
|
|
||||||
|
|
||||||
return object_li_get_promise;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,91 +1,115 @@
|
|||||||
|
import type { Dexie, Table } from 'dexie';
|
||||||
|
|
||||||
// This function will save an array of objects to a Dexie database table.
|
/**
|
||||||
// It will first attempt to update existing records using bulkUpdate.
|
* Extracts the primary key from an object using a prioritized list of possible key names.
|
||||||
// If that fails, it will fall back to bulkPut.
|
* @param obj The object to extract the ID from.
|
||||||
// The function takes a database instance, table name, array of objects, and properties to save.
|
* @param table_name The name of the table, used to construct legacy key names.
|
||||||
// It also accepts a log level for debugging purposes.
|
* @param log_lvl The logging level.
|
||||||
// Updated 2025-05-09
|
* @returns The found ID, or undefined if no ID could be found.
|
||||||
export async function db_save_ae_obj_li__ae_obj({
|
*/
|
||||||
db_instance,
|
function findObjectId(obj: any, table_name: string, log_lvl: number): string | number | undefined {
|
||||||
table_name,
|
const potentialKeys = ['id', `${table_name}_id`, `${table_name}_id_random`];
|
||||||
obj_li,
|
|
||||||
properties_to_save,
|
|
||||||
log_lvl = 0,
|
|
||||||
}: {
|
|
||||||
db_instance: any; // The Dexie database instance
|
|
||||||
table_name: string; // The name of the table in the database
|
|
||||||
obj_li: any[];
|
|
||||||
properties_to_save: string[];
|
|
||||||
log_lvl?: number;
|
|
||||||
}) {
|
|
||||||
// log_lvl = 1;
|
|
||||||
if (log_lvl) {
|
|
||||||
console.log(`*** db_save_ae_obj_li__ae_obj() *** table_name=${table_name}`, obj_li);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!obj_li || obj_li.length === 0) {
|
for (const key of potentialKeys) {
|
||||||
if (log_lvl) {
|
if (obj[key]) {
|
||||||
console.log('No objects to save.');
|
if (key !== 'id' && log_lvl > 0) {
|
||||||
}
|
console.warn(
|
||||||
return [];
|
`Found legacy ID key "${key}" for table "${table_name}". Consider standardizing to "id".`,
|
||||||
}
|
obj
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return obj[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const db_table = db_instance[table_name];
|
console.error(`Object is missing a valid ID for table "${table_name}". It will be skipped.`, obj);
|
||||||
if (!db_table) {
|
return undefined;
|
||||||
console.error(`Table not found in ${db_instance}: ${table_name}`);
|
}
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
const bulkUpdateData = [];
|
/**
|
||||||
const bulkPutData = [];
|
* Saves an array of objects to a Dexie database table using bulkPut.
|
||||||
|
* This function handles both creating new records and updating existing ones.
|
||||||
|
*
|
||||||
|
* @param db_instance The Dexie database instance.
|
||||||
|
* @param table_name The name of the table in the database.
|
||||||
|
* @param obj_li The array of objects to save.
|
||||||
|
* @param properties_to_save The list of property names to include in the saved object.
|
||||||
|
* @param log_lvl The logging level for debugging.
|
||||||
|
* @returns A promise that resolves with the keys of the saved objects.
|
||||||
|
* @throws An error if the database operation fails.
|
||||||
|
*
|
||||||
|
* @version 2.0.0
|
||||||
|
* @since 2025-11-13
|
||||||
|
*/
|
||||||
|
export async function db_save_ae_obj_li__ae_obj<T extends Record<string, any>>({
|
||||||
|
db_instance,
|
||||||
|
table_name,
|
||||||
|
obj_li,
|
||||||
|
properties_to_save,
|
||||||
|
log_lvl = 0
|
||||||
|
}: {
|
||||||
|
db_instance: Dexie;
|
||||||
|
table_name: string;
|
||||||
|
obj_li: T[];
|
||||||
|
properties_to_save: (keyof T)[];
|
||||||
|
log_lvl?: number;
|
||||||
|
}) {
|
||||||
|
if (log_lvl > 0) {
|
||||||
|
console.log(
|
||||||
|
`*** db_save_ae_obj_li__ae_obj: Attempting to save ${obj_li.length} objects to table "${table_name}" ***`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
for (const obj of obj_li) {
|
if (!obj_li || obj_li.length === 0) {
|
||||||
const obj_record: Record<string, any> = {};
|
if (log_lvl > 0) console.log('No objects to save.');
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
// Extract only the specified properties to save
|
const db_table: Table<T> = db_instance.table(table_name);
|
||||||
for (const prop of properties_to_save) {
|
if (!db_table) {
|
||||||
obj_record[prop] = obj[prop];
|
const errorMsg = `Table not found in Dexie instance: ${table_name}`;
|
||||||
}
|
console.error(errorMsg);
|
||||||
|
throw new Error(errorMsg);
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure the `id` field is included
|
const dataToSave = obj_li
|
||||||
obj_record.id = obj_record.id || obj.id || obj[`${table_name}_id`] || obj[`${table_name}_id_random`];
|
.map((obj) => {
|
||||||
|
const record: Partial<T> = {};
|
||||||
|
|
||||||
if (!obj_record.id) {
|
// Extract only the specified properties to save.
|
||||||
console.error(`Object is missing an ID:`, obj);
|
for (const prop of properties_to_save) {
|
||||||
continue;
|
record[prop] = obj[prop];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare data for bulkUpdate or bulkPut
|
// Ensure the primary key is included, attempting to find it from various legacy keys.
|
||||||
bulkUpdateData.push({
|
const id = findObjectId(obj, table_name, log_lvl);
|
||||||
key: obj_record.id,
|
|
||||||
changes: obj_record,
|
|
||||||
});
|
|
||||||
bulkPutData.push(obj_record);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt bulkUpdate first
|
if (id === undefined) {
|
||||||
try {
|
return null; // Skip objects without a valid ID.
|
||||||
const updatedKeys = await db_table.bulkUpdate(bulkUpdateData);
|
}
|
||||||
if (log_lvl) {
|
|
||||||
console.log(`Bulk update completed. Updated keys:`, updatedKeys);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// This is fairly common and normal if the object is new
|
|
||||||
if (log_lvl) {
|
|
||||||
console.log(`Bulk update failed. Falling back to bulkPut. This is normal.`, error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use bulkPut for any records that couldn't be updated
|
(record as any).id = id;
|
||||||
try {
|
return record;
|
||||||
const putKeys = await db_table.bulkPut(bulkPutData);
|
})
|
||||||
if (log_lvl) {
|
.filter(Boolean) as T[];
|
||||||
console.log(`Bulk put completed. Put keys:`, putKeys);
|
|
||||||
}
|
if (dataToSave.length === 0) {
|
||||||
return putKeys;
|
if (log_lvl > 0) {
|
||||||
} catch (error) {
|
console.warn('All objects were skipped, likely due to missing IDs.');
|
||||||
// This should not happen if the object is new
|
}
|
||||||
console.error(`Bulk put failed. Something likely went wrong!`, error);
|
return [];
|
||||||
return [];
|
}
|
||||||
}
|
|
||||||
|
try {
|
||||||
|
// bulkPut efficiently handles both inserts and updates.
|
||||||
|
const keys = await db_table.bulkPut(dataToSave);
|
||||||
|
if (log_lvl > 0) {
|
||||||
|
console.log(`Successfully saved ${keys.length} objects to "${table_name}".`);
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to save objects to "${table_name}":`, error);
|
||||||
|
// Re-throw the error to let the caller handle it.
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
import type { key_val } from '$lib/ae_stores';
|
import type { key_val } from '$lib/ae_stores';
|
||||||
import { api } from '$lib/api';
|
import { api } from '$lib/api';
|
||||||
|
|
||||||
import { db_save_ae_obj_li__ae_obj } from "$lib/ae_core/core__idb_dexie";
|
import { db_save_ae_obj_li__ae_obj } from '$lib/ae_core/core__idb_dexie';
|
||||||
import { db_events } from "$lib/ae_events/db_events";
|
import { db_events } from '$lib/ae_events/db_events';
|
||||||
|
|
||||||
import { load_ae_obj_li__event_device } from './ae_events__event_device';
|
import { load_ae_obj_li__event_device } from './ae_events__event_device';
|
||||||
import { load_ae_obj_li__event_location } from './ae_events__event_location';
|
import { load_ae_obj_li__event_location } from './ae_events__event_location';
|
||||||
import { load_ae_obj_li__event_session } from './ae_events__event_session';
|
import { load_ae_obj_li__event_session } from './ae_events__event_session';
|
||||||
import { load_ae_obj_li__event_badge_template } from "$lib/ae_events/ae_events__event_badge_template";
|
import { load_ae_obj_li__event_badge_template } from '$lib/ae_events/ae_events__event_badge_template';
|
||||||
|
|
||||||
let ae_promises: key_val = {};
|
let ae_promises: key_val = {};
|
||||||
|
|
||||||
|
|||||||
@@ -998,4 +998,4 @@ export async function process_ae_obj__journal_props(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return processed_obj_li;
|
return processed_obj_li;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user