datomic-flare 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ ![The image features a logo with curved lines forming a tesseract, suggesting distortion and movement like space-time.](https://media.githubusercontent.com/media/gbaptista/assets/refs/heads/main/datomic-flare/datomic-flare-canvas.png)
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
+ ```