Saving a quick snapshot after Gemini changes to Dexie function and processing functions.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user