supastash
Version:
Offline-first sync engine for Supabase in React Native using SQLite
67 lines (66 loc) • 2.82 kB
JavaScript
import { getSupastashDb } from "../../../db/dbInitializer";
import { logError } from "../../logs";
import { getSafeValue } from "../../serializer";
import { parseStringifiedFields } from "../../sync/pushLocal/parseFields";
import { assertTableExists } from "../../tableValidator";
/**
* Inserts data locally, sets synced_at to null pending update to remote server
*
* @param table - The name of the table to insert into
* @param payload - The payload to insert
* @returns a data / error object
*/
export async function insertData(table, payload, syncMode, isSingle) {
if (!table)
throw new Error("Table name was not provided for an insert call");
if (!payload)
throw new Error(`Payload data was not provided for an insert call on ${table}`);
const timeStamp = new Date().toISOString();
const inserted = [];
try {
await assertTableExists(table);
const db = await getSupastashDb();
for (const item of payload) {
if (!item.id) {
throw new Error(`Payload must include a valid 'id' field for inserts.`);
}
const newPayload = {
...item,
created_at: item.created_at ?? timeStamp,
updated_at: item.updated_at ?? timeStamp,
synced_at: Object.prototype.hasOwnProperty.call(item, "synced_at")
? item.synced_at
: syncMode && (syncMode === "localOnly" || syncMode === "remoteFirst")
? timeStamp
: null,
};
const colArray = Object.keys(newPayload);
const cols = colArray.join(", ");
const placeholders = colArray.map(() => "?").join(", ");
const values = colArray.map((c) => getSafeValue(newPayload[c]));
// Check if record already exist
const exists = await db.getFirstAsync(`SELECT 1 FROM ${table} WHERE id = ? LIMIT 1`, [newPayload.id]);
if (exists)
throw new Error(`Record with id ${newPayload.id} already exists in table ${table}`);
// Insert data
await db.runAsync(`INSERT INTO ${table} (${cols}) VALUES (${placeholders})`, values);
const insertedRow = await db.getFirstAsync(`SELECT * FROM ${table} WHERE id = ?`, [newPayload.id]);
if (insertedRow) {
inserted.push(parseStringifiedFields(insertedRow));
}
}
return {
error: null,
data: isSingle ? inserted[0] : inserted,
};
}
catch (error) {
logError(`[Supastash] ${error}`);
return {
error: {
message: error instanceof Error ? error.message : String(error),
},
data: null,
};
}
}