UNPKG

supastash

Version:

Offline-first sync engine for Supabase in React Native using SQLite

79 lines (78 loc) 3.62 kB
import { logWarn } from "../../logs"; import { INDEX_SYNC_MARKS_SQL, SYNC_STATUS_TABLES_SQL, } from "../../schema/createSyncStatus"; import { computeFilterKey } from "./filterKey"; const MILLISECOND = 1; const OLD_DATE = "2000-01-01T00:00:00Z"; const addAMillisecond = (date, table) => { const original = date || OLD_DATE; const timestamp = Date.parse(original); if (isNaN(timestamp)) { logWarn(`[Supastash] Invalid date string found on deleted_at column for ${table}: ${original}`); return original; } return new Date(timestamp + MILLISECOND).toISOString(); }; const addAMillisecondToSyncStatus = (syncStatus) => { return { ...syncStatus, last_created_at: addAMillisecond(syncStatus.last_created_at, syncStatus.table_name), last_synced_at: addAMillisecond(syncStatus.last_synced_at, syncStatus.table_name), last_deleted_at: addAMillisecond(syncStatus.last_deleted_at, syncStatus.table_name), }; }; export async function ensureSyncMarksTable(db) { await db.execAsync(SYNC_STATUS_TABLES_SQL); await db.execAsync(INDEX_SYNC_MARKS_SQL); } export async function selectMarks(db, table, filterKey) { return db.getFirstAsync(`SELECT * FROM supastash_sync_marks WHERE table_name=? AND filter_key=?`, [table, filterKey]); } export async function selectAndAddAMillisecond(db, table, tableFilters) { const filterKey = await computeFilterKey(tableFilters ?? []); const result = await db.getFirstAsync(`SELECT * FROM supastash_sync_marks WHERE table_name=? AND filter_key=?`, [table, filterKey]); if (result) { return addAMillisecondToSyncStatus(result); } return { table_name: table, filter_key: filterKey, filter_json: "{}", last_created_at: OLD_DATE, last_synced_at: OLD_DATE, last_deleted_at: OLD_DATE, }; } export async function upsertMarks(db, row) { const { table_name, filter_key, filter_json = null, last_created_at = null, last_synced_at = null, last_deleted_at = null, } = row; return db.runAsync(`INSERT INTO supastash_sync_marks (table_name, filter_key, filter_json, last_created_at, last_synced_at, last_deleted_at, updated_at) VALUES (?,?,?,?,?,?,datetime('now')) ON CONFLICT(table_name, filter_key) DO UPDATE SET filter_json = excluded.filter_json, last_created_at = COALESCE(excluded.last_created_at, supastash_sync_marks.last_created_at), last_synced_at = COALESCE(excluded.last_synced_at, supastash_sync_marks.last_synced_at), last_deleted_at = COALESCE(excluded.last_deleted_at, supastash_sync_marks.last_deleted_at), updated_at = datetime('now')`, [ table_name, filter_key, filter_json, last_created_at, last_synced_at, last_deleted_at, ]); } export async function resetColumn(db, table, filterKey, col, value, filterJson) { return db.runAsync(`INSERT INTO supastash_sync_marks (table_name, filter_key, filter_json, ${col}, updated_at) VALUES (?,?,?,?,datetime('now')) ON CONFLICT(table_name, filter_key) DO UPDATE SET filter_json = excluded.filter_json, ${col} = excluded.${col}, updated_at = datetime('now')`, [table, filterKey, filterJson, value]); } export async function deleteMarks(db, table, filterKey) { return filterKey ? db.runAsync(`DELETE FROM supastash_sync_marks WHERE table_name=? AND filter_key=?`, [table, filterKey]) : db.runAsync(`DELETE FROM supastash_sync_marks WHERE table_name=?`, [ table, ]); }