|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +DataScript is an immutable in-memory database and Datalog query engine implemented in Clojure and ClojureScript. It's designed to run in the browser and JVM, providing a lightweight, ephemeral database with Datalog querying capabilities similar to Datomic. |
| 8 | + |
| 9 | +## Key Commands |
| 10 | + |
| 11 | +### Testing |
| 12 | + |
| 13 | +```bash |
| 14 | +# Run Clojure tests |
| 15 | +./script/test_clj.sh |
| 16 | +# or: clojure -X:dev user/-test-main |
| 17 | + |
| 18 | +# Run ClojureScript tests |
| 19 | +./script/test_cljs.sh |
| 20 | + |
| 21 | +# Run all tests |
| 22 | +./script/test_all.sh |
| 23 | + |
| 24 | +# Run Datomic compatibility tests (requires datomic-free setup) |
| 25 | +./script/test_datomic.sh |
| 26 | +# or: clj -M:datomic |
| 27 | +``` |
| 28 | + |
| 29 | +### Benchmarking |
| 30 | + |
| 31 | +```bash |
| 32 | +# Run Clojure benchmarks |
| 33 | +./script/bench_clj.sh |
| 34 | +# or: clojure -A:bench -M -m datascript.bench.datascript |
| 35 | + |
| 36 | +# Run ClojureScript benchmarks |
| 37 | +./script/bench_cljs.sh |
| 38 | + |
| 39 | +# Run Datomic benchmarks (requires datomic-free setup) |
| 40 | +./script/bench_datomic.sh |
| 41 | + |
| 42 | +# Run all benchmarks |
| 43 | +./script/bench_all.sh |
| 44 | +``` |
| 45 | + |
| 46 | +### Development |
| 47 | + |
| 48 | +```bash |
| 49 | +# Start a REPL |
| 50 | +./script/repl.sh |
| 51 | + |
| 52 | +# Build ClojureScript release |
| 53 | +lein with-profile test cljsbuild once release |
| 54 | +``` |
| 55 | + |
| 56 | +## Architecture Overview |
| 57 | + |
| 58 | +### Core Components |
| 59 | + |
| 60 | +**Database Layer (`datascript.db`):** |
| 61 | +- `Datom` records represent facts as [entity attribute value transaction] tuples |
| 62 | +- `DB` is the immutable database value with three indexes: EAVT, AEVT, AVET |
| 63 | +- Uses persistent sorted sets for index storage (`me.tonsky.persistent-sorted-set`) |
| 64 | +- Transaction IDs start at `0x20000000` (tx0), entity IDs start at 0 (e0) |
| 65 | +- Schema is optional and only needed for special behaviors (cardinality many, unique attributes, ref types) |
| 66 | + |
| 67 | +**Query Engine (`datascript.query`):** |
| 68 | +- Implements Datalog query language |
| 69 | +- Queries are parsed, cached (LRU cache of 100), and executed against relations |
| 70 | +- Supports rules, aggregates, predicates, negation, and multiple data sources |
| 71 | +- `Relation` records store query intermediate results as {attrs tuples} |
| 72 | +- `Context` holds relations, sources, and rules during query execution |
| 73 | + |
| 74 | +**Connection Management (`datascript.conn`):** |
| 75 | +- Connections are atoms holding the latest DB value |
| 76 | +- Access current DB with `@conn`, not `(d/db conn)` as in Datomic |
| 77 | +- Transaction reports include `:db-before`, `:db-after`, `:tx-data`, `:tempids`, `:tx-meta` |
| 78 | +- Supports transaction listeners via `listen!` |
| 79 | + |
| 80 | +**Entity API (`datascript.impl.entity`):** |
| 81 | +- Lazy map-like entities for navigating database |
| 82 | +- Entities cache accessed attributes |
| 83 | +- Reverse references via `_` prefix (`:_ref`) |
| 84 | +- Component references return single entity instead of collection |
| 85 | + |
| 86 | +**Storage (`datascript.storage`):** |
| 87 | +- Protocol-based persistent storage for databases |
| 88 | +- Serializes indexes as persistent sorted sets with addressable chunks |
| 89 | +- Supports custom storage backends via `IStorage` protocol |
| 90 | + |
| 91 | +**Pull API (`datascript.pull-api`, `datascript.pull-parser`):** |
| 92 | +- EQL-style pattern-based entity graph extraction |
| 93 | +- Supports recursive patterns, attribute limits, default values |
| 94 | + |
| 95 | +### Key Differences from Datomic |
| 96 | + |
| 97 | +- Entities use `-1`, `-2` for tempids instead of `#db/id[:db.part/user -100]` |
| 98 | +- No `:db/txInstant` annotations by default |
| 99 | +- Custom query functions in ClojureScript must be passed as source (no `resolve`) |
| 100 | +- Transaction functions called as `[:db.fn/call f args]` where `f` is function reference |
| 101 | +- Additional `:db.fn/retractAttribute` built-in function |
| 102 | +- Schemas are not queryable and attributes don't need pre-declaration |
| 103 | + |
| 104 | +### File Organization |
| 105 | + |
| 106 | +- `src/datascript/` - Core implementation (.cljc files for JVM + JS) |
| 107 | + - `core.cljc` - Public API entry point |
| 108 | + - `db.cljc` - Database, datom, and index implementation |
| 109 | + - `query.cljc` - Datalog query engine |
| 110 | + - `pull_api.cljc`, `pull_parser.cljc` - Pull API |
| 111 | + - `storage.clj/.cljs` - Persistent storage (platform-specific) |
| 112 | + - `conn.cljc` - Connection and transaction handling |
| 113 | + - `parser.cljc` - Query/rule parsing |
| 114 | + - `built_ins.cljc` - Built-in query functions and aggregates |
| 115 | + |
| 116 | +- `test/datascript/test/` - Test suite (.cljc files) |
| 117 | + - Tests use `.cljc` files for cross-platform testing |
| 118 | + - Acceptance tests demonstrate usage: `test/datascript/test/*.cljc` |
| 119 | + |
| 120 | +- `bench/` - Benchmarking code |
| 121 | +- `bench_datomic/` - Datomic compatibility checks |
| 122 | +- `script/` - Build and test scripts |
| 123 | + |
| 124 | +### Development Notes |
| 125 | + |
| 126 | +- Uses `.cljc` files for cross-platform (JVM + ClojureScript) code |
| 127 | +- Custom macros in `datascript.db` like `defn+` handle CLJS efficiency |
| 128 | +- `*warn-on-reflection*` enabled for JVM performance |
| 129 | +- Storage implementation differs between Clojure (`.clj`) and ClojureScript (`.cljs`) |
| 130 | +- shadow-cljs users must add `:compiler-options {:externs ["datascript/externs.js"]}` |
| 131 | + |
| 132 | +### Aliases (deps.edn) |
| 133 | + |
| 134 | +- `:dev` - Development with REPL tools |
| 135 | +- `:test` - Test dependencies |
| 136 | +- `:bench` - Benchmarking tools (criterium, profiler) |
| 137 | +- `:datomic` - Datomic compatibility testing |
| 138 | +- `:cljs` - ClojureScript compilation |
| 139 | +- `:1.9`, `:1.10`, `:1.11.1`, `:1.12` - Override Clojure versions |
0 commit comments