supastash
Version:
Offline-first sync engine for Supabase in React Native using SQLite
124 lines (123 loc) • 4.44 kB
JavaScript
let _config = {
dbName: "supastash_db",
supabaseClient: null,
sqliteClient: null,
sqliteClientType: null,
excludeTables: { pull: [], push: [] },
pollingInterval: {
pull: 30000,
push: 30000,
},
syncEngine: {
push: true,
pull: true,
useFiltersFromStore: true,
},
listeners: 250,
debugMode: true,
};
let _configured = false;
/**
* Initializes the Supastash client.
*
* This must be called **once** during app startup (e.g., in `_layout.tsx` or `App.tsx`)
* before using any Supastash hooks or features.
*
* ⚠️ Pull sync is **disabled by default** to avoid unfiltered data fetches.
* Enable it only if you've configured **Row Level Security (RLS)** on your Supabase tables.
* The `useSupatashData` hook always performs filtered pull queries when `filter` is provided in the `options`, making it safe to use even when pull is disabled globally.
*
* @example
* import { supabase } from "./supabase";
* import { openDatabaseAsync } from "expo-sqlite";
* import { configureSupastash, defineLocalSchema } from "supastash";
*
* configureSupastash({
* dbName: "supastash_db",
* supabaseClient: supabase,
* sqliteClient: { openDatabaseAsync },
* sqliteClientType: "expo",
* onSchemaInit: () => {
* defineLocalSchema("users", {
* id: "TEXT PRIMARY KEY",
* name: "TEXT",
* email: "TEXT",
* created_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP",
* updated_at: "TIMESTAMP DEFAULT CURRENT_TIMESTAMP",
* });
* },
* });
*
* @param config - Configuration options for Supastash
* @param config.dbName - SQLite database name (default: `"supastash_db"`)
* @param config.supabaseClient - Supabase client instance (**required**)
* @param config.sqliteClient - SQLite client adapter (**required**)
* @param config.sqliteClientType - SQLite engine: `"expo" | "rn-storage" | "rn-nitro"` (**required**)
* @param config.onSchemaInit - Optional callback to define local table schemas
* @param config.debugMode - Enables debug logging (default: `false`)
* @param config.listeners - Max number of active Realtime subscriptions (default: `250`)
* @param config.excludeTables - Tables to exclude from sync (default: `{ pull: [], push: [] }`)
* @param config.pollingInterval - Polling interval for sync (default: `{ pull: 30000, push: 30000 }`)
* @param config.syncEngine - Control pull/push sync behavior (`push: true`, `pull: false` by default, `useFiltersFromStore: true` by default)
*/
export function configureSupastash(config) {
_config = {
..._config,
...config,
syncEngine: {
..._config.syncEngine,
...config.syncEngine,
},
excludeTables: {
pull: config.excludeTables?.pull ?? _config.excludeTables?.pull ?? [],
push: config.excludeTables?.push ?? _config.excludeTables?.push ?? [],
},
pollingInterval: {
pull: config.pollingInterval?.pull ?? _config.pollingInterval?.pull ?? 30000,
push: config.pollingInterval?.push ?? _config.pollingInterval?.push ?? 30000,
},
};
_configured = true;
}
/**
* Returns the current Supastash configuration.
*
* Throws an error if `configureSupastash` has not been called.
*
* @returns {SupastashConfig<T>} The active Supastash configuration
*
* @throws Will throw if Supastash is not configured or if essential values like
* `supabaseClient` or `sqliteClient` are missing.
*
* @example
* const config = getSupastashConfig();
* const dbName = config.dbName;
*/
export function getSupastashConfig() {
return _config;
}
/**
* Wrapper for `configureSupastash` that takes a strongly typed object containing
* the Supastash config, including optional schema initialization.
*
* Useful for abstracting config logic into a central setup file.
*
* @param config.dbOptions - The Supastash configuration object
* @param config.dbOptions.onSchemaInit - Optional callback to define the local schema
*
* @example
* defineSupastashConfig({
* dbOptions: {
* dbName: "supastash_db",
* supabaseClient,
* sqliteClient,
* sqliteClientType: "expo",
* onSchemaInit: () => {
* defineLocalSchema("orders", { id: "TEXT PRIMARY KEY", status: "TEXT" });
* },
* },
* });
*/
export function defineSupastashConfig(config) {
configureSupastash(config.dbOptions);
}