Saving a quick snapshot after Gemini changes to Dexie function and processing functions.

This commit is contained in:
Scott Idem
2025-11-13 12:12:58 -05:00
parent 848a3e9a4b
commit dfaa27384b
5 changed files with 261 additions and 311 deletions

View File

@@ -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.
// If that fails, it will fall back to bulkPut.
// The function takes a database instance, table name, array of objects, and properties to save.
// It also accepts a log level for debugging purposes.
// Updated 2025-05-09
export async function db_save_ae_obj_li__ae_obj({
db_instance,
table_name,
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);
}
/**
* Extracts the primary key from an object using a prioritized list of possible key names.
* @param obj The object to extract the ID from.
* @param table_name The name of the table, used to construct legacy key names.
* @param log_lvl The logging level.
* @returns The found ID, or undefined if no ID could be found.
*/
function findObjectId(obj: any, table_name: string, log_lvl: number): string | number | undefined {
const potentialKeys = ['id', `${table_name}_id`, `${table_name}_id_random`];
if (!obj_li || obj_li.length === 0) {
if (log_lvl) {
console.log('No objects to save.');
}
return [];
}
for (const key of potentialKeys) {
if (obj[key]) {
if (key !== 'id' && log_lvl > 0) {
console.warn(
`Found legacy ID key "${key}" for table "${table_name}". Consider standardizing to "id".`,
obj
);
}
return obj[key];
}
}
const db_table = db_instance[table_name];
if (!db_table) {
console.error(`Table not found in ${db_instance}: ${table_name}`);
return [];
}
console.error(`Object is missing a valid ID for table "${table_name}". It will be skipped.`, obj);
return undefined;
}
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) {
const obj_record: Record<string, any> = {};
if (!obj_li || obj_li.length === 0) {
if (log_lvl > 0) console.log('No objects to save.');
return [];
}
// Extract only the specified properties to save
for (const prop of properties_to_save) {
obj_record[prop] = obj[prop];
}
const db_table: Table<T> = db_instance.table(table_name);
if (!db_table) {
const errorMsg = `Table not found in Dexie instance: ${table_name}`;
console.error(errorMsg);
throw new Error(errorMsg);
}
// Ensure the `id` field is included
obj_record.id = obj_record.id || obj.id || obj[`${table_name}_id`] || obj[`${table_name}_id_random`];
const dataToSave = obj_li
.map((obj) => {
const record: Partial<T> = {};
if (!obj_record.id) {
console.error(`Object is missing an ID:`, obj);
continue;
}
// Extract only the specified properties to save.
for (const prop of properties_to_save) {
record[prop] = obj[prop];
}
// Prepare data for bulkUpdate or bulkPut
bulkUpdateData.push({
key: obj_record.id,
changes: obj_record,
});
bulkPutData.push(obj_record);
}
// Ensure the primary key is included, attempting to find it from various legacy keys.
const id = findObjectId(obj, table_name, log_lvl);
// Attempt bulkUpdate first
try {
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);
}
}
if (id === undefined) {
return null; // Skip objects without a valid ID.
}
// Use bulkPut for any records that couldn't be updated
try {
const putKeys = await db_table.bulkPut(bulkPutData);
if (log_lvl) {
console.log(`Bulk put completed. Put keys:`, putKeys);
}
return putKeys;
} catch (error) {
// This should not happen if the object is new
console.error(`Bulk put failed. Something likely went wrong!`, error);
return [];
}
(record as any).id = id;
return record;
})
.filter(Boolean) as T[];
if (dataToSave.length === 0) {
if (log_lvl > 0) {
console.warn('All objects were skipped, likely due to missing IDs.');
}
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;
}
}