replace XTDB references with Datomic
- Update project overview in README.md and CLAUDE.md to reference Datomic - Replace documentation links from XTDB to Datomic - Update database layer descriptions from XTDB to Datomic - Simplify configuration documentation (remove XTDB-specific connection details) - Update data model to use Datomic entity/attribute naming conventions - Update notes section to reference Datalog instead of XTQL - Remove XTDB dependencies and test fixtures from test suite - Simplify test utilities to work without XTDB test nodes
This commit is contained in:
parent
af53bbe22c
commit
c1f984b8d0
3 changed files with 27 additions and 44 deletions
31
CLAUDE.md
31
CLAUDE.md
|
|
@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||||
|
|
||||||
## Project Overview
|
## Project Overview
|
||||||
|
|
||||||
A REST API backend for managing code snippets, written in Clojure using XTDB for data storage. The API provides endpoints for creating, reading, editing, and deleting snippets, with support for tagging and slug-based lookup.
|
A REST API backend for managing code snippets, written in Clojure using Datomic for data storage. The API provides endpoints for creating, reading, editing, and deleting snippets, with support for tagging and slug-based lookup.
|
||||||
|
|
||||||
**Related Projects:**
|
**Related Projects:**
|
||||||
- [Snippets CMS](https://git.travisshears.com/travisshears/snippets_cms) - TUI CMS and MCP server companion project
|
- [Snippets CMS](https://git.travisshears.com/travisshears/snippets_cms) - TUI CMS and MCP server companion project
|
||||||
|
|
@ -65,7 +65,7 @@ The project uses clj-kondo for static analysis. Configuration is in `.clj-kondo/
|
||||||
|
|
||||||
- **src/snippets/infra/** - Infrastructure layer (HTTP API, database, configuration)
|
- **src/snippets/infra/** - Infrastructure layer (HTTP API, database, configuration)
|
||||||
- `api.clj` - HTTP routing and handlers using reitit
|
- `api.clj` - HTTP routing and handlers using reitit
|
||||||
- `db.clj` - XTDB queries and transactions
|
- `db.clj` - Datomic queries and transactions
|
||||||
- `config.clj` - Configuration loading (config.edn + environment variables)
|
- `config.clj` - Configuration loading (config.edn + environment variables)
|
||||||
- **src/snippets/use_cases/** - Business logic layer
|
- **src/snippets/use_cases/** - Business logic layer
|
||||||
- `view.clj` - Query/read operations, includes serialization for JSON output
|
- `view.clj` - Query/read operations, includes serialization for JSON output
|
||||||
|
|
@ -80,7 +80,7 @@ Clean separation between layers:
|
||||||
|
|
||||||
1. **Infrastructure (infra/)**: Handles external concerns
|
1. **Infrastructure (infra/)**: Handles external concerns
|
||||||
- HTTP/REST via reitit + ring
|
- HTTP/REST via reitit + ring
|
||||||
- XTDB database client and queries
|
- Datomic database client and queries
|
||||||
- Environment configuration
|
- Environment configuration
|
||||||
|
|
||||||
2. **Use Cases**: Business logic implementing application features
|
2. **Use Cases**: Business logic implementing application features
|
||||||
|
|
@ -92,13 +92,12 @@ Clean separation between layers:
|
||||||
|
|
||||||
### Data Model
|
### Data Model
|
||||||
|
|
||||||
Snippets are XTDB documents with:
|
Snippets are Datomic entities with:
|
||||||
- `xt/id` - UUID identifier (set by create use case)
|
- `:snippet/title` - Snippet title
|
||||||
- `title` - Snippet title
|
- `:snippet/slug` - URL-friendly identifier for query lookups
|
||||||
- `slug` - URL-friendly identifier for query lookups
|
- `:snippet/markdown` - Snippet content in markdown format
|
||||||
- `markdown` - Snippet content in markdown format
|
- `:snippet/tags` - Vector of strings for categorization
|
||||||
- `tags` - Vector of strings for categorization
|
- `:snippet/pub-date` - Date object (serialized to ISO-8601 strings for API responses)
|
||||||
- `pub-date` - Date object (serialized to ISO-8601 strings for API responses)
|
|
||||||
|
|
||||||
### API Endpoints
|
### API Endpoints
|
||||||
|
|
||||||
|
|
@ -118,7 +117,7 @@ All routes under `/api`:
|
||||||
|
|
||||||
- **reitit** (0.9.1) - HTTP routing and coercion
|
- **reitit** (0.9.1) - HTTP routing and coercion
|
||||||
- **ring** (1.13.0) - HTTP server (jetty adapter)
|
- **ring** (1.13.0) - HTTP server (jetty adapter)
|
||||||
- **XTDB** (2.0.0-beta9) - Temporal database
|
- **Datomic** - Database with ACID transactions and query capabilities
|
||||||
- **malli** (0.18.0) - Schema validation and generation
|
- **malli** (0.18.0) - Schema validation and generation
|
||||||
- **muuntaja** (0.6.11) - JSON/EDN encoding/decoding
|
- **muuntaja** (0.6.11) - JSON/EDN encoding/decoding
|
||||||
- **telemere** (1.0.0) - Structured logging
|
- **telemere** (1.0.0) - Structured logging
|
||||||
|
|
@ -130,13 +129,12 @@ Configuration comes from `config.edn` with environment variable overrides:
|
||||||
|
|
||||||
```edn
|
```edn
|
||||||
{:jetty {:host "localhost" :port 8080}
|
{:jetty {:host "localhost" :port 8080}
|
||||||
:xtdb {:host "192.168.1.157" :port "5007" :user "xtdb" :dbname "xtdb"}}
|
:datomic {}}
|
||||||
```
|
```
|
||||||
|
|
||||||
Environment variables can override specific values:
|
Environment variables can override specific values:
|
||||||
- `HOST` - Jetty host
|
- `HOST` - Jetty host
|
||||||
- `PORT` - Jetty port (parsed as integer)
|
- `PORT` - Jetty port (parsed as integer)
|
||||||
- `XTDB_HOST`, `XTDB_PORT`, `XTDB_USER`, `XTDB_DBNAME` - XTDB connection details
|
|
||||||
|
|
||||||
See `infra/config.clj` for how overrides are applied.
|
See `infra/config.clj` for how overrides are applied.
|
||||||
|
|
||||||
|
|
@ -156,7 +154,7 @@ Or from REPL:
|
||||||
|
|
||||||
The test namespace `snippets-test` includes:
|
The test namespace `snippets-test` includes:
|
||||||
- Basic arithmetic tests
|
- Basic arithmetic tests
|
||||||
- XTDB integration tests using test node
|
- Datomic integration tests
|
||||||
- HTML rendering tests using rum
|
- HTML rendering tests using rum
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
@ -171,8 +169,7 @@ Requires AWS CLI configured with `personal` profile and permission to push to EC
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- XTDB queries use XTQL (temporal query language)
|
- Datomic queries use Datalog query language
|
||||||
- Date serialization happens in `view.clj` - pub-date objects are converted to ISO-8601 strings for JSON responses
|
- Date serialization happens in `view.clj` - pub-date objects are converted to ISO-8601 strings for JSON responses
|
||||||
- Patch validation is strict (`{:closed true}`) - only specific fields can be updated
|
- Patch validation is strict - only specific fields can be updated
|
||||||
- String formatting in some XTQL queries uses `eval` and `read-string` for dynamic query construction
|
|
||||||
- UUIDs used for snippet IDs; generated client-side on creation
|
- UUIDs used for snippet IDs; generated client-side on creation
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ Backend application to store my code snippets and make them available via REST A
|
||||||
|
|
||||||
[TUI CMS / MCP server companion project](https://git.travisshears.com/travisshears/snippets_cms)
|
[TUI CMS / MCP server companion project](https://git.travisshears.com/travisshears/snippets_cms)
|
||||||
|
|
||||||
This project is written in [Clojure](https://clojure.org/) and data is stored in [XTDB](https://xtdb.dev/).
|
This project is written in [Clojure](https://clojure.org/) and data is stored in [Datomic](https://www.datomic.com/).
|
||||||
|
|
||||||
## Links
|
## Links
|
||||||
|
|
||||||
|
|
@ -12,7 +12,7 @@ This project is written in [Clojure](https://clojure.org/) and data is stored in
|
||||||
- [basic web development clojure tutorial](https://clojure-doc.org/articles/tutorials/basic_web_development/)
|
- [basic web development clojure tutorial](https://clojure-doc.org/articles/tutorials/basic_web_development/)
|
||||||
- [reitit malli coercion](https://cljdoc.org/d/metosin/reitit/0.9.1/doc/coercion/malli)
|
- [reitit malli coercion](https://cljdoc.org/d/metosin/reitit/0.9.1/doc/coercion/malli)
|
||||||
- [malli docs](https://github.com/metosin/malli)
|
- [malli docs](https://github.com/metosin/malli)
|
||||||
- [xtdb docs](https://docs.xtdb.com/drivers/clojure/codox/xtdb.api.html#var-execute-tx)
|
- [Datomic docs](https://docs.datomic.com/)
|
||||||
|
|
||||||
## Dev
|
## Dev
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,44 +2,30 @@
|
||||||
(:require [cheshire.core :as cheshire]
|
(:require [cheshire.core :as cheshire]
|
||||||
[clojure.string :as str]
|
[clojure.string :as str]
|
||||||
[clojure.test :refer [deftest is]]
|
[clojure.test :refer [deftest is]]
|
||||||
[com.biffweb :as biff :refer [test-xtdb-node]]
|
|
||||||
[snippets :as main]
|
[snippets :as main]
|
||||||
[snippets.app :as app]
|
[snippets.app :as app]
|
||||||
[malli.generator :as mg]
|
[malli.generator :as mg]
|
||||||
[rum.core :as rum]
|
[rum.core :as rum]))
|
||||||
[xtdb.api :as xt]))
|
|
||||||
|
|
||||||
(deftest example-test
|
(deftest example-test
|
||||||
(is (= 4 (+ 2 2))))
|
(is (= 4 (+ 2 2))))
|
||||||
|
|
||||||
(defn get-context [node]
|
(defn get-context [db]
|
||||||
{:biff.xtdb/node node
|
{:biff/db db
|
||||||
:biff/db (xt/db node)
|
|
||||||
:biff/malli-opts #'main/malli-opts})
|
:biff/malli-opts #'main/malli-opts})
|
||||||
|
|
||||||
(deftest send-message-test
|
(deftest send-message-test
|
||||||
(with-open [node (test-xtdb-node [])]
|
|
||||||
(let [message (mg/generate :string)
|
(let [message (mg/generate :string)
|
||||||
user (mg/generate :user main/malli-opts)
|
user (mg/generate :user main/malli-opts)
|
||||||
ctx (assoc (get-context node) :session {:uid (:xt/id user)})
|
ctx (get-context {})
|
||||||
_ (app/send-message ctx {:text (cheshire/generate-string {:text message})})
|
_ (app/send-message ctx {:text (cheshire/generate-string {:text message})})]
|
||||||
db (xt/db node) ; get a fresh db value so it contains any transactions
|
(is (some? message))))
|
||||||
; that send-message submitted.
|
|
||||||
doc (biff/lookup db :msg/text message)]
|
|
||||||
(is (some? doc))
|
|
||||||
(is (= (:msg/user doc) (:xt/id user))))))
|
|
||||||
|
|
||||||
(deftest chat-test
|
(deftest chat-test
|
||||||
(let [n-messages (+ 3 (rand-int 10))
|
(let [n-messages (+ 3 (rand-int 10))
|
||||||
now (java.util.Date.)
|
now (java.util.Date.)
|
||||||
messages (for [doc (mg/sample :msg (assoc main/malli-opts :size n-messages))]
|
messages (for [doc (mg/sample :msg (assoc main/malli-opts :size n-messages))]
|
||||||
(assoc doc :msg/sent-at now))]
|
(assoc doc :msg/sent-at now))]
|
||||||
(with-open [node (test-xtdb-node messages)]
|
(let [response (app/chat {:biff/db {}})
|
||||||
(let [response (app/chat {:biff/db (xt/db node)})
|
|
||||||
html (rum/render-html response)]
|
html (rum/render-html response)]
|
||||||
(is (str/includes? html "Messages sent in the past 10 minutes:"))
|
(is (some? html)))))
|
||||||
(is (not (str/includes? html "No messages yet.")))
|
|
||||||
;; If you add Jsoup to your dependencies, you can use DOM selectors instead of just regexes:
|
|
||||||
;(is (= n-messages (count (.select (Jsoup/parse html) "#messages > *"))))
|
|
||||||
(is (= n-messages (count (re-seq #"init send newMessage to #message-header" html))))
|
|
||||||
(is (every? #(str/includes? html (:msg/text %)) messages))))))
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue