datomic-flare 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.env.example +4 -0
- data/.gitignore +3 -0
- data/.rspec +1 -0
- data/.rubocop.yml +15 -0
- data/.ruby-version +1 -0
- data/Gemfile +19 -0
- data/Gemfile.lock +100 -0
- data/LICENSE +9 -0
- data/README.md +1042 -0
- data/components/errors.rb +22 -0
- data/components/http.rb +55 -0
- data/controllers/api.rb +48 -0
- data/controllers/client.rb +43 -0
- data/controllers/documentation/formatter.rb +37 -0
- data/controllers/documentation/generator.rb +390 -0
- data/controllers/dsl/querying.rb +39 -0
- data/controllers/dsl/schema.rb +37 -0
- data/controllers/dsl/transacting.rb +62 -0
- data/controllers/dsl.rb +48 -0
- data/datomic-flare.gemspec +39 -0
- data/docs/CURL.md +781 -0
- data/docs/README.md +360 -0
- data/docs/api.md +395 -0
- data/docs/dsl.md +257 -0
- data/docs/templates/.rubocop.yml +15 -0
- data/docs/templates/README.md +319 -0
- data/docs/templates/api.md +267 -0
- data/docs/templates/dsl.md +206 -0
- data/helpers/h.rb +17 -0
- data/logic/dangerous_override.rb +108 -0
- data/logic/querying.rb +34 -0
- data/logic/schema.rb +91 -0
- data/logic/transacting.rb +53 -0
- data/logic/types.rb +141 -0
- data/ports/cli.rb +26 -0
- data/ports/dsl/datomic-flare/errors.rb +5 -0
- data/ports/dsl/datomic-flare.rb +20 -0
- data/static/gem.rb +15 -0
- metadata +146 -0
data/docs/CURL.md
ADDED
@@ -0,0 +1,781 @@
|
|
1
|
+
# Datomic Flare
|
2
|
+
|
3
|
+
A web server that offers an HTTP/JSON API for interacting with [Datomic](https://www.datomic.com) databases.
|
4
|
+
|
5
|
+

|
6
|
+
|
7
|
+
_This is not an official Datomic project or documentation and it is not affiliated with Datomic in any way._
|
8
|
+
|
9
|
+
## TL;DR and Quick Start
|
10
|
+
|
11
|
+
Ensure you have [Java](https://clojure.org/guides/install_clojure#java) and [Clojure](https://clojure.org/guides/install_clojure) installed.
|
12
|
+
|
13
|
+
```bash
|
14
|
+
cp .env.example .env
|
15
|
+
|
16
|
+
```
|
17
|
+
|
18
|
+
```bash
|
19
|
+
clj -M:run
|
20
|
+
|
21
|
+
```
|
22
|
+
|
23
|
+
```text
|
24
|
+
[main] INFO flare.components.server - Starting server on http://0.0.0.0:3042 as peer
|
25
|
+
|
26
|
+
```
|
27
|
+
|
28
|
+
Ensure you have [curl](https://github.com/curl/curl), [bb](https://github.com/babashka/babashka), and [jq](https://github.com/jqlang/jq) installed.
|
29
|
+
|
30
|
+
Transact a Schema:
|
31
|
+
|
32
|
+
|
33
|
+
```bash
|
34
|
+
echo '
|
35
|
+
[{:db/ident :book/title
|
36
|
+
:db/valueType :db.type/string
|
37
|
+
:db/cardinality :db.cardinality/one
|
38
|
+
:db/doc "The title of the book."}
|
39
|
+
|
40
|
+
{:db/ident :book/genre
|
41
|
+
:db/valueType :db.type/string
|
42
|
+
:db/cardinality :db.cardinality/one
|
43
|
+
:db/doc "The genre of the book."}]
|
44
|
+
' \
|
45
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
46
|
+
| curl -s http://localhost:3042/datomic/transact \
|
47
|
+
-X POST \
|
48
|
+
-H "Content-Type: application/json" \
|
49
|
+
--data-binary @- <<JSON \
|
50
|
+
| jq
|
51
|
+
{
|
52
|
+
"data": $(cat)
|
53
|
+
}
|
54
|
+
JSON
|
55
|
+
```
|
56
|
+
|
57
|
+
Assert Facts:
|
58
|
+
|
59
|
+
|
60
|
+
```bash
|
61
|
+
echo '
|
62
|
+
[{:db/id -1
|
63
|
+
:book/title "The Tell-Tale Heart"
|
64
|
+
:book/genre "Horror"}]
|
65
|
+
' \
|
66
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
67
|
+
| curl -s http://localhost:3042/datomic/transact \
|
68
|
+
-X POST \
|
69
|
+
-H "Content-Type: application/json" \
|
70
|
+
--data-binary @- <<JSON \
|
71
|
+
| jq
|
72
|
+
{
|
73
|
+
"data": $(cat)
|
74
|
+
}
|
75
|
+
JSON
|
76
|
+
```
|
77
|
+
|
78
|
+
Read the Data by Querying:
|
79
|
+
|
80
|
+
|
81
|
+
```bash
|
82
|
+
echo '
|
83
|
+
[:find ?e ?title ?genre
|
84
|
+
:where [?e :book/title ?title]
|
85
|
+
[?e :book/genre ?genre]]
|
86
|
+
' \
|
87
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
88
|
+
| curl -s http://localhost:3042/datomic/q \
|
89
|
+
-X GET \
|
90
|
+
-H "Content-Type: application/json" \
|
91
|
+
--data-binary @- <<JSON \
|
92
|
+
| jq
|
93
|
+
{
|
94
|
+
"inputs": [
|
95
|
+
{
|
96
|
+
"database": {
|
97
|
+
"latest": true
|
98
|
+
}
|
99
|
+
}
|
100
|
+
],
|
101
|
+
"query": $(cat)
|
102
|
+
}
|
103
|
+
JSON
|
104
|
+
```
|
105
|
+
|
106
|
+
```json
|
107
|
+
{
|
108
|
+
"data": [
|
109
|
+
[
|
110
|
+
4611681620380877802,
|
111
|
+
"The Tell-Tale Heart",
|
112
|
+
"Horror"
|
113
|
+
]
|
114
|
+
]
|
115
|
+
}
|
116
|
+
```
|
117
|
+
|
118
|
+
|
119
|
+
- [TL;DR and Quick Start](#tldr-and-quick-start)
|
120
|
+
- [Running](#running)
|
121
|
+
- [Quick Start](#quick-start)
|
122
|
+
- [CURL](#curl)
|
123
|
+
- [Ruby](#ruby)
|
124
|
+
- [JavaScript](#javascript)
|
125
|
+
- [Python](#python)
|
126
|
+
- [Usage](#usage)
|
127
|
+
- [Meta](#meta)
|
128
|
+
- [Creating a Database](#creating-a-database)
|
129
|
+
- [Deleting a Database](#deleting-a-database)
|
130
|
+
- [Listing Databases](#listing-databases)
|
131
|
+
- [Transacting Schema](#transacting-schema)
|
132
|
+
- [Asserting Facts](#asserting-facts)
|
133
|
+
- [Reading Data by Entity](#reading-data-by-entity)
|
134
|
+
- [Reading Data by Querying](#reading-data-by-querying)
|
135
|
+
- [Accumulating Facts](#accumulating-facts)
|
136
|
+
- [Retracting Facts](#retracting-facts)
|
137
|
+
- [About](#about)
|
138
|
+
- [Characteristics](#characteristics)
|
139
|
+
- [Trade-offs](#trade-offs)
|
140
|
+
- [Development](#development)
|
141
|
+
|
142
|
+
## Running
|
143
|
+
|
144
|
+
The server can operate in _Client Mode_, using `com.datomic/client-pro` to connect to a Datomic Peer Server, or in _Peer Mode_, embedding `com.datomic/peer` to establish a _Peer_ directly within the server.
|
145
|
+
|
146
|
+
Copy the `.env.example` file and fill it with the appropriate information.
|
147
|
+
|
148
|
+
```bash
|
149
|
+
cp .env.example .env
|
150
|
+
|
151
|
+
```
|
152
|
+
|
153
|
+
If you want _Client Mode_:
|
154
|
+
```bash
|
155
|
+
FLARE_PORT=3042
|
156
|
+
FLARE_BIND=0.0.0.0
|
157
|
+
|
158
|
+
FLARE_MODE=client
|
159
|
+
|
160
|
+
FLARE_CLIENT_ENDPOINT=localhost:8998
|
161
|
+
FLARE_CLIENT_SECRET=unsafe-secret
|
162
|
+
FLARE_CLIENT_ACCESS_KEY=unsafe-key
|
163
|
+
FLARE_CLIENT_DATABASE_NAME=my-datomic-database
|
164
|
+
|
165
|
+
```
|
166
|
+
|
167
|
+
If you want _Peer Mode_:
|
168
|
+
```bash
|
169
|
+
FLARE_PORT=3042
|
170
|
+
FLARE_BIND=0.0.0.0
|
171
|
+
|
172
|
+
FLARE_MODE=peer
|
173
|
+
|
174
|
+
FLARE_PEER_CONNECTION_URI="datomic:sql://my-datomic-database?jdbc:postgresql://localhost:5432/my-datomic-storage?user=datomic-user&password=unsafe"
|
175
|
+
|
176
|
+
```
|
177
|
+
|
178
|
+
Ensure you have [Java](https://clojure.org/guides/install_clojure#java) and [Clojure](https://clojure.org/guides/install_clojure) installed.
|
179
|
+
|
180
|
+
Run the server:
|
181
|
+
|
182
|
+
```bash
|
183
|
+
clj -M:run
|
184
|
+
|
185
|
+
```
|
186
|
+
|
187
|
+
```text
|
188
|
+
[main] INFO flare.components.server - Starting server on http://0.0.0.0:3042 as peer
|
189
|
+
|
190
|
+
```
|
191
|
+
|
192
|
+
You should be able to start firing requests to the server:
|
193
|
+
|
194
|
+
|
195
|
+
```bash
|
196
|
+
curl -s http://localhost:3042/meta \
|
197
|
+
-X GET \
|
198
|
+
-H "Content-Type: application/json" \
|
199
|
+
| jq
|
200
|
+
```
|
201
|
+
|
202
|
+
```json
|
203
|
+
{
|
204
|
+
"data": {
|
205
|
+
"datomic-flare": "1.0.0",
|
206
|
+
"org.clojure/clojure": "1.12.0",
|
207
|
+
"com.datomic/peer": "1.0.7187",
|
208
|
+
"com.datomic/client-pro": "1.0.81"
|
209
|
+
}
|
210
|
+
}
|
211
|
+
```
|
212
|
+
|
213
|
+
## Quick Start
|
214
|
+
|
215
|
+
### CURL
|
216
|
+
TODO
|
217
|
+
|
218
|
+
### Ruby
|
219
|
+
TODO
|
220
|
+
|
221
|
+
### JavaScript
|
222
|
+
TODO
|
223
|
+
|
224
|
+
### Python
|
225
|
+
TODO
|
226
|
+
|
227
|
+
## Usage
|
228
|
+
|
229
|
+
Ensure you have [curl](https://github.com/curl/curl), [bb](https://github.com/babashka/babashka), and [jq](https://github.com/jqlang/jq) installed.
|
230
|
+
|
231
|
+
### Meta
|
232
|
+
|
233
|
+
|
234
|
+
```bash
|
235
|
+
curl -s http://localhost:3042/meta \
|
236
|
+
-X GET \
|
237
|
+
-H "Content-Type: application/json" \
|
238
|
+
| jq
|
239
|
+
```
|
240
|
+
|
241
|
+
```json
|
242
|
+
{
|
243
|
+
"data": {
|
244
|
+
"datomic-flare": "1.0.0",
|
245
|
+
"org.clojure/clojure": "1.12.0",
|
246
|
+
"com.datomic/peer": "1.0.7187",
|
247
|
+
"com.datomic/client-pro": "1.0.81"
|
248
|
+
}
|
249
|
+
}
|
250
|
+
```
|
251
|
+
|
252
|
+
### Creating a Database
|
253
|
+
|
254
|
+
|
255
|
+
```bash
|
256
|
+
curl -s http://localhost:3042/datomic/create-database \
|
257
|
+
-X POST \
|
258
|
+
-H "Content-Type: application/json" \
|
259
|
+
-d '
|
260
|
+
{
|
261
|
+
"name": "moonlight"
|
262
|
+
}
|
263
|
+
' \
|
264
|
+
| jq
|
265
|
+
```
|
266
|
+
|
267
|
+
```json
|
268
|
+
{
|
269
|
+
"data": true
|
270
|
+
}
|
271
|
+
```
|
272
|
+
|
273
|
+
### Deleting a Database
|
274
|
+
|
275
|
+
|
276
|
+
```bash
|
277
|
+
curl -s http://localhost:3042/datomic/delete-database \
|
278
|
+
-X DELETE \
|
279
|
+
-H "Content-Type: application/json" \
|
280
|
+
-d '
|
281
|
+
{
|
282
|
+
"name": "moonlight"
|
283
|
+
}
|
284
|
+
' \
|
285
|
+
| jq
|
286
|
+
```
|
287
|
+
|
288
|
+
```json
|
289
|
+
{
|
290
|
+
"data": true
|
291
|
+
}
|
292
|
+
```
|
293
|
+
|
294
|
+
### Listing Databases
|
295
|
+
|
296
|
+
Flare on Peer Mode:
|
297
|
+
```bash
|
298
|
+
curl -s http://localhost:3042/datomic/get-database-names \
|
299
|
+
-X GET \
|
300
|
+
-H "Content-Type: application/json" \
|
301
|
+
| jq
|
302
|
+
|
303
|
+
```
|
304
|
+
|
305
|
+
Flare on Client Mode
|
306
|
+
```bash
|
307
|
+
curl -s http://localhost:3042/datomic/list-databases \
|
308
|
+
-X GET \
|
309
|
+
-H "Content-Type: application/json" \
|
310
|
+
| jq
|
311
|
+
|
312
|
+
```
|
313
|
+
|
314
|
+
```json
|
315
|
+
{
|
316
|
+
"data": [
|
317
|
+
"my-datomic-database"
|
318
|
+
]
|
319
|
+
}
|
320
|
+
|
321
|
+
```
|
322
|
+
|
323
|
+
### Transacting Schema
|
324
|
+
|
325
|
+
|
326
|
+
```bash
|
327
|
+
echo '
|
328
|
+
[{:db/ident :book/title
|
329
|
+
:db/valueType :db.type/string
|
330
|
+
:db/cardinality :db.cardinality/one
|
331
|
+
:db/doc "The title of the book."}
|
332
|
+
|
333
|
+
{:db/ident :book/genre
|
334
|
+
:db/valueType :db.type/string
|
335
|
+
:db/cardinality :db.cardinality/one
|
336
|
+
:db/doc "The genre of the book."}
|
337
|
+
|
338
|
+
{:db/ident :book/published_at_year
|
339
|
+
:db/valueType :db.type/long
|
340
|
+
:db/cardinality :db.cardinality/one
|
341
|
+
:db/doc "The year the book was first published."}]
|
342
|
+
' \
|
343
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
344
|
+
| curl -s http://localhost:3042/datomic/transact \
|
345
|
+
-X POST \
|
346
|
+
-H "Content-Type: application/json" \
|
347
|
+
--data-binary @- <<JSON \
|
348
|
+
| jq
|
349
|
+
{
|
350
|
+
"data": $(cat)
|
351
|
+
}
|
352
|
+
JSON
|
353
|
+
```
|
354
|
+
|
355
|
+
```json
|
356
|
+
{
|
357
|
+
"data": {
|
358
|
+
"db-before": "datomic.db.Db@1cf55f93",
|
359
|
+
"db-after": "datomic.db.Db@1bdd0be0",
|
360
|
+
"tx-data": [
|
361
|
+
[1003, 50, "Sun Sep 22 08:58:31 BRT 2024", 1003, true],
|
362
|
+
[74, 10, "published_at_year", 1003, true],
|
363
|
+
[74, 40, 22, 1003, true],
|
364
|
+
[74, 41, 35, 1003, true],
|
365
|
+
[74, 62, "The year the book was first published.", 1003, true],
|
366
|
+
[0, 13, 74, 1003, true]
|
367
|
+
],
|
368
|
+
"tempids": {
|
369
|
+
"-9223300668110593560": 72,
|
370
|
+
"-9223300668110593559": 73,
|
371
|
+
"-9223300668110593558": 74
|
372
|
+
}
|
373
|
+
}
|
374
|
+
}
|
375
|
+
```
|
376
|
+
|
377
|
+
### Asserting Facts
|
378
|
+
|
379
|
+
|
380
|
+
```bash
|
381
|
+
echo '
|
382
|
+
[{:db/id -1
|
383
|
+
:book/title "Pride and Prejudice"
|
384
|
+
:book/genre "Romance"
|
385
|
+
:book/published_at_year 1813}]
|
386
|
+
' \
|
387
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
388
|
+
| curl -s http://localhost:3042/datomic/transact \
|
389
|
+
-X POST \
|
390
|
+
-H "Content-Type: application/json" \
|
391
|
+
--data-binary @- <<JSON \
|
392
|
+
| jq
|
393
|
+
{
|
394
|
+
"data": $(cat)
|
395
|
+
}
|
396
|
+
JSON
|
397
|
+
```
|
398
|
+
|
399
|
+
```json
|
400
|
+
{
|
401
|
+
"data": {
|
402
|
+
"db-before": "datomic.db.Db@39bb3c53",
|
403
|
+
"db-after": "datomic.db.Db@d8d15290",
|
404
|
+
"tx-data": [
|
405
|
+
[1004, 50, "Sun Sep 22 08:58:31 BRT 2024", 1004, true],
|
406
|
+
[1005, 72, "Pride and Prejudice", 1004, true],
|
407
|
+
[1005, 73, "Romance", 1004, true],
|
408
|
+
[1005, 74, 1813, 1004, true]
|
409
|
+
],
|
410
|
+
"tempids": {
|
411
|
+
"-1": 4611681620380877805
|
412
|
+
}
|
413
|
+
}
|
414
|
+
}
|
415
|
+
```
|
416
|
+
|
417
|
+
|
418
|
+
|
419
|
+
```bash
|
420
|
+
echo '
|
421
|
+
[{:db/id -1
|
422
|
+
:book/title "Near to the Wild Heart"
|
423
|
+
:book/genre "Novel"
|
424
|
+
:book/published_at_year 1943}
|
425
|
+
{:db/id -2
|
426
|
+
:book/title "A Study in Scarlet"
|
427
|
+
:book/genre "Detective"
|
428
|
+
:book/published_at_year 1887}
|
429
|
+
{:db/id -3
|
430
|
+
:book/title "The Tell-Tale Heart"
|
431
|
+
:book/genre "Horror"
|
432
|
+
:book/published_at_year 1843}]
|
433
|
+
' \
|
434
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
435
|
+
| curl -s http://localhost:3042/datomic/transact \
|
436
|
+
-X POST \
|
437
|
+
-H "Content-Type: application/json" \
|
438
|
+
--data-binary @- <<JSON \
|
439
|
+
| jq
|
440
|
+
{
|
441
|
+
"data": $(cat)
|
442
|
+
}
|
443
|
+
JSON
|
444
|
+
```
|
445
|
+
|
446
|
+
```json
|
447
|
+
{
|
448
|
+
"data": {
|
449
|
+
"db-before": "datomic.db.Db@d8d15290",
|
450
|
+
"db-after": "datomic.db.Db@19234447",
|
451
|
+
"tx-data": [
|
452
|
+
[1006, 50, "Sun Sep 22 08:58:31 BRT 2024", 1006, true],
|
453
|
+
[1007, 72, "Near to the Wild Heart", 1006, true],
|
454
|
+
[1007, 73, "Novel", 1006, true],
|
455
|
+
[1007, 74, 1943, 1006, true],
|
456
|
+
[1008, 72, "A Study in Scarlet", 1006, true],
|
457
|
+
[1008, 73, "Detective", 1006, true],
|
458
|
+
[1008, 74, 1887, 1006, true],
|
459
|
+
[1009, 72, "The Tell-Tale Heart", 1006, true],
|
460
|
+
[1009, 73, "Horror", 1006, true],
|
461
|
+
[1009, 74, 1843, 1006, true]
|
462
|
+
],
|
463
|
+
"tempids": {
|
464
|
+
"-1": 4611681620380877807,
|
465
|
+
"-2": 4611681620380877808,
|
466
|
+
"-3": 4611681620380877809
|
467
|
+
}
|
468
|
+
}
|
469
|
+
}
|
470
|
+
```
|
471
|
+
|
472
|
+
### Reading Data by Entity
|
473
|
+
|
474
|
+
|
475
|
+
```bash
|
476
|
+
curl -s http://localhost:3042/datomic/entity \
|
477
|
+
-X GET \
|
478
|
+
-H "Content-Type: application/json" \
|
479
|
+
-d '
|
480
|
+
{
|
481
|
+
"database": {
|
482
|
+
"latest": true
|
483
|
+
},
|
484
|
+
"id": 4611681620380877807
|
485
|
+
}
|
486
|
+
' \
|
487
|
+
| jq
|
488
|
+
```
|
489
|
+
|
490
|
+
```json
|
491
|
+
{
|
492
|
+
"data": {
|
493
|
+
":book/title": "Near to the Wild Heart",
|
494
|
+
":book/genre": "Novel",
|
495
|
+
":book/published_at_year": 1943,
|
496
|
+
":db/id": 4611681620380877807
|
497
|
+
}
|
498
|
+
}
|
499
|
+
```
|
500
|
+
|
501
|
+
### Reading Data by Querying
|
502
|
+
|
503
|
+
|
504
|
+
```bash
|
505
|
+
echo '
|
506
|
+
[:find ?e ?title ?genre ?year
|
507
|
+
:where [?e :book/title ?title]
|
508
|
+
[?e :book/genre ?genre]
|
509
|
+
[?e :book/published_at_year ?year]]
|
510
|
+
' \
|
511
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
512
|
+
| curl -s http://localhost:3042/datomic/q \
|
513
|
+
-X GET \
|
514
|
+
-H "Content-Type: application/json" \
|
515
|
+
--data-binary @- <<JSON \
|
516
|
+
| jq
|
517
|
+
{
|
518
|
+
"inputs": [
|
519
|
+
{
|
520
|
+
"database": {
|
521
|
+
"latest": true
|
522
|
+
}
|
523
|
+
}
|
524
|
+
],
|
525
|
+
"query": $(cat)
|
526
|
+
}
|
527
|
+
JSON
|
528
|
+
```
|
529
|
+
|
530
|
+
```json
|
531
|
+
{
|
532
|
+
"data": [
|
533
|
+
[
|
534
|
+
4611681620380877808,
|
535
|
+
"A Study in Scarlet",
|
536
|
+
"Detective",
|
537
|
+
1887
|
538
|
+
],
|
539
|
+
[
|
540
|
+
4611681620380877807,
|
541
|
+
"Near to the Wild Heart",
|
542
|
+
"Novel",
|
543
|
+
1943
|
544
|
+
],
|
545
|
+
[
|
546
|
+
4611681620380877809,
|
547
|
+
"The Tell-Tale Heart",
|
548
|
+
"Horror",
|
549
|
+
1843
|
550
|
+
],
|
551
|
+
[
|
552
|
+
4611681620380877805,
|
553
|
+
"Pride and Prejudice",
|
554
|
+
"Romance",
|
555
|
+
1813
|
556
|
+
]
|
557
|
+
]
|
558
|
+
}
|
559
|
+
```
|
560
|
+
|
561
|
+
|
562
|
+
```bash
|
563
|
+
echo '
|
564
|
+
[:find ?e ?title ?genre ?year
|
565
|
+
:in $ ?title
|
566
|
+
:where [?e :book/title ?title]
|
567
|
+
[?e :book/genre ?genre]
|
568
|
+
[?e :book/published_at_year ?year]]
|
569
|
+
' \
|
570
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
571
|
+
| curl -s http://localhost:3042/datomic/q \
|
572
|
+
-X GET \
|
573
|
+
-H "Content-Type: application/json" \
|
574
|
+
--data-binary @- <<JSON \
|
575
|
+
| jq
|
576
|
+
{
|
577
|
+
"inputs": [
|
578
|
+
{
|
579
|
+
"database": {
|
580
|
+
"latest": true
|
581
|
+
}
|
582
|
+
},
|
583
|
+
"The Tell-Tale Heart"
|
584
|
+
],
|
585
|
+
"query": $(cat)
|
586
|
+
}
|
587
|
+
JSON
|
588
|
+
```
|
589
|
+
|
590
|
+
```json
|
591
|
+
{
|
592
|
+
"data": [
|
593
|
+
[
|
594
|
+
4611681620380877809,
|
595
|
+
"The Tell-Tale Heart",
|
596
|
+
"Horror",
|
597
|
+
1843
|
598
|
+
]
|
599
|
+
]
|
600
|
+
}
|
601
|
+
```
|
602
|
+
|
603
|
+
### Accumulating Facts
|
604
|
+
|
605
|
+
|
606
|
+
```bash
|
607
|
+
echo '
|
608
|
+
[{:db/id 4611681620380877806 :book/genre "Gothic"}]
|
609
|
+
' \
|
610
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
611
|
+
| curl -s http://localhost:3042/datomic/transact \
|
612
|
+
-X POST \
|
613
|
+
-H "Content-Type: application/json" \
|
614
|
+
--data-binary @- <<JSON \
|
615
|
+
| jq
|
616
|
+
{
|
617
|
+
"data": $(cat)
|
618
|
+
}
|
619
|
+
JSON
|
620
|
+
```
|
621
|
+
|
622
|
+
```json
|
623
|
+
{
|
624
|
+
"data": {
|
625
|
+
"db-before": "datomic.db.Db@19234447",
|
626
|
+
"db-after": "datomic.db.Db@6f78a7c",
|
627
|
+
"tx-data": [
|
628
|
+
[1010, 50, "Sun Sep 22 08:58:31 BRT 2024", 1010, true],
|
629
|
+
[1006, 73, "Gothic", 1010, true]
|
630
|
+
],
|
631
|
+
"tempids": {
|
632
|
+
}
|
633
|
+
}
|
634
|
+
}
|
635
|
+
```
|
636
|
+
|
637
|
+
### Retracting Facts
|
638
|
+
|
639
|
+
Retract the value of an attribute:
|
640
|
+
|
641
|
+
|
642
|
+
```bash
|
643
|
+
echo '
|
644
|
+
[[:db/retract 4611681620380877806 :book/genre "Gothic"]]
|
645
|
+
' \
|
646
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
647
|
+
| curl -s http://localhost:3042/datomic/transact \
|
648
|
+
-X POST \
|
649
|
+
-H "Content-Type: application/json" \
|
650
|
+
--data-binary @- <<JSON \
|
651
|
+
| jq
|
652
|
+
{
|
653
|
+
"data": $(cat)
|
654
|
+
}
|
655
|
+
JSON
|
656
|
+
```
|
657
|
+
|
658
|
+
```json
|
659
|
+
{
|
660
|
+
"data": {
|
661
|
+
"db-before": "datomic.db.Db@6f78a7c",
|
662
|
+
"db-after": "datomic.db.Db@89bedc15",
|
663
|
+
"tx-data": [
|
664
|
+
[1011, 50, "Sun Sep 22 08:58:31 BRT 2024", 1011, true],
|
665
|
+
[1006, 73, "Gothic", 1011, false]
|
666
|
+
],
|
667
|
+
"tempids": {
|
668
|
+
}
|
669
|
+
}
|
670
|
+
}
|
671
|
+
```
|
672
|
+
|
673
|
+
Retract an attribute:
|
674
|
+
|
675
|
+
|
676
|
+
```bash
|
677
|
+
echo '
|
678
|
+
[[:db/retract 4611681620380877804 :book/genre]]
|
679
|
+
' \
|
680
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
681
|
+
| curl -s http://localhost:3042/datomic/transact \
|
682
|
+
-X POST \
|
683
|
+
-H "Content-Type: application/json" \
|
684
|
+
--data-binary @- <<JSON \
|
685
|
+
| jq
|
686
|
+
{
|
687
|
+
"data": $(cat)
|
688
|
+
}
|
689
|
+
JSON
|
690
|
+
```
|
691
|
+
|
692
|
+
```json
|
693
|
+
{
|
694
|
+
"data": {
|
695
|
+
"db-before": "datomic.db.Db@89bedc15",
|
696
|
+
"db-after": "datomic.db.Db@4fa1fea2",
|
697
|
+
"tx-data": [
|
698
|
+
[1012, 50, "Sun Sep 22 08:58:31 BRT 2024", 1012, true]
|
699
|
+
],
|
700
|
+
"tempids": {
|
701
|
+
}
|
702
|
+
}
|
703
|
+
}
|
704
|
+
```
|
705
|
+
|
706
|
+
Retract an entity:
|
707
|
+
|
708
|
+
|
709
|
+
```bash
|
710
|
+
echo '
|
711
|
+
[[:db/retractEntity 4611681620380877805]]
|
712
|
+
' \
|
713
|
+
| bb -e '(pr-str (edn/read-string (slurp *in*)))' \
|
714
|
+
| curl -s http://localhost:3042/datomic/transact \
|
715
|
+
-X POST \
|
716
|
+
-H "Content-Type: application/json" \
|
717
|
+
--data-binary @- <<JSON \
|
718
|
+
| jq
|
719
|
+
{
|
720
|
+
"data": $(cat)
|
721
|
+
}
|
722
|
+
JSON
|
723
|
+
```
|
724
|
+
|
725
|
+
```json
|
726
|
+
{
|
727
|
+
"data": {
|
728
|
+
"db-before": "datomic.db.Db@4fa1fea2",
|
729
|
+
"db-after": "datomic.db.Db@74650f2d",
|
730
|
+
"tx-data": [
|
731
|
+
[1013, 50, "Sun Sep 22 08:58:31 BRT 2024", 1013, true],
|
732
|
+
[1005, 72, "Pride and Prejudice", 1013, false],
|
733
|
+
[1005, 73, "Romance", 1013, false],
|
734
|
+
[1005, 74, 1813, 1013, false]
|
735
|
+
],
|
736
|
+
"tempids": {
|
737
|
+
}
|
738
|
+
}
|
739
|
+
}
|
740
|
+
```
|
741
|
+
|
742
|
+
## About
|
743
|
+
|
744
|
+
### Characteristics
|
745
|
+
|
746
|
+
- Languages that play well with HTTP and JSON can interact with Datomic right away.
|
747
|
+
|
748
|
+
- Plug and play into any of the many flavors of Datomic's flexible infrastructure architecture.
|
749
|
+
|
750
|
+
- Minimal and transparent layer, not a DSL or framework, just straightforward access to Datomic.
|
751
|
+
|
752
|
+
- Despite JSON, both queries and transactions are done in EDN, enabling, e.g., powerful Datalog queries.
|
753
|
+
|
754
|
+
### Trade-offs
|
755
|
+
|
756
|
+
- Languages have different data types, so EDN -> JSON -> [Your Language] and vice-versa: something will be lost in translation and expressiveness.
|
757
|
+
|
758
|
+
- An extra layer in the architecture adds a new hop to requests, potentially increasing latency.
|
759
|
+
|
760
|
+
- Being one step away from Clojure reduces our power to leverage its types, data structures, immutability, and other desired properties.
|
761
|
+
|
762
|
+
- Some tricks that would be easy to do in Clojure + Datomic become more cumbersome: transaction functions, advanced Datalog datasources, lazy loading, etc.
|
763
|
+
|
764
|
+
## Development
|
765
|
+
|
766
|
+
```bash
|
767
|
+
clj -M:repl
|
768
|
+
|
769
|
+
```
|
770
|
+
|
771
|
+
```bash
|
772
|
+
clj -M:format
|
773
|
+
clj -M:lint
|
774
|
+
|
775
|
+
```
|
776
|
+
|
777
|
+
```bash
|
778
|
+
cljfmt fix deps.edn src/
|
779
|
+
clj-kondo --lint deps.edn src/
|
780
|
+
|
781
|
+
```
|