Graph type definitions as TypeBox Modules — the core architecture evolution for @alkdev/storage. The SchemaBuilder is removed (no existing consumers), replaced by direct TypeModule construction with Metagraph.Import() for base attribute composition and Type.Composite() for node/edge type specialization. Key additions: - metagraph-module.md: Module pattern, edge constraints as named entries, SchemaBuilder equivalence, DB bridge contracts (moduleToDbSchema return type, validateNode/validateEdge signatures), 10 design decisions (DD1-DD10) - forward-look.md: pointer abstraction (ujsx ValuePointer analogy, JPATH Module), dbtype table rendering relationship, ujsx as universal IR pipeline Critical corrections from architecture review: - Type.Composite uses IntersectEvaluated (intersection, not Object.assign override) — overlapping keys with subtype relationships resolve correctly - Type.Ref inside Type.Composite within a Module is verified working - BaseNode/BaseEdge use Metagraph.Import() for same-package Modules (Option B), not local re-declaration (no circular dep within same package) - Edge constraints use Type.String() for node type name arrays (not Type.Ref) — constraints contain names, not schemas
5.3 KiB
5.3 KiB
AGENTS.md — @alkdev/storage
Project-specific guidance for agents working on this package.
Project Overview
@alkdev/storage is a deno-first TypeScript package providing typed graph
storage with dual database hosts (SQLite for spokes, PostgreSQL for the hub). It
uses the metagraph pattern (graphTypes → nodeTypes → edgeTypes → typed graph
instances) from the earlier @ade prototype.
Architecture Snapshot
@alkdev/storage/
├── mod.ts # Re-exports graphs/ only (zero db deps)
├── deno.json # JSR config, imports, tasks, lint rules
├── src/
│ ├── graphs/ # Metagraph Module + bridge functions (no db deps)
│ ├── sqlite/ # SQLite host (drizzle-orm/libsql)
│ │ ├── tables/ # Drizzle table definitions
│ │ ├── relations.ts # Drizzle relations
│ │ ├── schema.ts # Re-exports
│ │ └── client.ts # Injectable createSqliteDatabase()
│ └── pg/ # PostgreSQL host (NOT YET IMPLEMENTED)
└── test/
Subpath Exports (JSR/npm)
@alkdev/storage→ Metagraph Module, graph type definitions (zero deps)@alkdev/storage/sqlite→ SQLite tables, relations, client (drizzle-orm + libsql)@alkdev/storage/pg→ PostgreSQL tables, relations, client (NOT YET IMPLEMENTED)
This design ensures consumers don't bundle database drivers they don't use.
Key Decisions
- Deno-first, npm-second via JSR: Package is published to JSR
(
deno publish). npm compatibility is automatic via JSR's npm layer (@jsr/alkdev__storage). No separate dnt build step. - No comments in code: Per project convention across @alkdev packages.
- JSR slow types excluded from lint: Drizzle's deeply inferred generics
(
sqliteTable,createInsertSchema,relations) make explicit type annotations impractical. We use--allow-slow-typeson publish and"exclude": ["no-slow-types"]in lint config. This is known technical debt — can be tightened iteratively. - Injectable clients:
createSqliteDatabase(client)takes a client, not env vars. Module-level side effects are forbidden. - Dependencies:
@alkdev/typeboxand@alkdev/drizzleboxare npm deps (not yet on JSR). This works fine — JSR handles npm dependencies natively.
Commands
deno check mod.ts src/graphs/mod.ts src/sqlite/mod.ts # Type check
deno lint # Lint (slow-types, verbatim-module-syntax excluded)
deno task lint:analyze # Analyze lint issues by code/file grouping
deno fmt # Format
deno test --allow-all test/ # Run tests
deno publish --allow-slow-types --dry-run # Dry-run publish
Source Heritage
The graphs/ and sqlite/ modules were adapted from
@ade/ade-v0/packages/core/graphs and @ade/ade-v0/packages/storage_sqlite.
Key changes from the originals:
@sinclair/typebox→@alkdev/typeboxdrizzle-typebox→@alkdev/drizzlebox@ade/coreimports → relative imports withinsrc/graphs/import type { GraphConfig }→import { GraphConfig }(TypeBox schemas are both values and types)Relationtype alias removed (JSR slow type)- TypeScript enums replaced with
as constobjects (EnumGraphStatus→GRAPH_STATUS) client.tsrefactored to be injectable- Module-level
dbandclientexports removed SchemaBuilderremoved — replaced byType.Module()construction
File Conventions
- All source files use
.tsextension with explicit extensions in imports (Deno convention) - Entry points are
mod.tsfiles that re-export from subdirectories - TypeBox schemas are named with PascalCase (
NodeType,GraphConfig) - Drizzle table objects are named with camelCase (
graphTypes,nodeTypes) - Schema objects from drizzlebox are named with PascalCase (
InsertGraph,SelectGraph) - Enum constants use
SCREAMING_SNAKE_CASEobjects (GRAPH_STATUS,ACTOR_TYPE)
Architecture Docs
See docs/architecture/ for detailed specifications:
overview.md— Package purpose, exports, design decisions, open questionsmetagraph.md— Core graph model, schema types, SchemaBuilder, attribute storagemetagraph-module.md— Graph type definitions as TypeBox Modules (evolution of metagraph.md), naming conventions, migration pathforward-look.md— Connections to dbtype, graph pointers, ujsx universal IR pipelinesqlite-host.md— SQLite tables, relations, client factory, porting notesencrypted-data.md— Encrypted data design (planned), crypto utility, node type modeling
These docs describe what the package is AND what it's becoming. Items marked ⚠️ are not yet implemented.
What's Not Done Yet
src/pg/— PostgreSQL host (same table shapes,pgTable+jsonb+timestamp+pgEnum)src/graphs/crypto.ts— Crypto utility (encrypt,decrypt,generateEncryptionKey,EncryptedDataSchema)- Tests
- Repository/CRUD layer (currently only table definitions, no typed query functions)
- Hub-specific tables (sessions, messages, parts, call graphs, tasks, etc.)
- JSR publication setup (need to create scope/package on jsr.io first)