TeaQL's TypeScript Runtime Is Now Available on npm
TeaQL's TypeScript runtime is now publicly available as
@teaql/teaql. The first release,
0.1.0, can be installed directly from npm:
npm install @teaql/teaql
TeaQL's TypeScript runtime is now publicly available as
@teaql/teaql. The first release,
0.1.0, can be installed directly from npm:
npm install @teaql/teaql
TeaQL now has a dated, executed database baseline across six generated language runtimes: Java, Rust, Go, Python, C#/.NET, and TypeScript.
The headline result is Java's real nine-database matrix:
tests=9 failures=0 errors=0 skipped=0
The databases were PostgreSQL, MySQL, SQLite, Oracle, DB2, DM8 (Dameng), SAP HANA, SQL Server, and DuckDB.
That is meaningful only because these were not adapter-discovery tests. The generated domain APIs compiled and executed schema creation, graph persistence, reconnect queries, optimistic updates, and direct database checks.
TeaQL Rust uses runtime providers to keep generated business APIs separate from storage execution.
The application code should use the generated API. The runtime should decide how that API executes against PostgreSQL, MySQL, SQLite, embedded SQLite, or memory.
| Provider | Best for |
|---|---|
| SQLx PostgreSQL | production-grade backend services, complex queries, transactions, aggregation |
| SQLx MySQL | enterprise MySQL systems and migration scenarios |
| SQLx SQLite | local-first apps, tests, lightweight services |
| rusqlite SQLite | embedded, router, edge, sync execution, multi-architecture devices |
| MemoryRepository | no-database tests, demos, fast model validation |
PostgreSQL is the strongest default for production backend systems that need:
TeaQL's SQLx PostgreSQL provider keeps PostgreSQL-specific execution behind the repository boundary.
MySQL remains common in enterprise business systems. TeaQL's SQLx MySQL provider is intended for teams that want generated business APIs while staying on a familiar MySQL backend.
This is especially useful when moving away from handwritten mapper-heavy persistence without moving the database first.
SQLite has two important TeaQL paths.
SQLx SQLite is useful for async local-first apps, integration tests, small services, and portable demos.
rusqlite is useful when synchronous embedded SQLite is a better fit:
Not every generated API test needs a database.
MemoryRepository gives TeaQL a no-database path for:
The goal is to test generated API behavior without requiring a database server.
The provider is registered below UserContext:
Generated service crate
-> RuntimeModule
-> UserContext
-> Repository API
-> selected provider
Generated crates can expose helpers for module registration, behavior/checker registration, provider-backed runtime setup, and schema bootstrap.
Without a provider boundary, application code tends to mix business intent with database details.
With providers, the generated API remains stable:
Q::platforms().select_merchant_list_with(Q::merchants().comment("Query merchants").purpose("Load data").select_name())
.comment("Query platforms").purpose("Load data")
.execute_for_list(&ctx)
.await?;
The runtime decides whether that request executes through PostgreSQL, MySQL, SQLite, rusqlite, or memory.
That is the point of TeaQL's multi-database runtime direction.
Important MySQL schema management improvements.
ensureTables automatically creates foreign key constraints:
+ MysqlRepository: FK generation logic
+ Auto-create FOREIGN KEY based on domain model relationships
No need to manually manage foreign key relationships.
Corrected MySQL ALTER TABLE statement generation:
+ Column type changes and nullability updates
+ Schema migration edge case handling
needCheck logic optimized to reduce unnecessary validation overhead.
TeaQL gained four new database backends in a single sprint.
+ teaql-oracle: Oracle database support
+ teaql-db2: IBM DB2 support
+ teaql-hana: SAP HANA support
+ teaql-mssql: Microsoft SQL Server support
Each module includes:
ensureTables)Migrated from raw JDBC to Spring JdbcTemplate for better resource management, connection pooling, and exception handling.
tinyint → Boolean mappingint → Integer mappingtimestamp → LocalDateTime mappingORDER BY sorting fixINNER JOIN, auxiliary table LEFT JOINNative pagination with page and pageSize:
Q.orders().filter(Q.orders().comment("Query orders").purpose("Load data").status().eq("ACTIVE"))
.page(1, 20)
.comment("Query orders").purpose("Load data")
.executeForList(ctx);