Add three open questions (OQ-17, OQ-18, OQ-19) covering attribute query strategy, CRUD generation approach, and storage-operations bridge placement. Create ADR-033 recording the v1 decision: JSON path queries for attributes with hand-written CRUD for static tables. Expand forward-look.md with Repository Layer Strategy section analyzing three approaches (JSON path, native columns via dbtype, hybrid) and their implications for the metagraph pattern. Add drizzle-graphql and dbtype from-dbtype comparison showing neither handles dynamic schema-as-data. Update overview.md with dbtype/ujsx in the dependency diagram, expanded ecosystem context in the bridging pattern section, and new open questions. Align open-questions.md: resolve OQ-17 and OQ-18 for v1 (ADR-033), add OQ-19 as open, update summary counts and ADR impact table.
3.5 KiB
ADR-033: JSON path queries and hand-written CRUD for v1 repository layer
Status
Accepted
Context
The repository layer is the next major feature for @alkdev/storage. It needs to provide typed CRUD operations for the 6 metagraph tables and query capability for node/edge attributes stored as JSON columns.
The metagraph pattern stores node and edge attributes as JSON (attributes text not null default '{}' with JSON mode in SQLite, jsonb in PG). This is fundamental to the design — node types are dynamic schemas defined at runtime and stored in node_types.schema, not static columns known at database definition time.
Three approaches exist for querying attributes:
-
JSON path queries: Map filter criteria to
json_extract()(SQLite) or->>/#>>(PG). Works with current table definitions. No native index support on individual attributes. -
Native columns via dbtype: Render the metagraph tables via
@alkdev/dbtypeelement trees and make attributes native columns. Conflicts with the metagraph's dynamic schema model — attributes are runtime data, not static columns. -
Hybrid: dbtype renders the 6 static tables. Attributes remain JSON (dynamic schema requirement). CRUD for static tables could be auto-generated. Graph-specific queries use JSON path. Virtual columns for frequently queried attributes as a later optimization.
Separately, the CRUD operations for the 6 metagraph tables (insert graph type, find node by key, etc.) could be hand-written, auto-generated from Drizzle schemas (drizzle-graphql pattern), or auto-generated from dbtype element trees (the from-dbtype adapter pattern).
Decision
For v1:
-
Attribute queries use JSON path extraction (
json_extracton SQLite,->>/#>>on PG). This preserves the metagraph's dynamic schema model. Native column indexes on individual attributes are not available in v1. -
Static table CRUD operations are hand-written with explicit function signatures (
findNode(graphId, key),insertNodeType(...), etc.). No auto-generation from Drizzle or dbtype. -
dbtype integration is deferred (per ADR-018). The hybrid approach remains viable for a future iteration but is not the v1 path.
-
Virtual/computed columns for frequently queried attributes are a post-v1 optimization, not a v1 design concern.
The repository layer will have two parts:
- Static table CRUD: Insert, find, update, delete for graph_types, node_types, edge_types, graphs, nodes, edges, actors.
- Graph data queries: JSON path queries against node/edge attributes, validated by the Module schema at the application layer.
Consequences
- v1 repository API uses JSON path for attribute queries — no native SQL indexes on attributes
- CRUD function signatures are known and explicit — no generated code surface to learn
- PG can add GIN indexes on
jsonbcolumns for containment queries, but not for arbitrary key-value lookups - The hand-written CRUD path doesn't block any future auto-generation approach (dbtype
from-dbtype, drizzle-graphql pattern, or afrom-storageadapter in@alkdev/operations) - The metagraph's dynamic schema model is preserved — attributes are always JSON, not static columns
References
- forward-look.md — Repository Layer Strategy section (full analysis)
- overview.md — Repository Layer Bridging Pattern
- sqlite-host.md — JSON text for schema columns (ADR-019)
- ADR-018: dbtype integration is post-v1
- ADR-005: Drizzle + TypeBox via drizzlebox