Cuttlefish SDK Reference - v0.1.0
    Preparing search index...

    Module @cuttlefish-sync/raw-sql

    @cuttlefish-sync/raw-sql

    ⚠️ The sql`` tagged template is still a placeholder and will throw.
    Use parseSQL() with pre-parameterized SQL strings today.

    Raw SQL adapter for Cuttlefish Sync. It parses PostgreSQL-flavoured SQL into the same Cuttlefish AST consumed by the React hooks and other runtime components, without requiring an ORM dependency.

    @cuttlefish-sync/raw-sql provides the same adapter interface as @cuttlefish-sync/kysely, but for raw SQL strings instead of query builders. It uses PostgreSQL's canonical SQL parser (libpg-query) to parse SQL into AST format for client-side evaluation.

    Implemented

    • parseSQL(sql: string) – parses SQL and returns a OperationNode
    • ✅ PostgreSQL AST → Cuttlefish AST converter
    • ✅ Parser test helpers used by @cuttlefish-sync/core-test-cases
    • ✅ Type definitions and public exports

    Still in progress

    • sql`` tagged template wrapper
    • ❌ Higher-level helpers for bundling { sql, params, ast }
    • ❌ Table extraction & validation utilities
    import { sql } from '@cuttlefish-sync/raw-sql'
    import { useLocalLiveQuery } from '@cuttlefish-sync/react'

    const id = 123
    const status = 'active'

    const query = sql<Todo>`
    SELECT * FROM todos
    WHERE id = ${id} AND status = ${status}
    `

    // Use with React hooks
    const { data } = useLocalLiveQuery(query)

    The tagged template will eventually:

    • Convert values to parameterized placeholders ($1, $2, etc.)
    • Extract parameter values
    • Parse SQL into a OperationNode
    • Return a { sql, params, ast } payload ready for React hooks
    import { parseSQL } from '@cuttlefish-sync/raw-sql'

    const sqlText = `
    SELECT * FROM todos
    WHERE id = $1 AND status = $2
    `
    const params = [123, 'active']

    const ast = await parseSQL(sqlText)

    // Bundle however you need for downstream consumers:
    const query = { ast, sql: sqlText, params }
    const { data } = useLocalLiveQuery(query)

    parseSQL() focuses purely on SQL → AST conversion. You control how SQL text and parameter values are stored or transported.

    After researching options, we've selected libpg-query for parsing:

    • ✅ Official PostgreSQL parser compiled to WebAssembly
    • ✅ Works in browsers AND Node.js (zero native dependencies)
    • ✅ Cross-platform (macOS, Linux, Windows)
    • ✅ Production-grade (millions of downloads)
    • ✅ Supports PostgreSQL 13-17

    Alternative considered: pgsql-parser (libpg-query + pure TypeScript deparser)

    • May be useful for round-trip SQL generation
    • Deferred to implementation PR

    Currently using @pgsql/types (dev dependency) for PostgreSQL AST type definitions:

    • Pure TypeScript (no WASM overhead during development)
    • Compatible with libpg-query's AST format
    • Enables type-safe development before parser implementation

    The package will convert PostgreSQL AST → unified Cuttlefish AST format (similar to @cuttlefish-sync/kysely):

    • Enables consistent query evaluation across adapters
    • Unified AST format for Kysely, raw SQL, and future ORMs
    • Implementation deferred to future PR

    To avoid upfront bundle cost:

    • Parser will be lazy-loaded on first use
    • WASM binary loaded asynchronously
    • Consider code-splitting for React applications

    Current:

    • @cuttlefish-sync/core - Core Cuttlefish types and utilities
    • @pgsql/types (dev) - PostgreSQL AST type definitions

    Future implementation will add:

    • libpg-query - PostgreSQL parser (WASM build)
    • Or pgsql-parser - Parser + deparser if round-trip SQL generation needed
    import { parseSQL } from '@cuttlefish-sync/raw-sql'
    import { useLocalLiveQuery } from '@cuttlefish-sync/react'

    const sqlText = 'SELECT * FROM todos WHERE list_id = $1'
    const params = [listId]

    const ast = await parseSQL(sqlText)
    const query = { ast, sql: sqlText, params }

    const { data } = useLocalLiveQuery(query)

    // Works alongside the Kysely adapter:
    import { fromKysely } from '@cuttlefish-sync/kysely'
    const kyselyQuery = fromKysely(db.selectFrom('todos').selectAll())
    const { data: kyselyData } = useLocalLiveQuery(kyselyQuery)
    # Install dependencies
    npm install

    # Build (currently just type-checks placeholders)
    npm run build

    # Watch mode
    npm run dev

    Phase 1: Scaffolding ✅

    • Package structure, exports, placeholder APIs

    Phase 2: Parser Integration ✅

    • parseSQL() wired to pgsql-parser
    • PostgreSQL AST → Cuttlefish AST conversion
    • Test helpers updated to the new API

    Phase 3 (up next): Ergonomics

    • Implement sql`` tagged template
    • Provide helper(s) to bundle { sql, params, ast }
    • Table extraction and validation tooling

    Phase 4 (future): Optimization

    • Performance work
    • Lazy loading / bundle size improvements
    • Additional validation utilities
    • @cuttlefish-sync/core - Core client functionality
    • @cuttlefish-sync/kysely - Kysely query builder adapter
    • @cuttlefish-sync/react - React hooks (will consume this package)

    MIT

    Type Aliases

    PostgresAST

    Functions

    parseSQL
    sql