Files
dbtype/docs/architecture/open-questions.md
glm-5.1 da65f7b693 docs: resolve OQ-11 and OQ-12 with ADR-015 and ADR-016
ADR-015: <table> accepts extraConfig prop mirroring Drizzle's third
callback argument for composite unique constraints and other
column-reference-based features.

ADR-016: Adapter accepts Type.Module compiled bundle (not individual
schemas). M.Import() handles ref resolution automatically, eliminating
potential complications with separate schema wiring.

Update FromDbTypeConfig interface to use module instead of schema,
update element types table with extraConfig prop.
2026-05-23 13:02:23 +00:00

11 KiB

status, last_updated
status last_updated
stable 2026-05-23

Open Questions Tracker

Architectural questions for dbtype, organized by theme. Resolved questions reference their ADR.

Schema & Module

OQ-01: Should relation entries use a naming convention?

  • Origin: schema.md
  • Status: Resolved
  • Priority: Medium Resolved
  • Context: Currently UsersRelations / TasksRelations. Is this naming convention sufficient, or should relations be structured differently? A relations field on the table entry would couple relations to table definitions.
  • Resolution: Keep the FooRelations naming convention. Separate module entries for relations align with Drizzle's naming convention, stay within Type.Module's flat namespace, and are independently addressable via M.Import. A relations field on the table entry would break the TypeBox schema model. See ADR-009.
  • Cross-references: OQ-03

OQ-02: Should derived schemas live in the module or be extracted separately?

  • Origin: schema.md
  • Status: Resolved
  • Priority: Low Resolved
  • Context: Insert/update schemas can be added as module entries (InsertUsers, UpdateUsers) or extracted by walking the module. Adding them to the module increases size but makes everything accessible via Import. Extracting separately is more flexible but requires separate code paths.
  • Resolution: Include all derived schemas (insert, update, filter) in the module by default. A repo_from interface will generate CRUD operation specs from the module using the operations system, and needs access to all derived schemas. The decision isn't hard to reverse — an includeDerived: false opt-out can be added later. See ADR-010.
  • Cross-references: OQ-03

OQ-03: Should the module support multiple database namespaces?

  • Origin: schema.md
  • Status: Resolved
  • Priority: Low Resolved
  • Context: One module per database, or one module with all tables across all databases? Probably one per database namespace, but this needs confirmation from real use cases.
  • Resolution: One module per database namespace. This keeps the module's flat namespace clean, avoids table name collisions across databases, and aligns with how Drizzle organizes schemas. See ADR-010.

Element & Host

OQ-04: Should column elements support nested TypeBox schemas?

  • Origin: elements.md
  • Status: Resolved
  • Priority: High Resolved
  • Context: The research docs proposed DbType.String({ notNull: true, inner: Type.String({ format: 'email', maxLength: 255 }) }). With UJSX elements, this would be <column name="email" type="string" notNull format="email" maxLength={255} />. The flat props model works for common cases, but custom validation constraints (patterns, ranges, custom checks) may need a nested inner prop.
  • Resolution: Yes — flat props for common cases, inner as escape hatch for custom validation. When inner is provided, extractTable() uses it directly instead of calling colToTypeBox(). The host ignores inner — it's purely for the TypeBox schema. See ADR-007.

OQ-05: How to handle PG enum pre-declaration?

  • Origin: hosts.md
  • Status: Resolved
  • Priority: High Resolved
  • Context: PG requires pgEnum() at module scope before tables that reference it. Options: (A) return both enums and tables from render, (B) start with text for all enums, (C) per-column opt-in with postgres: { nativeEnum: true }.
  • Resolution: Option A — the PG host accumulates enums in ctx.enums during the render walk. The consumer includes both ctx.enums and ctx.tables in their Drizzle schema. Enum names follow the table_column convention. See ADR-008.

OQ-06: Should hosts return rendered tables or store them in context?

  • Origin: hosts.md
  • Status: Resolved
  • Priority: Medium Resolved
  • Context: The probe scripts use ctx.tables to collect rendered tables. A more functional approach would have render() return the rendered table directly. Need to resolve this before implementation.
  • Resolution: render() accumulates results in root.ctx (tables, enums). The context shape varies by dialect — SQLite has ctx.tables, PG has ctx.tables and ctx.enums. This is a design clarification confirmed by implementation, not a significant architectural decision requiring its own ADR. See hosts.md Rendering Pipeline.

OQ-07: Should we support JSX file extensions?

  • Origin: elements.md
  • Status: Resolved
  • Priority: Low Resolved
  • Context: JSX syntax (.tsx with jsxImportSource: '@alkdev/ujsx') would be more ergonomic than h() calls. This requires build configuration (TSConfig jsx, bundler support). The h() API works universally; JSX is a convenience layer.
  • Resolution: Yes — support JSX/TSX as an ergonomic authoring layer. JSX desugars to h() calls via jsxImportSource: '@alkdev/ujsx', so the runtime representation is identical. The h() API remains the universal fallback. See ADR-011.

Repo Adapter

OQ-08: Per-dialect handler differences?

  • Origin: repo-adapter.md
  • Status: Resolved
  • Priority: Medium Resolved
  • Context: PG has .returning() on all mutations, MySQL often doesn't. Should the adapter handle this transparently (always try .returning(), fall back gracefully), or should it be explicit in the config?
  • Resolution: Always use .returning() and gracefully fall back. For dialects that support it (PG, SQLite), return the full result rows. For dialects that don't (MySQL), fall back to returning validated input data (for inserts) or affected row count (for updates/deletes). This keeps the operations API uniform across dialects. See ADR-012.

OQ-09: Relation rendering responsibility?

  • Origin: repo-adapter.md
  • Status: Resolved
  • Priority: Medium Resolved
  • Context: Should the host render relations (new element type <relation>), or should the adapter generate them from the module's relation entries? The adapter knows the rendered table objects; the module knows the relation structure. Leaning toward the adapter generating them.
  • Resolution: The adapter generates relation objects from the module's relation entries and the rendered table objects. No new <relation> element type is needed. The adapter reads FooRelations entries from the module, maps them to Drizzle relations() calls using the rendered table objects in ctx.tables. See ADR-013.

Migration & Diffing

OQ-10: How far should migration diffing go in phase 1?

  • Origin: module.md
  • Status: Resolved
  • Priority: Low Resolved
  • Context: Value.Diff on serialized schemas produces structural edit lists (insert/delete/update property). Translating these to ALTER TABLE statements is straightforward for additive changes (new column) but complex for destructive ones (drop column, change type). Phase 1 likely skips migration generation entirely (rely on drizzle-kit), but the module structure should not prevent it later.
  • Resolution: Leverage drizzle-kit for migrations. dbtype renders to Drizzle table definitions, and drizzle-kit generate already handles migration generation from those. No dbtype-native migration generator in phase 1 or the foreseeable future. The module's Value.Diff capability remains available as a foundation for future use. See ADR-014.

OQ-11: Should <table> accept extraConfig props?

  • Origin: elements.md
  • Status: Resolved
  • Priority: Low Resolved
  • Context: Drizzle tables accept a third callback argument for indexes and unique constraints defined in terms of column references (e.g., t => ({ uniqueEmail: unique().on(t.email) })). The <index> element handles most index cases, but composite unique constraints using the Drizzle callback style may not be expressible via <index unique>. How should this map to element props, or is it needed at all?
  • Resolution: Yes — the <table> element accepts an extraConfig prop that mirrors Drizzle's third callback argument. It receives the rendered column builders and returns an object for indexes, unique constraints, and other column-reference-based features. This is the escape hatch pattern, consistent with inner on <column>. See ADR-015.

OQ-12: Should the adapter accept the Type.Module bundle or individual schemas?

  • Origin: repo-adapter.md
  • Status: Resolved
  • Priority: Low Resolved
  • Context: The adapter needs access to select, insert, update, and filter schemas. Accepting the Type.Module compiled bundle is convenient (everything in one place, accessible via M.Import()) but couples the adapter to TypeBox's module format. Accepting individual schemas is more flexible but requires more config. With ADR-010 resolving that derived schemas are included in the module, the module bundle approach is the natural default, but the adapter could expose both interfaces.
  • Resolution: Accept the Type.Module compiled bundle. M.Import() handles ref resolution and recursion automatically, which eliminates potential complications with separate schema wiring. Consistent with ADR-010 (derived schemas in the module) and requires less configuration. See ADR-016.

Summary Table

ID Question Origin Priority Status
OQ-01 Relation naming convention schema.md Medium Resolved Resolved — ADR-009
OQ-02 Derived schemas in module or separate schema.md Low Resolved Resolved — ADR-010
OQ-03 Multiple database namespaces schema.md Low Resolved Resolved — ADR-010
OQ-04 Nested TypeBox schemas in column props elements.md High Resolved Resolved — ADR-007
OQ-05 PG enum pre-declaration hosts.md High Resolved Resolved — ADR-008
OQ-06 Host render return value vs context hosts.md Medium Resolved Resolved — design clarification
OQ-07 JSX file extensions elements.md Low Resolved Resolved — ADR-011
OQ-08 Per-dialect handler differences repo-adapter.md Medium Resolved Resolved — ADR-012
OQ-09 Relation rendering responsibility repo-adapter.md Medium Resolved Resolved — ADR-013
OQ-10 Migration diffing scope module.md Low Resolved Resolved — ADR-014
OQ-11 Table extraConfig props elements.md Low Resolved Resolved — ADR-015
OQ-12 Module bundle vs. individual schemas repo-adapter.md Low Resolved Resolved — ADR-016