feat(sqlite): add SQLite target (milestones 1–3)#274
Draft
Conversation
Scaffold @prisma-next/driver-sqlite and @prisma-next/adapter-sqlite as the first two packages for the SQLite target (Milestone 1). Driver: file-based SqliteDriver wrapping node:sqlite DatabaseSync with per-connection isolation, FK enforcement, busy_timeout, error normalization to SqlQueryError/SqlConnectionError, and unbound/control driver descriptors. Adapter: 8 SQLite codecs (text, integer, real, blob, boolean, datetime, json, bigint) plus 4 inherited SQL codecs, column-type descriptors, and capability metadata (returning: true, lateral: false, jsonAgg: true, enums: false).
Adapter: implement SQLite SQL renderer with ? positional params, json_object/json_group_array, ILIKE→LIKE mapping, no DISTINCT ON or LATERAL. DEFAULT in INSERT VALUES throws (unsupported by SQLite). Driver: remove primary connection — all operations acquire fresh connections via openConnection(), simplifying lifecycle management. Capabilities scoped under sql namespace, not sqlite.
…ation Add @prisma-next/target-sqlite with runtime target descriptor and pack ref for contract authoring. Add @prisma-next/sqlite extension with sqlite() factory function mirroring postgres() — lazy client with sql, schema, orm surfaces, connect()/runtime() lifecycle. Add adapter create() method for SqlRuntimeAdapterDescriptor compliance. Register all 4 SQLite packages in architecture.config.json with correct domain/layer/plane mappings. lint:deps passes with no violations.
- Move MarkerReader to AdapterProfile so each target provides its own marker SQL (Postgres: schema-qualified $1 params, SQLite: flat table ? params) - Fix sqlite() factory to pass context (not contract) to ORM builder - Add codec traits to all SQLite codecs for ORM field accessor methods - Fix codec definitions to let TS infer literal types (remove incorrect explicit generic params that broke type inference) - Remove ColumnTypeDescriptor annotation from column-type exports to preserve literal codecId types through the contract builder - Add sql-builder-new integration tests: SELECT, INSERT, UPDATE, DELETE with RETURNING, codec round-trips (boolean, datetime, JSON), and capability gating (lateralJoin, distinctOn blocked at type + runtime) - Add ORM integration tests: findMany, findFirst, create, createAll, update, updateAll, delete, deleteAll, includeMany, upsert, and typed row codec verification - Add expectTypeOf assertions verifying row types flow correctly from contract through sql-builder and ORM
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
closes TML-2167
Intent
Add SQLite as the second concrete target in Prisma Next, validating the multi-target adapter architecture. Four new packages (driver, adapter, target, extension) follow the Postgres 4-tier pattern. All dialect differences are handled through adapters, capabilities, and codecs — no target-name conditionals anywhere in shared code. This covers milestones 1–3 of the project plan: driver + codecs, AST→SQL lowering, and end-to-end integration through
sql-builder-newand ORM.Change map
node:sqlitedriversqlite()factory + integration testsreadMarkerStatement()onAdapterProfileThe story
Driver and codec foundation — A
node:sqliteDatabaseSyncdriver wraps synchronous APIs in the asyncSqlDriverinterface, with foreign keys enabled by default. Eight codecs handle SQLite's type system (TEXT, INTEGER, REAL, BLOB, plus semantic codecs for boolean→0/1, datetime→ISO8601, JSON→TEXT, bigint→INTEGER).AST→SQL lowering — The SQLite adapter lowers the shared
AnyQueryAstto valid SQLite SQL:?positional params instead of$1,CAST()instead of::type,json_object()/json_group_array()instead of Postgres JSON functions, andON CONFLICTupsert support. Golden tests lock every AST node type.Target-aware marker reader — The runtime's contract verification previously hardcoded Postgres SQL (
prisma_contract.markerwith$1). Marker reading is moved toAdapterProfileso each target provides its own SQL. This is the only cross-cutting change to shared framework code.Extension + integration tests — The
sqlite()factory composes driver, adapter, and target into a lazy client withsql,schema,ormsurfaces. Integration tests exercise the full stack against real:memory:databases, withexpectTypeOfassertions proving that codec output types flow correctly through the contract type system.Codec type preservation — Column type descriptors and codec definitions are fixed to preserve literal
codecIdtypes through the TypeScript type system, enablingDb<Contract>to resolve row types to concrete JS types (e.g.boolean,Date,JsonValue) rather thanunknown.Behavior changes & evidence
Adds SQLite driver wrapping
node:sqliteDatabaseSyncProvides
connect(),execute()(async iterable),query(),close(), transaction support, andPRAGMA foreign_keys = ONon connect.Adds SQLite adapter that lowers
AnyQueryAstto SQLite SQLSELECT, INSERT (with ON CONFLICT), UPDATE, DELETE, RETURNING, JOINs, subqueries, JSON aggregation, parameterized queries with
?placeholders,CAST()syntax.Moves marker reader from hardcoded Postgres SQL to
AdapterProfileBefore:
SqlFamilyAdapterhardcodedreadContractMarker()which producedSELECT ... FROM prisma_contract.marker WHERE id = $1. This failed on SQLite (no schema support, wrong placeholder syntax).After:
AdapterProfile.readMarkerStatement()lets each adapter provide target-specific marker SQL.SqlFamilyAdapterdelegates to the adapter profile. Postgres usesprisma_contract.markerwith$1; SQLite usesprisma_contract_markerwith?.MarkerStatementinterface +readMarkerStatement()onAdapterProfileadapter.profileAdds
sqlite()factory with lazy client compositionMirrors
postgres(): accepts contract/contractJson + path, creates execution stack, returnsSqliteClientwithsql,schema,orm,context,connect(),runtime().Fixes codec type preservation so
Db<Contract>resolves row typesTwo root causes made all sql-builder row fields resolve to
unknown:integerColumn) had explicit: ColumnTypeDescriptorannotation, wideningcodecIdfrom literal'sqlite/integer@1'tostring.codec<Id, number, number>wherenumbermapped toTTraitsnotTWire), breaking type inference.Both are fixed by removing explicit annotations and letting TypeScript infer literals from
as constand typed encode/decode signatures.: ColumnTypeDescriptorannotationsexpectTypeOfassertions verify{ id: number; name: string },{ active: boolean },{ created_at: Date },{ metadata: JsonValue | null }expectTypeOfassertions on ORM row typesCapability gating verified at type level and runtime
lateralJoinanddistinctOnare unavailable for SQLite contracts — verified by@ts-expect-error(type gate) andexpect(...).toThrow()(runtime gate with specific error message).Compatibility / migration / risk
AdapterProfilebreaking change: AllAdapterProfileimplementations must now providereadMarkerStatement(). Updated for Postgres adapter and all test stubs.: ColumnTypeDescriptorfrom column type exports narrows the inferred type. This is a type-level improvement (more precise), not a runtime change.Follow-ups / open questions
projectionTypeson its query plans, so codec decoding (e.g. INTEGER 0/1 → boolean) does not apply to ORM read results. Pre-existing cross-target limitation.selectIncludeStrategybug: Readscapabilities['lateral']at top level but capabilities are nested undersql.*. Lateral/correlated strategies unreachable for any target. Pre-existing.ilikenot feature-gated: The ORM exposesilike()on text fields for SQLite, but the adapter silently maps it toLIKE. Should be properly gated in a follow-up.Non-goals / intentionally out of scope
sql-lane(legacy) andkysely-laneSQLite support