datahike-browser-tests 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.
Files changed (324) hide show
  1. package/.circleci/config.yml +405 -0
  2. package/.circleci/scripts/gen_ci.clj +194 -0
  3. package/.cirrus.yml +60 -0
  4. package/.clj-kondo/babashka/sci/config.edn +1 -0
  5. package/.clj-kondo/babashka/sci/sci/core.clj +9 -0
  6. package/.clj-kondo/config.edn +95 -0
  7. package/.dir-locals.el +2 -0
  8. package/.github/FUNDING.yml +3 -0
  9. package/.github/ISSUE_TEMPLATE/1-bug-report.yml +68 -0
  10. package/.github/ISSUE_TEMPLATE/2-feature-request.yml +28 -0
  11. package/.github/ISSUE_TEMPLATE/config.yml +6 -0
  12. package/.github/pull_request_template.md +24 -0
  13. package/.github/workflows/native-image.yml +84 -0
  14. package/LICENSE +203 -0
  15. package/README.md +273 -0
  16. package/bb/deps.edn +9 -0
  17. package/bb/resources/github-fingerprints +3 -0
  18. package/bb/resources/native-image-tests/run-bb-pod-tests.clj +162 -0
  19. package/bb/resources/native-image-tests/run-libdatahike-tests +12 -0
  20. package/bb/resources/native-image-tests/run-native-image-tests +74 -0
  21. package/bb/resources/native-image-tests/run-python-tests +22 -0
  22. package/bb/resources/native-image-tests/testconfig.attr-refs.edn +6 -0
  23. package/bb/resources/native-image-tests/testconfig.edn +5 -0
  24. package/bb/resources/template/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  25. package/bb/resources/template/.settings/org.eclipse.jdt.core.prefs +9 -0
  26. package/bb/resources/template/.settings/org.eclipse.m2e.core.prefs +4 -0
  27. package/bb/resources/template/pom.xml +22 -0
  28. package/bb/src/tools/build.clj +132 -0
  29. package/bb/src/tools/clj_kondo.clj +32 -0
  30. package/bb/src/tools/deploy.clj +26 -0
  31. package/bb/src/tools/examples.clj +19 -0
  32. package/bb/src/tools/npm.clj +100 -0
  33. package/bb/src/tools/python.clj +14 -0
  34. package/bb/src/tools/release.clj +94 -0
  35. package/bb/src/tools/test.clj +148 -0
  36. package/bb/src/tools/version.clj +47 -0
  37. package/bb.edn +269 -0
  38. package/benchmark/src/benchmark/cli.clj +195 -0
  39. package/benchmark/src/benchmark/compare.clj +157 -0
  40. package/benchmark/src/benchmark/config.clj +316 -0
  41. package/benchmark/src/benchmark/measure.clj +187 -0
  42. package/benchmark/src/benchmark/store.clj +190 -0
  43. package/benchmark/test/benchmark/measure_test.clj +156 -0
  44. package/build.clj +30 -0
  45. package/config.edn +49 -0
  46. package/deps.edn +138 -0
  47. package/dev/sandbox.clj +82 -0
  48. package/dev/sandbox.cljs +127 -0
  49. package/dev/sandbox_benchmarks.clj +27 -0
  50. package/dev/sandbox_client.clj +87 -0
  51. package/dev/sandbox_transact_bench.clj +109 -0
  52. package/dev/user.clj +79 -0
  53. package/doc/README.md +96 -0
  54. package/doc/adl/README.md +6 -0
  55. package/doc/adl/adr-000-adr.org +28 -0
  56. package/doc/adl/adr-001-attribute-references.org +15 -0
  57. package/doc/adl/adr-002-build-tooling.org +54 -0
  58. package/doc/adl/adr-003-db-meta-data.md +52 -0
  59. package/doc/adl/adr-004-github-flow.md +40 -0
  60. package/doc/adl/adr-XYZ-template.md +30 -0
  61. package/doc/adl/index.org +3 -0
  62. package/doc/assets/datahike-logo.svg +3 -0
  63. package/doc/assets/datahiking-invoice.org +85 -0
  64. package/doc/assets/hhtree2.png +0 -0
  65. package/doc/assets/network_topology.svg +624 -0
  66. package/doc/assets/perf.png +0 -0
  67. package/doc/assets/schema_mindmap.mm +132 -0
  68. package/doc/assets/schema_mindmap.svg +970 -0
  69. package/doc/assets/temporal_index.mm +74 -0
  70. package/doc/backend-development.md +78 -0
  71. package/doc/bb-pod.md +89 -0
  72. package/doc/benchmarking.md +360 -0
  73. package/doc/bindings/edn-conversion.md +383 -0
  74. package/doc/cli.md +162 -0
  75. package/doc/cljdoc.edn +27 -0
  76. package/doc/cljs-support.md +133 -0
  77. package/doc/config.md +406 -0
  78. package/doc/contributing.md +114 -0
  79. package/doc/datalog-vs-sql.md +210 -0
  80. package/doc/datomic_differences.md +109 -0
  81. package/doc/development/pull-api-ns.md +186 -0
  82. package/doc/development/pull-frame-state-diagram.jpg +0 -0
  83. package/doc/distributed.md +566 -0
  84. package/doc/entity_spec.md +92 -0
  85. package/doc/gc.md +273 -0
  86. package/doc/java-api.md +808 -0
  87. package/doc/javascript-api.md +421 -0
  88. package/doc/libdatahike.md +86 -0
  89. package/doc/logging_and_error_handling.md +43 -0
  90. package/doc/norms.md +66 -0
  91. package/doc/schema-migration.md +85 -0
  92. package/doc/schema.md +287 -0
  93. package/doc/storage-backends.md +363 -0
  94. package/doc/store-id-refactoring.md +596 -0
  95. package/doc/time_variance.md +325 -0
  96. package/doc/unstructured.md +167 -0
  97. package/doc/versioning.md +261 -0
  98. package/examples/basic/README.md +19 -0
  99. package/examples/basic/deps.edn +6 -0
  100. package/examples/basic/docker-compose.yml +13 -0
  101. package/examples/basic/src/examples/core.clj +60 -0
  102. package/examples/basic/src/examples/schema.clj +155 -0
  103. package/examples/basic/src/examples/store.clj +60 -0
  104. package/examples/basic/src/examples/time_travel.clj +185 -0
  105. package/examples/java/.settings/org.eclipse.core.resources.prefs +3 -0
  106. package/examples/java/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
  107. package/examples/java/.settings/org.eclipse.jdt.core.prefs +9 -0
  108. package/examples/java/.settings/org.eclipse.m2e.core.prefs +4 -0
  109. package/examples/java/README.md +162 -0
  110. package/examples/java/pom.xml +62 -0
  111. package/examples/java/src/main/java/examples/QuickStart.java +115 -0
  112. package/examples/java/src/main/java/examples/SchemaExample.java +148 -0
  113. package/examples/java/src/main/java/examples/TimeTravelExample.java +121 -0
  114. package/flake.lock +27 -0
  115. package/flake.nix +27 -0
  116. package/http-server/datahike/http/middleware.clj +75 -0
  117. package/http-server/datahike/http/server.clj +269 -0
  118. package/java/src/datahike/java/Database.java +274 -0
  119. package/java/src/datahike/java/Datahike.java +281 -0
  120. package/java/src/datahike/java/DatahikeGeneratedTest.java +349 -0
  121. package/java/src/datahike/java/DatahikeTest.java +370 -0
  122. package/java/src/datahike/java/EDN.java +170 -0
  123. package/java/src/datahike/java/IEntity.java +11 -0
  124. package/java/src/datahike/java/Keywords.java +161 -0
  125. package/java/src/datahike/java/SchemaFlexibility.java +52 -0
  126. package/java/src/datahike/java/Util.java +219 -0
  127. package/karma.conf.js +19 -0
  128. package/libdatahike/compile-cpp +7 -0
  129. package/libdatahike/src/datahike/impl/LibDatahikeBase.java +203 -0
  130. package/libdatahike/src/datahike/impl/libdatahike.clj +59 -0
  131. package/libdatahike/src/test_cpp.cpp +61 -0
  132. package/npm-package/PUBLISHING.md +140 -0
  133. package/npm-package/README.md +226 -0
  134. package/npm-package/package.template.json +34 -0
  135. package/npm-package/test-isomorphic.ts +281 -0
  136. package/npm-package/test.js +557 -0
  137. package/npm-package/typescript-test.ts +70 -0
  138. package/package.json +16 -0
  139. package/pydatahike/README.md +569 -0
  140. package/pydatahike/pyproject.toml +91 -0
  141. package/pydatahike/setup.py +42 -0
  142. package/pydatahike/src/datahike/__init__.py +134 -0
  143. package/pydatahike/src/datahike/_native.py +250 -0
  144. package/pydatahike/src/datahike/_version.py +2 -0
  145. package/pydatahike/src/datahike/database.py +722 -0
  146. package/pydatahike/src/datahike/edn.py +311 -0
  147. package/pydatahike/src/datahike/py.typed +0 -0
  148. package/pydatahike/tests/conftest.py +17 -0
  149. package/pydatahike/tests/test_basic.py +170 -0
  150. package/pydatahike/tests/test_database.py +51 -0
  151. package/pydatahike/tests/test_edn_conversion.py +299 -0
  152. package/pydatahike/tests/test_query.py +99 -0
  153. package/pydatahike/tests/test_schema.py +55 -0
  154. package/resources/clj-kondo.exports/io.replikativ/datahike/config.edn +5 -0
  155. package/resources/example_server.edn +4 -0
  156. package/shadow-cljs.edn +56 -0
  157. package/src/data_readers.clj +7 -0
  158. package/src/datahike/api/impl.cljc +176 -0
  159. package/src/datahike/api/specification.cljc +633 -0
  160. package/src/datahike/api/types.cljc +261 -0
  161. package/src/datahike/api.cljc +41 -0
  162. package/src/datahike/array.cljc +99 -0
  163. package/src/datahike/cli.clj +166 -0
  164. package/src/datahike/cljs.cljs +6 -0
  165. package/src/datahike/codegen/cli.clj +406 -0
  166. package/src/datahike/codegen/clj_kondo.clj +291 -0
  167. package/src/datahike/codegen/java.clj +403 -0
  168. package/src/datahike/codegen/naming.cljc +33 -0
  169. package/src/datahike/codegen/native.clj +559 -0
  170. package/src/datahike/codegen/pod.clj +488 -0
  171. package/src/datahike/codegen/python.clj +838 -0
  172. package/src/datahike/codegen/report.clj +55 -0
  173. package/src/datahike/codegen/typescript.clj +262 -0
  174. package/src/datahike/codegen/validation.clj +145 -0
  175. package/src/datahike/config.cljc +294 -0
  176. package/src/datahike/connections.cljc +16 -0
  177. package/src/datahike/connector.cljc +265 -0
  178. package/src/datahike/constants.cljc +142 -0
  179. package/src/datahike/core.cljc +297 -0
  180. package/src/datahike/datom.cljc +459 -0
  181. package/src/datahike/db/interface.cljc +119 -0
  182. package/src/datahike/db/search.cljc +305 -0
  183. package/src/datahike/db/transaction.cljc +937 -0
  184. package/src/datahike/db/utils.cljc +338 -0
  185. package/src/datahike/db.cljc +956 -0
  186. package/src/datahike/experimental/unstructured.cljc +126 -0
  187. package/src/datahike/experimental/versioning.cljc +172 -0
  188. package/src/datahike/externs.js +31 -0
  189. package/src/datahike/gc.cljc +69 -0
  190. package/src/datahike/http/client.clj +188 -0
  191. package/src/datahike/http/writer.clj +79 -0
  192. package/src/datahike/impl/entity.cljc +218 -0
  193. package/src/datahike/index/interface.cljc +93 -0
  194. package/src/datahike/index/persistent_set.cljc +469 -0
  195. package/src/datahike/index/utils.cljc +44 -0
  196. package/src/datahike/index.cljc +32 -0
  197. package/src/datahike/js/api.cljs +172 -0
  198. package/src/datahike/js/api_macros.clj +22 -0
  199. package/src/datahike/js.cljs +163 -0
  200. package/src/datahike/json.cljc +209 -0
  201. package/src/datahike/lru.cljc +146 -0
  202. package/src/datahike/migrate.clj +39 -0
  203. package/src/datahike/norm/norm.clj +245 -0
  204. package/src/datahike/online_gc.cljc +252 -0
  205. package/src/datahike/pod.clj +155 -0
  206. package/src/datahike/pull_api.cljc +325 -0
  207. package/src/datahike/query.cljc +1945 -0
  208. package/src/datahike/query_stats.cljc +88 -0
  209. package/src/datahike/readers.cljc +62 -0
  210. package/src/datahike/remote.cljc +218 -0
  211. package/src/datahike/schema.cljc +228 -0
  212. package/src/datahike/schema_cache.cljc +42 -0
  213. package/src/datahike/spec.cljc +101 -0
  214. package/src/datahike/store.cljc +80 -0
  215. package/src/datahike/tools.cljc +308 -0
  216. package/src/datahike/transit.cljc +80 -0
  217. package/src/datahike/writer.cljc +239 -0
  218. package/src/datahike/writing.cljc +362 -0
  219. package/src/deps.cljs +1 -0
  220. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/insert.cljc +76 -0
  221. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/upsert.cljc +128 -0
  222. package/src-hitchhiker-tree/datahike/index/hitchhiker_tree.cljc +213 -0
  223. package/test/datahike/backward_compatibility_test/src/backward_test.clj +37 -0
  224. package/test/datahike/integration_test/config_record_file_test.clj +14 -0
  225. package/test/datahike/integration_test/config_record_test.clj +14 -0
  226. package/test/datahike/integration_test/depr_config_uri_test.clj +15 -0
  227. package/test/datahike/integration_test/return_map_test.clj +62 -0
  228. package/test/datahike/integration_test.cljc +67 -0
  229. package/test/datahike/norm/norm_test.clj +124 -0
  230. package/test/datahike/norm/resources/naming-and-sorting-test/001-a1-example.edn +5 -0
  231. package/test/datahike/norm/resources/naming-and-sorting-test/002-a2-example.edn +5 -0
  232. package/test/datahike/norm/resources/naming-and-sorting-test/003-tx-fn-test.edn +1 -0
  233. package/test/datahike/norm/resources/naming-and-sorting-test/004-tx-data-and-tx-fn-test.edn +5 -0
  234. package/test/datahike/norm/resources/naming-and-sorting-test/01-transact-basic-characters.edn +2 -0
  235. package/test/datahike/norm/resources/naming-and-sorting-test/02 add occupation.edn +5 -0
  236. package/test/datahike/norm/resources/naming-and-sorting-test/checksums.edn +12 -0
  237. package/test/datahike/norm/resources/simple-test/001-a1-example.edn +5 -0
  238. package/test/datahike/norm/resources/simple-test/002-a2-example.edn +5 -0
  239. package/test/datahike/norm/resources/simple-test/checksums.edn +4 -0
  240. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/001-a1-example.edn +5 -0
  241. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/002-a2-example.edn +5 -0
  242. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/003-tx-fn-test.edn +1 -0
  243. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/checksums.edn +6 -0
  244. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/004-tx-data-and-tx-fn-test.edn +5 -0
  245. package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/checksums.edn +2 -0
  246. package/test/datahike/norm/resources/tx-fn-test/first/001-a1-example.edn +5 -0
  247. package/test/datahike/norm/resources/tx-fn-test/first/002-a2-example.edn +5 -0
  248. package/test/datahike/norm/resources/tx-fn-test/first/checksums.edn +4 -0
  249. package/test/datahike/norm/resources/tx-fn-test/second/003-tx-fn-test.edn +1 -0
  250. package/test/datahike/norm/resources/tx-fn-test/second/checksums.edn +2 -0
  251. package/test/datahike/test/api_test.cljc +895 -0
  252. package/test/datahike/test/array_test.cljc +40 -0
  253. package/test/datahike/test/attribute_refs/datoms_test.cljc +140 -0
  254. package/test/datahike/test/attribute_refs/db_test.cljc +42 -0
  255. package/test/datahike/test/attribute_refs/differences_test.cljc +515 -0
  256. package/test/datahike/test/attribute_refs/entity_test.cljc +89 -0
  257. package/test/datahike/test/attribute_refs/pull_api_test.cljc +320 -0
  258. package/test/datahike/test/attribute_refs/query_find_specs_test.cljc +59 -0
  259. package/test/datahike/test/attribute_refs/query_fns_test.cljc +130 -0
  260. package/test/datahike/test/attribute_refs/query_interop_test.cljc +47 -0
  261. package/test/datahike/test/attribute_refs/query_not_test.cljc +193 -0
  262. package/test/datahike/test/attribute_refs/query_or_test.cljc +137 -0
  263. package/test/datahike/test/attribute_refs/query_pull_test.cljc +156 -0
  264. package/test/datahike/test/attribute_refs/query_rules_test.cljc +176 -0
  265. package/test/datahike/test/attribute_refs/query_test.cljc +241 -0
  266. package/test/datahike/test/attribute_refs/temporal_search.cljc +22 -0
  267. package/test/datahike/test/attribute_refs/transact_test.cljc +220 -0
  268. package/test/datahike/test/attribute_refs/utils.cljc +128 -0
  269. package/test/datahike/test/cache_test.cljc +38 -0
  270. package/test/datahike/test/components_test.cljc +92 -0
  271. package/test/datahike/test/config_test.cljc +158 -0
  272. package/test/datahike/test/core_test.cljc +105 -0
  273. package/test/datahike/test/datom_test.cljc +44 -0
  274. package/test/datahike/test/db_test.cljc +54 -0
  275. package/test/datahike/test/entity_spec_test.cljc +159 -0
  276. package/test/datahike/test/entity_test.cljc +103 -0
  277. package/test/datahike/test/explode_test.cljc +143 -0
  278. package/test/datahike/test/filter_test.cljc +75 -0
  279. package/test/datahike/test/gc_test.cljc +159 -0
  280. package/test/datahike/test/http/server_test.clj +192 -0
  281. package/test/datahike/test/http/writer_test.clj +86 -0
  282. package/test/datahike/test/ident_test.cljc +32 -0
  283. package/test/datahike/test/index_test.cljc +345 -0
  284. package/test/datahike/test/insert.cljc +125 -0
  285. package/test/datahike/test/java_bindings_test.clj +6 -0
  286. package/test/datahike/test/listen_test.cljc +41 -0
  287. package/test/datahike/test/lookup_refs_test.cljc +266 -0
  288. package/test/datahike/test/lru_test.cljc +27 -0
  289. package/test/datahike/test/migrate_test.clj +297 -0
  290. package/test/datahike/test/model/core.cljc +376 -0
  291. package/test/datahike/test/model/invariant.cljc +142 -0
  292. package/test/datahike/test/model/rng.cljc +82 -0
  293. package/test/datahike/test/model_test.clj +217 -0
  294. package/test/datahike/test/nodejs_test.cljs +262 -0
  295. package/test/datahike/test/online_gc_test.cljc +475 -0
  296. package/test/datahike/test/pod_test.clj +369 -0
  297. package/test/datahike/test/pull_api_test.cljc +474 -0
  298. package/test/datahike/test/purge_test.cljc +144 -0
  299. package/test/datahike/test/query_aggregates_test.cljc +101 -0
  300. package/test/datahike/test/query_find_specs_test.cljc +52 -0
  301. package/test/datahike/test/query_fns_test.cljc +523 -0
  302. package/test/datahike/test/query_interop_test.cljc +47 -0
  303. package/test/datahike/test/query_not_test.cljc +189 -0
  304. package/test/datahike/test/query_or_test.cljc +158 -0
  305. package/test/datahike/test/query_pull_test.cljc +147 -0
  306. package/test/datahike/test/query_rules_test.cljc +248 -0
  307. package/test/datahike/test/query_stats_test.cljc +218 -0
  308. package/test/datahike/test/query_test.cljc +984 -0
  309. package/test/datahike/test/schema_test.cljc +424 -0
  310. package/test/datahike/test/specification_test.cljc +30 -0
  311. package/test/datahike/test/store_test.cljc +78 -0
  312. package/test/datahike/test/stress_test.cljc +57 -0
  313. package/test/datahike/test/time_variance_test.cljc +518 -0
  314. package/test/datahike/test/tools_test.clj +134 -0
  315. package/test/datahike/test/transact_test.cljc +518 -0
  316. package/test/datahike/test/tuples_test.cljc +564 -0
  317. package/test/datahike/test/unstructured_test.cljc +291 -0
  318. package/test/datahike/test/upsert_impl_test.cljc +205 -0
  319. package/test/datahike/test/upsert_test.cljc +363 -0
  320. package/test/datahike/test/utils.cljc +110 -0
  321. package/test/datahike/test/validation_test.cljc +48 -0
  322. package/test/datahike/test/versioning_test.cljc +56 -0
  323. package/test/datahike/test.cljc +66 -0
  324. package/tests.edn +24 -0
@@ -0,0 +1,421 @@
1
+ # Datahike JavaScript API
2
+
3
+ **Status: Beta** - API is functional and tested, but may receive breaking changes. Published as `datahike@next` on npm.
4
+
5
+ ## Overview
6
+
7
+ The Datahike JavaScript API provides a Promise-based interface for Node.js and browser environments. All async operations return Promises, and data is automatically converted between JavaScript and ClojureScript.
8
+
9
+ ## Project Structure
10
+
11
+ ```
12
+ src/datahike/js/
13
+ ├── api.cljs # Main JS API implementation
14
+ ├── api_macros.clj # Macro for generating API functions
15
+ ├── naming.cljc # Shared naming conventions (ClojureScript → JavaScript)
16
+ └── typescript.clj # TypeScript definition generator
17
+
18
+ npm-package/
19
+ ├── test.js # Comprehensive test suite
20
+ ├── package.template.json # Version-controlled template
21
+ ├── README.md # npm package documentation
22
+ ├── PUBLISHING.md # Publishing guide
23
+ └── index.d.ts # Generated TypeScript definitions
24
+
25
+ bb/src/tools/
26
+ └── npm.clj # Build automation (version, types, compile, test)
27
+ ```
28
+
29
+ ## Build Configuration
30
+
31
+ The JS API uses a modern automated build pipeline:
32
+
33
+ ```bash
34
+ # Full build: version + types + compile + test
35
+ bb npm-build
36
+
37
+ # Individual steps:
38
+ bb npm-version # Generate package.json from template with version from config.edn
39
+ bb codegen-ts # Generate TypeScript definitions
40
+ bb npm-test # Run npm package tests
41
+ ```
42
+
43
+ Versions are automatically calculated as `major.minor.commit-count` from `config.edn`.
44
+
45
+ Output is generated in `npm-package/datahike.js.api.js` with advanced compilation.
46
+
47
+ ## Installation
48
+
49
+ ```bash
50
+ npm install datahike@next
51
+ ```
52
+
53
+ ## Usage
54
+
55
+ ### Basic Example
56
+
57
+ ```javascript
58
+ const d = require('datahike');
59
+ const crypto = require('crypto');
60
+
61
+ async function example() {
62
+ // Configuration - must use UUID for :id
63
+ const config = {
64
+ store: {
65
+ backend: ':memory',
66
+ id: crypto.randomUUID()
67
+ }
68
+ };
69
+
70
+ // Create database
71
+ await d.createDatabase(config);
72
+
73
+ // Connect
74
+ const conn = await d.connect(config);
75
+
76
+ // Define schema
77
+ // Keys: WITHOUT colon (plain strings)
78
+ // Values: WITH colon prefix (keywords)
79
+ const schema = [
80
+ {
81
+ 'db/ident': ':name',
82
+ 'db/valueType': ':db.type/string',
83
+ 'db/cardinality': ':db.cardinality/one'
84
+ },
85
+ {
86
+ 'db/ident': ':age',
87
+ 'db/valueType': ':db.type/long',
88
+ 'db/cardinality': ':db.cardinality/one'
89
+ }
90
+ ];
91
+ await d.transact(conn, schema);
92
+
93
+ // Insert data (data keys without colons)
94
+ const data = [
95
+ { name: 'Alice', age: 30 },
96
+ { name: 'Bob', age: 25 }
97
+ ];
98
+ await d.transact(conn, data);
99
+
100
+ // Get database value (synchronous)
101
+ const db = await d.db(conn);
102
+
103
+ // Get datoms
104
+ const datoms = await d.datoms(db, ':eavt');
105
+ console.log('Datoms:', datoms.length);
106
+
107
+ // Pull API (pattern attributes with colons)
108
+ const entityId = 1; // Find ID through query or datoms
109
+ const pulled = await d.pull(db, [':name', ':age'], entityId);
110
+ console.log('Entity:', pulled);
111
+
112
+ // Clean up
113
+ d.release(conn);
114
+ await d.deleteDatabase(config);
115
+ }
116
+ ```
117
+
118
+ ## Data Conversion
119
+
120
+ Datahike uses universal EDN conversion rules that are consistent across Python, JavaScript, and Java bindings:
121
+
122
+ > **Keys are always keywordized. Values starting with `:` become keywords, everything else remains literal.**
123
+
124
+ ### JavaScript → ClojureScript
125
+
126
+ - **Object keys**: Always converted to keywords (`:` prefix added automatically)
127
+ - **String values starting with `:`**: Converted to keywords (e.g., `":memory"` → `:memory`)
128
+ - **String values starting with `\\:`**: Literal colon string (e.g., `"\\:literal"` → `":literal"`)
129
+ - **Other string values**: Remain as strings
130
+ - **Arrays**: Converted to CLJ vectors
131
+ - **Numbers, booleans, null**: Pass through unchanged
132
+ - **UUID strings**: Auto-detected and converted to UUID objects (convenience feature)
133
+
134
+ ### ClojureScript → JavaScript
135
+
136
+ - **Keywords**: Converted to strings with `:` prefix
137
+ - **CLJ maps**: Converted to JS objects (keyword keys become strings)
138
+ - **Vectors/Lists**: Converted to Arrays
139
+ - **Sets**: Converted to Arrays
140
+ - **Special**: DB values, datoms, and connections pass through unchanged
141
+
142
+ For complete conversion rules and edge cases, see [EDN Conversion Documentation](bindings/edn-conversion.md).
143
+
144
+ ## Important Notes
145
+
146
+ ### Keyword Syntax
147
+
148
+ The universal EDN conversion rules make keyword syntax simple and predictable:
149
+
150
+ **Simple rule: Keys never need `:`, values that should be keywords need `:`**
151
+
152
+ ```javascript
153
+ // ✅ Schema definition
154
+ const schema = [{
155
+ 'db/ident': ':name', // Key auto-keywordized, value is keyword
156
+ 'db/valueType': ':db.type/string', // Both become keywords
157
+ 'db/cardinality': ':db.cardinality/one'
158
+ }];
159
+
160
+ // ✅ Data insertion
161
+ const data = [
162
+ { name: 'Alice', age: 30 } // Keys auto-keywordized, values are literals
163
+ ];
164
+
165
+ // ✅ Configuration
166
+ const config = {
167
+ store: {
168
+ backend: ':memory', // ":memory" becomes :memory keyword
169
+ id: 'test' // "test" stays as string
170
+ },
171
+ 'schema-flexibility': ':read', // ":read" becomes :read keyword
172
+ 'keep-history?': true // boolean passes through
173
+ };
174
+
175
+ // ✅ Pull patterns (array of keyword strings)
176
+ const pattern = [':name', ':age']; // Strings with : become keywords
177
+
178
+ // ✅ Literal colon strings (rare)
179
+ const data = [{
180
+ description: '\\:starts-with-colon' // Escaped → ":starts-with-colon" (string)
181
+ }];
182
+ ```
183
+
184
+ ### Backend Configuration
185
+
186
+ ```javascript
187
+ const crypto = require('crypto');
188
+
189
+ // In-memory backend (requires UUID)
190
+ const memConfig = {
191
+ store: {
192
+ backend: ':memory',
193
+ id: crypto.randomUUID()
194
+ }
195
+ };
196
+
197
+ // File backend (Node.js only)
198
+ const fileConfig = {
199
+ store: {
200
+ backend: ':file',
201
+ path: '/path/to/db'
202
+ }
203
+ };
204
+ ```
205
+
206
+ ### Async Operations
207
+
208
+ All database operations return Promises. Use `await` or `.then()`:
209
+
210
+ ```javascript
211
+ // Using await (recommended)
212
+ const conn = await d.connect(config);
213
+ const result = await d.transact(conn, data);
214
+ console.log(result['tx-data']); // Note: 'tx-data' not 'tx_data'
215
+ console.log(result['db-before']);
216
+ console.log(result['db-after']);
217
+
218
+ // Using promises
219
+ d.connect(config).then(conn => {
220
+ return d.transact(conn, data);
221
+ }).then(result => {
222
+ console.log(result['tx-data']);
223
+ });
224
+ ```
225
+
226
+ ## API Functions
227
+
228
+ All functions use camelCase naming. The JavaScript API automatically:
229
+ - Converts `kebab-case` → `camelCase`
230
+ - Removes `!` and `?` suffixes
231
+ - Renames `with` → `withDb` (reserved keyword)
232
+
233
+ **Main API Functions:**
234
+ - **Database Lifecycle**: `createDatabase`, `deleteDatabase`, `databaseExists`
235
+ - **Connection**: `connect`, `release`
236
+ - **Database Values**: `db`, `asOf`, `since`, `history`, `withDb`, `dbWith`
237
+ - **Transactions**: `transact` (async, returns Promise), `loadEntities`
238
+ - **Queries**: `q`, `pull`, `pullMany`, `datoms`, `seekDatoms`, `entity`, `entityDb`
239
+ - **Schema**: `schema`, `reverseSchema`
240
+ - **Utilities**: `tempid`, `isFiltered`, `filter`, `indexRange`
241
+ - **Maintenance**: `gcStorage`
242
+ - **Info**: `datahikeVersion`
243
+
244
+ Note: `transact!` from Clojure becomes `transact` in JavaScript (the `!` is removed).
245
+
246
+ ## TypeScript Support
247
+
248
+ Full TypeScript definitions are automatically generated and included:
249
+
250
+ ```typescript
251
+ import * as d from 'datahike';
252
+
253
+ interface Config {
254
+ store: {
255
+ backend: string;
256
+ id?: string;
257
+ path?: string;
258
+ };
259
+ 'keep-history'?: boolean;
260
+ 'schema-flexibility'?: string;
261
+ }
262
+
263
+ const config: Config = {
264
+ store: { backend: ':memory', id: 'example' }
265
+ };
266
+
267
+ async function example() {
268
+ await d.createDatabase(config);
269
+ const conn = await d.connect(config);
270
+ const db = d.db(conn);
271
+ // TypeScript will check types automatically
272
+ }
273
+ ```
274
+
275
+ ## Testing
276
+
277
+ The comprehensive test suite in `npm-package/test.js` covers all functionality:
278
+ - Basic database operations
279
+ - Schema and transactions
280
+ - Datoms API
281
+ - Pull API
282
+ - Entity API
283
+ - Temporal databases (history, as-of, since)
284
+ - File backend persistence
285
+ - Query API
286
+
287
+ Run tests with:
288
+ ```bash
289
+ bb npm-test
290
+ ```
291
+
292
+ Tests are automatically run in CI/CD as part of `bb check`.
293
+
294
+ ## Naming Conventions
295
+
296
+ Naming is centralized in `src/datahike/js/naming.cljc` for consistency:
297
+
298
+ ```clojure
299
+ ;; Functions to skip (incompatible with JS or aliases)
300
+ (def js-skip-list #{'transact}) ; sync version, use transact! instead
301
+
302
+ ;; Conversion rules:
303
+ ;; database-exists? → databaseExists
304
+ ;; create-database → createDatabase
305
+ ;; transact! → transact (! removed)
306
+ ;; with → withDb (reserved keyword)
307
+ ```
308
+
309
+ ### Adding New Functions
310
+
311
+ 1. **Add to API specification**: Function must be in `datahike.api.specification`
312
+ 2. **Update skip list** (if needed): Add to `js-skip-list` in `naming.cljc` to exclude
313
+ 3. **Rebuild package**:
314
+ ```bash
315
+ bb npm-build
316
+ ```
317
+ This will:
318
+ - Generate TypeScript definitions (using naming.cljc)
319
+ - Compile API functions (using api_macros.clj)
320
+ - Run tests
321
+
322
+ ### Version Management
323
+
324
+ Versions are calculated automatically from `config.edn`:
325
+ - Format: `major.minor.commit-count`
326
+ - Example: `0.6.1637` (major: 0, minor: 6, commits: 1637)
327
+ - `package.json` is generated from `package.template.json` during build
328
+
329
+ ### Publishing to npm
330
+
331
+ See `npm-package/PUBLISHING.md` for detailed publishing instructions.
332
+
333
+ Quick workflow:
334
+ ```bash
335
+ # 1. Build and test
336
+ bb npm-build
337
+
338
+ # 2. Verify package
339
+ cd npm-package && npm pack --dry-run
340
+
341
+ # 3. Publish as next
342
+ npm publish --tag next
343
+ ```
344
+
345
+ ## Known Limitations
346
+
347
+ ### Query API
348
+
349
+ The Datalog query API requires EDN string format:
350
+
351
+ ```javascript
352
+ // ✅ Works: EDN string format
353
+ const results = await d.q(
354
+ '[:find ?name ?age :where [?e :name ?name] [?e :age ?age]]',
355
+ db
356
+ );
357
+
358
+ // ❌ Doesn't work: JavaScript object syntax
359
+ // const results = await d.q({ find: '?e', where: [...] }, db);
360
+
361
+ // ✅ Alternative: Use Datoms API for simple queries
362
+ const datoms = await d.datoms(db, ':eavt');
363
+ ```
364
+
365
+ ### Entity API
366
+
367
+ The `entity` function returns ClojureScript objects, not plain JavaScript objects. Use the Pull API for plain data:
368
+
369
+ ```javascript
370
+ // ✅ Recommended: Pull API returns plain objects
371
+ const data = await d.pull(db, [':name', ':age'], entityId);
372
+ console.log(data.name); // Works
373
+
374
+ // ⚠️ Entity API returns ClojureScript objects
375
+ const entity = await d.entity(db, entityId);
376
+ // Accessing attributes requires understanding ClojureScript objects
377
+ ```
378
+
379
+ ### Compilation Warnings
380
+
381
+ Shadow-cljs compilation may produce warnings from dependencies:
382
+ - **BigInt warnings** from `persistent-sorted-set` (harmless, ES2020 feature)
383
+ - **Infer warnings** (cosmetic, doesn't affect functionality)
384
+ - **Redef warning** for `filter` (expected, intentional override)
385
+
386
+ These can be safely ignored.
387
+
388
+ ## Development
389
+
390
+ ### Adding New Functions
391
+
392
+ Functions are automatically generated from `datahike.api.specification` by the `emit-js-api` macro. To add a function:
393
+
394
+ 1. Add it to `api-specification` in `src/datahike/api/specification.cljc`
395
+ 2. Add to `js-skip-list` in `api_macros.clj` if it should be excluded
396
+ 3. Rebuild with `npx shadow-cljs compile npm-release`
397
+
398
+ ### Data Conversion Rules
399
+
400
+ If you need to handle special types, update `clj->js-recursive` and `js->clj-recursive` in `src/datahike/js/api.cljs`.
401
+
402
+ ## Current Release
403
+
404
+ Published as `datahike@next` on npm. Install with:
405
+ ```bash
406
+ npm install datahike@next
407
+ ```
408
+
409
+ ## Future Improvements
410
+
411
+ - Add transaction builder helpers for common patterns
412
+ - Fluent/chainable API for queries
413
+ - Convenience wrappers for common query patterns
414
+ - Improved error messages for JavaScript users
415
+ - Helper module with EDN type constructors (similar to Python's `edn.keyword()`, `kw.DB_ID` constants)
416
+
417
+ ## See Also
418
+
419
+ - [Datahike Documentation](../README.md)
420
+ - [Configuration Guide](config.md)
421
+ - [Schema Documentation](schema.md)
@@ -0,0 +1,86 @@
1
+ # Libdatahike - C/C++ Native Library
2
+
3
+ **Status: Beta** - The native library is functional and tested, but the API may change as we refine the bindings.
4
+
5
+ Libdatahike provides a C/C++ interface to Datahike, allowing you to use Datahike databases from native applications. This library is built using GraalVM Native Image.
6
+
7
+ ## Building
8
+
9
+ To build the native library and test executable you need [GraalVM-JDK](https://www.graalvm.org/latest/getting-started/) installed with `native-compile`, [babashka](https://babashka.org/) and [Clojure](https://clojure.org/guides/install_clojure).
10
+
11
+ ```bash
12
+ # Compile the native library
13
+ bb ni-compile
14
+
15
+ # Compile the C++ test executable
16
+ ./libdatahike/compile-cpp
17
+ ```
18
+
19
+ This will create:
20
+ - `libdatahike/target/libdatahike.so` - The shared library
21
+ - `libdatahike/target/test_cpp` - Test executable
22
+
23
+ ## API Functions
24
+
25
+ The library provides the following C functions (defined in `libdatahike/target/libdatahike.h`):
26
+
27
+ ### Database Operations
28
+ - `create_database(thread, config, format, callback)` - Create a new database
29
+ - `database_exists(thread, config, format, callback)` - Check if database exists
30
+ - `delete_database(thread, config, format, callback)` - Delete a database
31
+
32
+ ### Data Operations
33
+ - `transact(thread, config, input_format, data, output_format, callback)` - Execute transactions
34
+ - `query(thread, query, num_inputs, input_formats, inputs, output_format, callback)` - Execute queries
35
+ - `pull(thread, config, format, pattern, entity_id, output_format, callback)` - Pull entity data
36
+ - `pull_many(thread, config, format, pattern, entity_ids, output_format, callback)` - Pull multiple entities
37
+ - `entity(thread, config, format, entity_id, output_format, callback)` - Get entity
38
+ - `datoms(thread, config, format, index, components, callback)` - Get datoms
39
+ - `schema(thread, config, format, output_format, callback)` - Get schema
40
+ - `reverse_schema(thread, config, format, output_format, callback)` - Get reverse schema
41
+
42
+ ### Utility Operations
43
+ - `metrics(thread, config, format, output_format, callback)` - Get database metrics
44
+ - `gc_storage(thread, config, older_than, output_format, callback)` - Garbage collect storage
45
+
46
+ ## Usage Example
47
+
48
+ ### C++ Example
49
+
50
+ Please take a look at the C++ example that is part of our test suite: [../libdatahike/src/test_cpp.cpp]
51
+
52
+ ## Data Formats
53
+
54
+ The library supports multiple data formats:
55
+ - `"edn"` - Extensible Data Notation (default)
56
+ - `"json"` - JSON format
57
+ - `"cbor"` - RFC 8949 Concise Binary Object Representation
58
+
59
+ ## Error Handling
60
+
61
+ Errors are returned through the callback functions as strings. Always check the callback results for error conditions.
62
+
63
+ ## Memory Management
64
+
65
+ - The GraalVM isolate should be created once and reused
66
+ - Callback functions receive string data that should be processed immediately
67
+ - The library handles memory management for internal operations
68
+
69
+ ## Thread Safety
70
+
71
+ Each thread requires its own `graal_isolatethread_t`. For multi-threaded applications, create separate thread contexts for each thread that will use the library.
72
+
73
+ ## Building Your Application
74
+
75
+ When building applications that use libdatahike:
76
+
77
+ ```bash
78
+ # Compile your C++ code
79
+ g++ -I./libdatahike/target -L./libdatahike/target -ldatahike -o your_app your_app.cpp
80
+
81
+ # Run with library path
82
+ LD_LIBRARY_PATH=./libdatahike/target ./your_app
83
+
84
+ # or on MacOS
85
+ DYLD_LIBRARY_PATH=./libdatahike/target ./your_app
86
+ ```
@@ -0,0 +1,43 @@
1
+ # Logging and Error Handling
2
+
3
+ **Note:** Datahike is transitioning from Timbre to trove/custom logging macros. As a library, Datahike should not force any logging implementation on users.
4
+
5
+ Historically, we chose Timbre for logging because it is the only library that comes with Clojure and ClojureScript
6
+ logging in one piece. Aside from that it offers easy appender implementation and is heavily used throughout
7
+ the Clojure community. You can use file logging and structured logging from built-in appenders.
8
+
9
+ However, as a library, Datahike should not force any logging implementation on users. We are transitioning to trove or custom logging macros that allow users to bring their own logging solution. Timbre can be configured via a simple Clojure map, or you can use your preferred Java logging implementation.
10
+
11
+ We needed a central place to raise an error and log at the same time in a consistent way. Therefore, we chose
12
+ to use a macro in the `tools` namespace named `raise` to solve that problem. In case you want to contribute to
13
+ Datahike please use this macro to throw errors. Please use logging appropriately in case you want to log in
14
+ another level.
15
+
16
+ ## Logging Configuration
17
+
18
+ Logging of an error consists of the message as the first part and optionally of a map of details. These details mostly consist of an `:error` key that describes where to search for your error and some information regarding the input that created the error like `:value`, `:binding` or `:symbol`.
19
+
20
+ ### Current Implementation (Transitional)
21
+
22
+ Currently, Datahike uses Timbre internally. Please see [Timbre on GitHub](https://github.com/ptaoussanis/timbre/) for details of the library. You can use it via any of your preferred logging implementations on the JVM as well as in JS.
23
+
24
+ There is a [bug in Clojure](https://clojure.atlassian.net/browse/CLJ-865) that prevents macros from passing line numbers to downstream macros. Thanks to Timbre we can use the low-level `log!` macro and pass it the line number. This is currently the only workaround to pass line numbers between macros.
25
+
26
+ An example to configure logging for an application using Datahike:
27
+
28
+ ```clojure
29
+ (ns datahike-example-app.core
30
+ (:require [taoensso.timbre :as log]
31
+ [taoensso.timbre.appenders.3rd-party.rotor :as rotor]))
32
+
33
+ (log/merge-config! {:level :debug
34
+ :appenders {:rotating (rotor/rotor-appender
35
+ {:path "/var/log/datahike-server.log"
36
+ :max-size (* 512 1024)
37
+ :backlog 10})}})
38
+ (log/infof "My first log in Datahike")
39
+ ```
40
+
41
+ ## Error Handling
42
+
43
+ Errors that are caught inside Datahike create an `ExceptionInfo` for Clojure or an `Error` for ClojureScript. It carries similar information to the logging of these errors. An error consists of the message as the first part and optionally a map of details. These details mostly consist of an `:error` key that describes where to search for your error and some information regarding the input that created the error like `:value`, `:binding` or `:symbol`.
package/doc/norms.md ADDED
@@ -0,0 +1,66 @@
1
+ # Datahike Norms - Database Migration System
2
+
3
+ The `datahike.norm.norm` namespace provides a database migration system for Datahike databases. Norms allow you to define schema changes and data migrations that are applied exactly once to your database.
4
+
5
+ ## Overview
6
+
7
+ Norms are EDN files that define database migrations. Each norm contains transaction data (`tx-data`) and/or transaction functions (`tx-fn`) that are applied to the database. The norms system tracks which migrations have been applied using a special `:tx/norm` attribute, ensuring each migration runs only once.
8
+
9
+ ## Core Functions
10
+
11
+ ### `ensure-norms!`
12
+
13
+ ```clojure
14
+ (ensure-norms! conn)
15
+ (ensure-norms! conn file-or-resource)
16
+ ```
17
+
18
+ Takes a Datahike connection and optionally a java.io.File or java.net.URL to specify the location of your norms. Defaults to the resource `migrations`. All EDN files in the folder and its subfolders are considered migration files and will be transacted in lexicographical order by filename.
19
+
20
+ ### `update-checksums!`
21
+
22
+ ```clojure
23
+ (update-checksums!)
24
+ (update-checksums! norms-folder)
25
+ ```
26
+
27
+ Computes checksums for all norm files and writes them to `checksums.edn`. This prevents inadvertent migrations when used with version control. Always run this after adding a new norm-file to your project.
28
+
29
+ ### `verify-checksums`
30
+
31
+ ```clojure
32
+ (verify-checksums file-or-resource)
33
+ ```
34
+
35
+ Verifies that norm files haven't changed by comparing the files' checksums against stored checksums. Always run this before your migrations to ensure integrity.
36
+
37
+ ## Norm File Format
38
+
39
+ Norm files are EDN files containing:
40
+ - `:tx-data` - Vector of transaction data to apply
41
+ - `:tx-fn` - Symbol referencing a transaction function that takes a connection and returns a vector of transactions
42
+
43
+ The filename (without extension) becomes the norm identifier keyword.
44
+
45
+ ## File Organization
46
+
47
+ Files are processed in lexicographical order by name. Use numeric prefixes for ordering:
48
+
49
+ ```
50
+ resources/migrations/
51
+ 001-initial-schema.edn
52
+ 002-add-users.edn
53
+ 003-data-migration.edn
54
+ checksums.edn
55
+ ```
56
+
57
+ ## Examples
58
+
59
+ See test files in `test/datahike/norm/resources/` for working examples:
60
+ - `simple-test/` - Basic schema migrations
61
+ - `tx-fn-test/` - Using transaction functions
62
+ - `naming-and-sorting-test/` - File ordering examples
63
+
64
+ ## Integration
65
+
66
+ The norms system automatically creates the `:tx/norm` attribute to track applied migrations. Each successfully applied norm is marked to prevent re-application.