⚠️ The
sql``tagged template is still a placeholder and will throw.
UseparseSQL()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@cuttlefish-sync/core-test-casesStill in progress
sql`` tagged template wrapper{ sql, params, ast }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:
OperationNode{ sql, params, ast } payload ready for React hooksimport { 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:
Alternative considered: pgsql-parser (libpg-query + pure TypeScript deparser)
Currently using @pgsql/types (dev dependency) for PostgreSQL AST type definitions:
The package will convert PostgreSQL AST → unified Cuttlefish AST format (similar to @cuttlefish-sync/kysely):
To avoid upfront bundle cost:
Current:
@cuttlefish-sync/core - Core Cuttlefish types and utilities@pgsql/types (dev) - PostgreSQL AST type definitionsFuture implementation will add:
libpg-query - PostgreSQL parser (WASM build)pgsql-parser - Parser + deparser if round-trip SQL generation neededimport { 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 ✅
Phase 2: Parser Integration ✅
parseSQL() wired to pgsql-parserPhase 3 (up next): Ergonomics
sql`` tagged template{ sql, params, ast }Phase 4 (future): Optimization
@cuttlefish-sync/core - Core client functionality@cuttlefish-sync/kysely - Kysely query builder adapter@cuttlefish-sync/react - React hooks (will consume this package)MIT