supastash
Version:
Offline-first sync engine for Supabase in React Native using SQLite
79 lines (78 loc) • 3.11 kB
JavaScript
import { getSupastashConfig } from "../../../core/config";
import { getSupastashDb } from "../../../db/dbInitializer";
import { parseStringifiedFields } from "../../../utils/sync/pushLocal/parseFields";
import { logError, logWarn } from "../../logs";
import { getSafeValue } from "../../serializer";
import { assertTableExists } from "../../tableValidator";
import { buildWhereClause } from "../helpers/remoteDb/queryFilterBuilder";
const warned = new Set();
/**
* Updates data locally, sets synced_at to null pending update to remote server
*
* @param table - The name of the table to update
* @param payload - The payload to update
* @param filters - The filters to apply to the update query
* @returns a data / error object
*/
export async function updateData(table, payload, filters, syncMode, isSingle, preserveTimestamp) {
if (!payload)
throw new Error(`Payload data was not provided for an update call on ${table}`);
if (!table)
throw new Error("Table name was not provided for an update call");
await assertTableExists(table);
const timeStamp = new Date().toISOString();
const newPayload = {
...payload,
synced_at: Object.prototype.hasOwnProperty.call(payload, "synced_at")
? payload.synced_at
: syncMode && (syncMode === "localOnly" || syncMode === "remoteFirst")
? timeStamp
: null,
};
if (!preserveTimestamp || payload.updated_at === undefined) {
if (!warned.has(table) && !getSupastashConfig().debugMode && __DEV__) {
warned.add(table);
logWarn(`[Supastash] updated_at not provided for update call on ${table} – defaulting to ${timeStamp}`);
}
const userUpdatedAt = payload.updated_at;
newPayload.updated_at =
userUpdatedAt !== undefined ? userUpdatedAt : timeStamp;
}
const colArray = Object.keys(newPayload);
const cols = colArray
.filter((col) => col !== "id")
.map((col) => `${col} = ?`)
.join(", ");
const values = colArray
.filter((col) => col !== "id")
.map((c) => getSafeValue(newPayload[c]));
const { clause, values: filterValues } = buildWhereClause(filters ?? []);
try {
const db = await getSupastashDb();
await db.runAsync(`UPDATE ${table} SET ${cols} ${clause}`, [
...values,
...filterValues,
]);
const updatedRow = await db.getAllAsync(`SELECT * FROM ${table} ${clause}`, filterValues);
const result = isSingle && updatedRow
? parseStringifiedFields(updatedRow?.[0])
: !updatedRow
? isSingle
? null
: []
: updatedRow?.map(parseStringifiedFields);
return {
error: null,
data: result,
};
}
catch (error) {
logError(`[Supastash] ${error}`);
return {
error: {
message: error instanceof Error ? error.message : String(error),
},
data: null,
};
}
}