Skip to main content

Schema Management

🧱 defineLocalSchema(...)​

Manually defines the schema for a local SQLite table used by Supastash.

This is helpful for:

  • Explicitly controlling column types and constraints.
  • Ensuring default values and modifiers (e.g., NOT NULL, DEFAULT CURRENT_TIMESTAMP) are present.
  • Pre-defining tables before useSupastashData(...) is called.
  • Will not replace previously created tables unless it's called with the deletePreviousSchema argument.

⚠️ Important Notes​

  • useSupastashData(...) automatically creates local tables based on the remote schema fetched via the get_table_schema RPC. But there are a few things to keep in mind:

    • It does not include default values or constraints.
    • It does not include modifiers like UNIQUE, DEFAULT, or PRIMARY KEY.
    • It only ensures the structure exists enough to read/write data.

If your local table needs strict constraints, timestamps, or default values β€” use defineLocalSchema(...) manually instead.


πŸ§ͺ Example​

import { defineLocalSchema } from "supastash";

await defineLocalSchema(
"users",
{
id: "TEXT PRIMARY KEY",
full_name: "TEXT NOT NULL",
email: "TEXT UNIQUE NOT NULL",
created_by: "TEXT",
},
true
); // Pass `true` if you want to force re-creation

πŸ”§ Parameters​

NameTypeRequiredDescription
tableNamestringβœ…The name of the table to create.
schemaRecord<string, ColumnDefinition>βœ…The column definitions (see below).
deletePreviousSchemaboolean (default: false)❌If true, drops any existing table and Supastash sync state for that table.

⚠️ Avoid using deletePreviousSchema = true in production. This option wipes all local data for the table β€” only use it when resetting development state or during controlled migrations.


🧱 Required Columns​

Regardless of what you pass in schema, Supastash will automatically include these columns:

{
created_at: "TEXT NOT NULL",
updated_at: "TEXT NOT NULL",
synced_at: "TEXT DEFAULT NULL",
deleted_at: "TEXT DEFAULT NULL",
}

Your schema must include an id column (UUID format as TEXT). If omitted, the function will throw an error.


πŸ’‘ Column Type Support​

Columns are defined using string templates based on SQL types and modifiers. Examples:

{
id: "TEXT PRIMARY KEY",
quantity: "INTEGER NOT NULL",
price: "REAL",
active: "INTEGER DEFAULT 1",
created_at: "TEXT DEFAULT CURRENT_TIMESTAMP"
}

You can combine multiple modifiers like so:

"name": "TEXT NOT NULL UNIQUE"

🧼 Resetting a Table​

To reset the schema (e.g., in development):

await defineLocalSchema("users", schema, true);

This drops the table, clears sync metadata, and re-creates the table with the new schema.


  • βœ… useSupastashData(...): Automatically creates missing tables, but with no constraints or default values.
  • ❌ Does not apply default constraints like NOT NULL, UNIQUE, or DEFAULT β€” use defineLocalSchema(...) for those.

πŸ”Œ getSupastashDb()​

πŸ“„ Description​

Returns the active SQLite database used by Supastash for local reads, writes, and sync tracking.

The connection is created only once and reused β€” based on the adapter you set in your config.


🧠 How It Works​

  1. Retrieves your Supastash config using getSupastashConfig().

  2. Checks for presence of both:

    • sqliteClient: The raw SQLite client you've passed during setup.
    • sqliteClientType: A string that tells Supastash which adapter to use (expo, rn-nitro, rn-storage).
  3. If the database instance hasn't been initialized yet:

    • Calls that adapter’s openDatabaseAsync(...) method with the configured DB name and client.
  4. Caches the result in a db variable so future calls don’t re-open the database.


βœ… Supported Client Types​

Client TypeAdapter UsedCompatible With
"expo"SQLiteAdapterExpoexpo-sqlite
"rn-storage"SQLiteAdapterStoragereact-native-sqlite-storage
"rn-nitro"SQLiteAdapterNitroreact-native-quick-sqlite

πŸ”§ API Methods​

MethodDescriptionReturns
runAsync(sql, params?)Executes a single statement (e.g., INSERT, UPDATE, DELETE)Promise<void>
getAllAsync(sql, params?)Fetches all rows from a SELECT queryPromise<any[]>
getFirstAsync(sql, params?)Fetches first row only (or null if none) from a SELECT queryPromise<any | null>
execAsync(statements)Executes multiple SQL statements separated by ; (used in schema creation)Promise<void>

Follows the same call patterns as expo-sqlite, making it familiar and easy to use.


πŸ“¦ Example Usage​

This function is used internally by other Supastash functions (e.g., defineLocalSchema, query runners, sync processors) but can also be called manually if you need raw access to the database:

const db = await getSupastashDb();
const users = await db.getAllAsync("SELECT * FROM users");

⚠️ Notes​

  • If configureSupastash(...) hasn't been called before this, the config will be empty and this function will throw.
  • This method assumes the client and clientType are correctly configured; if not, an error will be thrown.
  • This is designed to be adapter-agnostic, so it supports multiple SQLite engines while exposing a unified interface.

πŸ“‹ getAllTables(): Promise<string[] | null>​

Returns a list of all user-defined tables in the local SQLite database, excluding internal tables used by Supastash.

βœ… Example​

const tables = await getAllTables();
console.log(tables);
// ["users", "orders", "transactions"]

πŸ“Œ Use Cases​

  • Listing all tables available for syncing or inspection.
  • Dynamic tooling (e.g., admin panels, migration utilities).
  • Debugging which user tables are present in the local DB.

πŸ” Return​

  • string[] – array of table names (excluding system/internal).
  • null – if no user tables are found.

πŸ”— What’s Next?​