UNPKG

supastash

Version:

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

82 lines (81 loc) 2.93 kB
import { getSupastashConfig } from "../../core/config"; import { getSupastashDb } from "../../db/dbInitializer"; import { tableSchemaData } from "../../store/tableSchemaData"; import { isNetworkError, isOnline } from "../connection"; import log from "../logs"; import { supabaseClientErr } from "../supabaseClientErr"; import { checkIfTableExist } from "../tableValidator"; import { mapPgTypeToSQLite } from "./getKeyType"; import { validatePayload, validatePayloadForTable } from "./validatePayload"; let errorCount = new Map(); async function getTableSchema(table) { const config = getSupastashConfig(); const supabase = config?.supabaseClient; if (!supabase) { throw new Error(`Supabase client not found, ${supabaseClientErr}`); } if (tableSchemaData.has(table)) { return tableSchemaData.get(table); } if (errorCount.get(table) && (errorCount.get(table) || 0) > 3) { return null; } const isConnected = await isOnline(); if (!isConnected) { return null; } const { data, error } = await supabase.rpc("get_table_schema", { table_name: table, }); if (error) { if (!isNetworkError(error)) { log(`[Supastash] Error getting table schema for table ${table}: ${error.message}`); } errorCount.set(table, (errorCount.get(table) || 0) + 1); return null; } if (!data || !Array.isArray(data)) return null; validatePayloadForTable(data); tableSchemaData.set(table, data); return [ ...data, { column_name: "synced_at", data_type: "text", is_nullable: "YES", }, ]; } /** * Creates a table in the database * @param table - The name of the table to create * @param payload - The payload of the table */ export async function createTable(table, payload) { const db = await getSupastashDb(); let newPayload = payload; const isTableExist = await checkIfTableExist(table); if (isTableExist) return; const tableSchema = await getTableSchema(table); if (!tableSchema) { throw new Error(`[Supastash] Can't create table ${table} because no data was found Try creating the table manually using the 'defineLocalSchema()' function. `); } const columns = tableSchema.map((col) => { return `${col.column_name} ${mapPgTypeToSQLite(col.data_type)} ${col.column_name === "id" ? "PRIMARY KEY" : ""} ${col.is_nullable === "YES" ? "" : "NOT NULL"}`; }); validatePayload(newPayload); try { log("Table to be created", columns); // Create the table await db.runAsync(`CREATE TABLE IF NOT EXISTS ${table} (${columns.join(", ")})`); } catch (error) { throw new Error(`Failed to create table ${table}. Use the 'defineLocalSchema()' function to create the table manually. Error: ${error}`); } }