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,161 @@
1
+ package datahike.java;
2
+
3
+ import clojure.lang.Keyword;
4
+
5
+ /**
6
+ * Pre-defined Datahike keyword constants.
7
+ *
8
+ * <p>Use these constants for common Datahike schema and transaction attributes
9
+ * to avoid typos and get IDE autocompletion.</p>
10
+ *
11
+ * <p>Example:</p>
12
+ * <pre>{@code
13
+ * import static datahike.java.Keywords.*;
14
+ * import static datahike.java.EDN.*;
15
+ *
16
+ * Map<String, Object> schema = Map.of(
17
+ * DB_IDENT, keyword("person", "name"),
18
+ * DB_VALUE_TYPE, STRING,
19
+ * DB_CARDINALITY, ONE,
20
+ * DB_DOC, "Person's full name"
21
+ * );
22
+ * }</pre>
23
+ */
24
+ public class Keywords {
25
+
26
+ /**
27
+ * Forbids instance creation.
28
+ */
29
+ private Keywords() {}
30
+
31
+ // =========================================================================
32
+ // Entity Attributes
33
+ // =========================================================================
34
+
35
+ /** Entity ID: :db/id */
36
+ public static final Keyword DB_ID = Keyword.intern("db", "id");
37
+
38
+ /** Entity identifier: :db/ident */
39
+ public static final Keyword DB_IDENT = Keyword.intern("db", "ident");
40
+
41
+ // =========================================================================
42
+ // Schema Attributes
43
+ // =========================================================================
44
+
45
+ /** Value type: :db/valueType */
46
+ public static final Keyword DB_VALUE_TYPE = Keyword.intern("db", "valueType");
47
+
48
+ /** Cardinality: :db/cardinality */
49
+ public static final Keyword DB_CARDINALITY = Keyword.intern("db", "cardinality");
50
+
51
+ /** Documentation: :db/doc */
52
+ public static final Keyword DB_DOC = Keyword.intern("db", "doc");
53
+
54
+ /** Uniqueness constraint: :db/unique */
55
+ public static final Keyword DB_UNIQUE = Keyword.intern("db", "unique");
56
+
57
+ /** Component attribute: :db/isComponent */
58
+ public static final Keyword DB_IS_COMPONENT = Keyword.intern("db", "isComponent");
59
+
60
+ /** Disable history: :db/noHistory */
61
+ public static final Keyword DB_NO_HISTORY = Keyword.intern("db", "noHistory");
62
+
63
+ /** Index attribute: :db/index */
64
+ public static final Keyword DB_INDEX = Keyword.intern("db", "index");
65
+
66
+ /** Fulltext index: :db/fulltext */
67
+ public static final Keyword DB_FULLTEXT = Keyword.intern("db", "fulltext");
68
+
69
+ // =========================================================================
70
+ // Value Types
71
+ // =========================================================================
72
+
73
+ /** String type: :db.type/string */
74
+ public static final Keyword STRING = Keyword.intern("db.type", "string");
75
+
76
+ /** Boolean type: :db.type/boolean */
77
+ public static final Keyword BOOLEAN = Keyword.intern("db.type", "boolean");
78
+
79
+ /** Long type: :db.type/long */
80
+ public static final Keyword LONG = Keyword.intern("db.type", "long");
81
+
82
+ /** Big integer type: :db.type/bigint */
83
+ public static final Keyword BIGINT = Keyword.intern("db.type", "bigint");
84
+
85
+ /** Float type: :db.type/float */
86
+ public static final Keyword FLOAT = Keyword.intern("db.type", "float");
87
+
88
+ /** Double type: :db.type/double */
89
+ public static final Keyword DOUBLE = Keyword.intern("db.type", "double");
90
+
91
+ /** Big decimal type: :db.type/bigdec */
92
+ public static final Keyword BIGDEC = Keyword.intern("db.type", "bigdec");
93
+
94
+ /** Instant type: :db.type/instant */
95
+ public static final Keyword INSTANT = Keyword.intern("db.type", "instant");
96
+
97
+ /** UUID type: :db.type/uuid */
98
+ public static final Keyword UUID_TYPE = Keyword.intern("db.type", "uuid");
99
+
100
+ /** Keyword type: :db.type/keyword */
101
+ public static final Keyword KEYWORD_TYPE = Keyword.intern("db.type", "keyword");
102
+
103
+ /** Symbol type: :db.type/symbol */
104
+ public static final Keyword SYMBOL_TYPE = Keyword.intern("db.type", "symbol");
105
+
106
+ /** Reference type: :db.type/ref */
107
+ public static final Keyword REF = Keyword.intern("db.type", "ref");
108
+
109
+ /** Bytes type: :db.type/bytes */
110
+ public static final Keyword BYTES = Keyword.intern("db.type", "bytes");
111
+
112
+ // =========================================================================
113
+ // Cardinality Values
114
+ // =========================================================================
115
+
116
+ /** Cardinality one: :db.cardinality/one */
117
+ public static final Keyword ONE = Keyword.intern("db.cardinality", "one");
118
+
119
+ /** Cardinality many: :db.cardinality/many */
120
+ public static final Keyword MANY = Keyword.intern("db.cardinality", "many");
121
+
122
+ // =========================================================================
123
+ // Uniqueness Values
124
+ // =========================================================================
125
+
126
+ /** Unique value constraint: :db.unique/value */
127
+ public static final Keyword UNIQUE_VALUE = Keyword.intern("db.unique", "value");
128
+
129
+ /** Unique identity constraint: :db.unique/identity */
130
+ public static final Keyword UNIQUE_IDENTITY = Keyword.intern("db.unique", "identity");
131
+
132
+ // =========================================================================
133
+ // Transaction Metadata
134
+ // =========================================================================
135
+
136
+ /** Transaction entity: :db/tx */
137
+ public static final Keyword TX = Keyword.intern("db", "tx");
138
+
139
+ /** Transaction timestamp: :db/txInstant */
140
+ public static final Keyword TX_INSTANT = Keyword.intern("db", "txInstant");
141
+
142
+ // =========================================================================
143
+ // Schema Flexibility Values
144
+ // =========================================================================
145
+
146
+ /** Schema flexibility read mode: :read */
147
+ public static final Keyword SCHEMA_READ = Keyword.intern("read");
148
+
149
+ /** Schema flexibility write mode: :write */
150
+ public static final Keyword SCHEMA_WRITE = Keyword.intern("write");
151
+
152
+ // =========================================================================
153
+ // Storage Backends
154
+ // =========================================================================
155
+
156
+ /** Memory backend: :memory */
157
+ public static final Keyword BACKEND_MEMORY = Keyword.intern("memory");
158
+
159
+ /** File backend: :file */
160
+ public static final Keyword BACKEND_FILE = Keyword.intern("file");
161
+ }
@@ -0,0 +1,52 @@
1
+ package datahike.java;
2
+
3
+ import clojure.lang.Keyword;
4
+
5
+ /**
6
+ * Schema flexibility modes for Datahike databases.
7
+ *
8
+ * <p>Controls how the database handles attributes not defined in the schema:</p>
9
+ * <ul>
10
+ * <li>{@link #READ} - Strict mode: Only allow reads of undefined attributes, reject writes</li>
11
+ * <li>{@link #WRITE} - Flexible mode: Allow both reads and writes of undefined attributes</li>
12
+ * </ul>
13
+ *
14
+ * @see <a href="https://github.com/replikativ/datahike/blob/main/doc/schema.md">Schema Documentation</a>
15
+ */
16
+ public enum SchemaFlexibility {
17
+ /**
18
+ * Read-only flexibility: Allow reading undefined attributes but reject writes.
19
+ * This is the recommended mode for production use with schemaless data.
20
+ */
21
+ READ(Keywords.SCHEMA_READ),
22
+
23
+ /**
24
+ * Write flexibility: Allow both reading and writing undefined attributes.
25
+ * Use this for fully schemaless databases or during prototyping.
26
+ */
27
+ WRITE(Keywords.SCHEMA_WRITE);
28
+
29
+ private final Keyword keyword;
30
+
31
+ SchemaFlexibility(Keyword keyword) {
32
+ this.keyword = keyword;
33
+ }
34
+
35
+ /**
36
+ * Returns the Clojure keyword representation.
37
+ *
38
+ * @return the keyword for this schema flexibility mode
39
+ */
40
+ public Keyword toKeyword() {
41
+ return keyword;
42
+ }
43
+
44
+ /**
45
+ * Returns the string representation suitable for EDN/config maps.
46
+ *
47
+ * @return the string representation (e.g., ":read", ":write")
48
+ */
49
+ public String toEDNString() {
50
+ return keyword.toString();
51
+ }
52
+ }
@@ -0,0 +1,219 @@
1
+ package datahike.java;
2
+
3
+ import clojure.java.api.Clojure;
4
+ import clojure.lang.IFn;
5
+ import clojure.lang.APersistentMap;
6
+ import clojure.lang.APersistentVector;
7
+ import clojure.lang.Keyword;
8
+ import clojure.lang.RT;
9
+
10
+ public class Util {
11
+ public static final IFn derefFn = Clojure.var("clojure.core", "deref");
12
+ private static final IFn hashMapFn = Clojure.var("clojure.core", "hash-map");
13
+ private static final IFn vectorFn = Clojure.var("clojure.core", "vec");
14
+ private static final IFn readStringFn = Clojure.var("clojure.edn", "read-string");
15
+
16
+ /** Converts a keyword given as a string into a clojure keyword */
17
+ public static Keyword kwd(String str) {
18
+ return (Keyword)Clojure.read(str);
19
+ }
20
+
21
+ /** Creates a new clojure HashMap from the arguments of the form: key1, val1, key2, val2, ... */
22
+ public static APersistentMap map(Object... keyVals) {
23
+ Object[] converted = new Object[keyVals.length];
24
+ for (int i = 0; i < keyVals.length; i += 2) {
25
+ // Convert keys (always keywordize)
26
+ Object key = keyVals[i];
27
+ if (key instanceof String) {
28
+ String strKey = (String) key;
29
+ converted[i] = strKey.startsWith(":") ? kwd(strKey) : Keyword.intern(strKey);
30
+ } else {
31
+ converted[i] = key;
32
+ }
33
+
34
+ // Convert values (apply EDN rules)
35
+ if (i + 1 < keyVals.length) {
36
+ converted[i + 1] = convertValue(keyVals[i + 1]);
37
+ }
38
+ }
39
+ return (APersistentMap) hashMapFn.applyTo(RT.seq(converted));
40
+ }
41
+
42
+ /** Creates a new clojure vector with EDN conversion applied to items */
43
+ public static APersistentVector vec(Object... items) {
44
+ // Convert each item using EDN rules
45
+ Object[] converted = new Object[items.length];
46
+ for (int i = 0; i < items.length; i++) {
47
+ converted[i] = convertValue(items[i]);
48
+ }
49
+ return vecRaw(converted);
50
+ }
51
+
52
+ /** Creates a new clojure vector without conversion (internal use) */
53
+ private static APersistentVector vecRaw(Object... items) {
54
+ // No need to use 'applyTo here, as 'vectorFn taking a collection as an argument will produce a clj vector
55
+ // containing *each* of the collection elements.
56
+ return (APersistentVector) vectorFn.invoke(items);
57
+ }
58
+
59
+ /**
60
+ * Converts a value following universal EDN conversion rules:
61
+ * - String starting with ":" → keyword
62
+ * - String starting with "\\:" → literal string with ":" (escaped)
63
+ * - String without ":" → string
64
+ * - Numbers, booleans, null → as-is
65
+ * - Maps → recursively convert
66
+ * - Lists/Arrays → recursively convert
67
+ *
68
+ * This is public to allow reuse from Clojure interop layer.
69
+ */
70
+ public static Object convertValue(Object value) {
71
+ if (value == null) {
72
+ return null;
73
+ }
74
+
75
+ // Handle strings with EDN conversion rules
76
+ if (value instanceof String) {
77
+ String str = (String) value;
78
+
79
+ // Escaped colon - strip backslash and return as string
80
+ if (str.startsWith("\\:")) {
81
+ return str.substring(1); // Return ":literal" from "\\:literal"
82
+ }
83
+
84
+ // Colon prefix - convert to keyword
85
+ if (str.startsWith(":")) {
86
+ return kwd(str);
87
+ }
88
+
89
+ // Regular string - return as-is
90
+ return str;
91
+ }
92
+
93
+ // Recursively convert nested maps
94
+ if (value instanceof java.util.Map && !(value instanceof APersistentMap)) {
95
+ return mapToPersistentMap((java.util.Map<String, Object>) value);
96
+ }
97
+
98
+ // Recursively convert lists/arrays
99
+ if (value instanceof java.util.List) {
100
+ java.util.List<?> list = (java.util.List<?>) value;
101
+ Object[] converted = new Object[list.size()];
102
+ for (int i = 0; i < list.size(); i++) {
103
+ converted[i] = convertValue(list.get(i));
104
+ }
105
+ return vecRaw(converted);
106
+ }
107
+
108
+ if (value instanceof Object[]) {
109
+ Object[] arr = (Object[]) value;
110
+ Object[] converted = new Object[arr.length];
111
+ for (int i = 0; i < arr.length; i++) {
112
+ converted[i] = convertValue(arr[i]);
113
+ }
114
+ return vecRaw(converted);
115
+ }
116
+
117
+ // Numbers, booleans, and other types - return as-is
118
+ return value;
119
+ }
120
+
121
+ /** Converts a Java Map to a Clojure persistent map */
122
+ public static APersistentMap mapToPersistentMap(java.util.Map<String, Object> javaMap) {
123
+ if (javaMap == null) {
124
+ return null;
125
+ }
126
+ Object[] keyVals = new Object[javaMap.size() * 2];
127
+ int i = 0;
128
+ for (java.util.Map.Entry<String, Object> entry : javaMap.entrySet()) {
129
+ Object key = entry.getKey();
130
+ // If key is already a Keyword, use it as-is
131
+ if (key instanceof Keyword) {
132
+ keyVals[i++] = key;
133
+ } else if (key instanceof String) {
134
+ String strKey = (String) key;
135
+ // Convert string keys to keywords (auto-prefix with : if not present)
136
+ keyVals[i++] = strKey.startsWith(":") ? kwd(strKey) : Keyword.intern(strKey);
137
+ } else {
138
+ // Use key as-is for other types
139
+ keyVals[i++] = key;
140
+ }
141
+
142
+ // Convert values using universal EDN rules
143
+ keyVals[i++] = convertValue(entry.getValue());
144
+ }
145
+ return (APersistentMap) hashMapFn.applyTo(RT.seq(keyVals));
146
+ }
147
+
148
+ /**
149
+ * Convert Clojure persistent map to Java HashMap.
150
+ * Used for return values that need to be Java-friendly.
151
+ *
152
+ * @param clojureMap Clojure persistent map
153
+ * @return Java HashMap with string keys
154
+ */
155
+ public static java.util.Map<String, Object> clojureMapToJavaMap(APersistentMap clojureMap) {
156
+ if (clojureMap == null) {
157
+ return null;
158
+ }
159
+ java.util.Map<String, Object> javaMap = new java.util.HashMap<>();
160
+ for (Object entry : clojureMap) {
161
+ java.util.Map.Entry<?, ?> e = (java.util.Map.Entry<?, ?>) entry;
162
+ String key = e.getKey().toString();
163
+ javaMap.put(key, e.getValue());
164
+ }
165
+ return javaMap;
166
+ }
167
+
168
+ /**
169
+ * Normalize Java collections to Clojure collections for API processing.
170
+ *
171
+ * <p><b>Escape hatch (automatic):</b> If data is already a Clojure persistent
172
+ * collection, returns immediately with O(1) instanceof check. Advanced users
173
+ * can use {@link #vec} and {@link #map} for zero-overhead calls.</p>
174
+ *
175
+ * <p><b>Conversion rules (applied recursively):</b></p>
176
+ * <ul>
177
+ * <li>java.util.List → clojure.lang.PersistentVector</li>
178
+ * <li>java.util.Map → clojure.lang.PersistentHashMap</li>
179
+ * <li>Map keys (String) → keywords ("name" → :name, ":name" → :name)</li>
180
+ * <li>Values (String) → keywords only if prefixed with ":"</li>
181
+ * <li>Primitives, Clojure types → unchanged</li>
182
+ * </ul>
183
+ *
184
+ * <p>This function is general and consistent - applied uniformly to all
185
+ * Java API method parameters that accept collections.</p>
186
+ *
187
+ * @param data The data to normalize (List, Map, or other types)
188
+ * @return Clojure-compatible data structure
189
+ */
190
+ public static Object normalizeCollections(Object data) {
191
+ // Escape hatch: already Clojure persistent collection - O(1) check
192
+ if (data instanceof clojure.lang.IPersistentCollection) {
193
+ return data;
194
+ }
195
+
196
+ // Java List → Clojure vector with recursive conversion
197
+ if (data instanceof java.util.List) {
198
+ java.util.List<?> list = (java.util.List<?>) data;
199
+ Object[] converted = new Object[list.size()];
200
+ for (int i = 0; i < list.size(); i++) {
201
+ converted[i] = convertValue(list.get(i));
202
+ }
203
+ return vecRaw(converted);
204
+ }
205
+
206
+ // Java Map → Clojure map with recursive conversion
207
+ if (data instanceof java.util.Map && !(data instanceof APersistentMap)) {
208
+ return mapToPersistentMap((java.util.Map<String, Object>) data);
209
+ }
210
+
211
+ // Other types → apply EDN value conversion rules
212
+ return convertValue(data);
213
+ }
214
+
215
+ /** Read string into edn data structure. */
216
+ public static Object ednFromString(String str) {
217
+ return readStringFn.invoke(str);
218
+ }
219
+ }
package/karma.conf.js ADDED
@@ -0,0 +1,19 @@
1
+ module.exports = function (config) {
2
+ config.set({
3
+ browsers: ['ChromeHeadless'],
4
+ basePath: 'target',
5
+ files: ['browser-ci.js'],
6
+ frameworks: ['cljs-test'],
7
+ plugins: ['karma-cljs-test', 'karma-chrome-launcher'],
8
+ colors: true,
9
+ logLevel: config.LOG_INFO,
10
+ client: {
11
+ args: ["shadow.test.karma.init"]
12
+ },
13
+ singleRun: true,
14
+ // Integration tests need longer timeouts due to database ops and network calls
15
+ browserDisconnectTimeout: 180000, // 3 minutes
16
+ browserNoActivityTimeout: 180000, // 3 minutes
17
+ captureTimeout: 300000 // 5 minutes
18
+ })
19
+ };
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -eo pipefail
4
+
5
+ g++ libdatahike/src/test_cpp.cpp -L libdatahike/target -I libdatahike/target -ldatahike -o libdatahike/target/test_cpp
6
+
7
+ echo "Created libdatahike/target/test_cpp"
@@ -0,0 +1,203 @@
1
+ package datahike.impl;
2
+
3
+ import org.graalvm.nativeimage.c.function.CFunctionPointer;
4
+ import org.graalvm.nativeimage.c.function.InvokeCFunctionPointer;
5
+ import org.graalvm.nativeimage.c.type.CCharPointer;
6
+ import org.graalvm.nativeimage.c.type.CCharPointerPointer;
7
+ import org.graalvm.nativeimage.c.type.CConst;
8
+ import org.graalvm.nativeimage.c.type.CTypeConversion;
9
+ import datahike.java.Datahike;
10
+ import datahike.java.Util;
11
+ import datahike.impl.libdatahike;
12
+ import clojure.lang.APersistentMap;
13
+ import clojure.lang.Keyword;
14
+ import java.io.StringWriter;
15
+ import java.io.PrintWriter;
16
+ import java.util.Date;
17
+ import java.util.Base64;
18
+
19
+ /**
20
+ * Base infrastructure for native C bindings.
21
+ *
22
+ * This class provides the core utilities for:
23
+ * - Exception handling and formatting
24
+ * - Input format parsing (db, history, since, asof, json, edn, cbor)
25
+ * - Output format serialization (json, edn, cbor)
26
+ * - C type conversions
27
+ *
28
+ * The actual C entry points are generated in LibDatahike.java.
29
+ */
30
+ public class LibDatahikeBase {
31
+
32
+ // =========================================================================
33
+ // Callback Interface
34
+ // =========================================================================
35
+
36
+ /**
37
+ * C function pointer interface for reading return values.
38
+ * All native entry points use this callback pattern to return results.
39
+ */
40
+ public interface OutputReader extends CFunctionPointer {
41
+ @InvokeCFunctionPointer
42
+ void call(@CConst CCharPointer output);
43
+ }
44
+
45
+ // =========================================================================
46
+ // Exception Handling
47
+ // =========================================================================
48
+
49
+ /**
50
+ * Format an exception as a C string for callback.
51
+ * Format: "exception:{message}\nStacktrace:\n{stacktrace}"
52
+ */
53
+ protected static @CConst CCharPointer toException(Exception e) {
54
+ StringWriter sw = new StringWriter();
55
+ e.printStackTrace(new PrintWriter(sw));
56
+ String st = sw.toString();
57
+ return toCCharPointer("exception:".concat(e.toString()).concat("\nStacktrace:\n").concat(st));
58
+ }
59
+
60
+ // =========================================================================
61
+ // C Type Conversions
62
+ // =========================================================================
63
+
64
+ /**
65
+ * Parse EDN configuration string to Clojure map.
66
+ */
67
+ public static APersistentMap readConfig(CCharPointer db_config) {
68
+ return (APersistentMap) Util.ednFromString(CTypeConversion.toJavaString(db_config));
69
+ }
70
+
71
+ /**
72
+ * Convert Java String to C char pointer.
73
+ */
74
+ public static @CConst CCharPointer toCCharPointer(String result) {
75
+ CTypeConversion.CCharPointerHolder holder = CTypeConversion.toCString(result);
76
+ CCharPointer value = holder.get();
77
+ return value;
78
+ }
79
+
80
+ /**
81
+ * Convert byte array to Base64-encoded C char pointer.
82
+ * Used for CBOR output format.
83
+ */
84
+ public static @CConst CCharPointer toCCharPointer(byte[] result) {
85
+ CTypeConversion.CCharPointerHolder holder = CTypeConversion.toCBytes(Base64.getEncoder().encode(result));
86
+ CCharPointer value = holder.get();
87
+ return value;
88
+ }
89
+
90
+ // =========================================================================
91
+ // Input Format Handling
92
+ // =========================================================================
93
+
94
+ /**
95
+ * Load input based on format specification.
96
+ *
97
+ * Supported formats:
98
+ * - "db" : Connect and deref to get current database
99
+ * - "history" : Get full history database
100
+ * - "since:{timestamp_ms}" : Get database since timestamp
101
+ * - "asof:{timestamp_ms}" : Get database as-of timestamp
102
+ * - "json" : Parse as JSON
103
+ * - "edn" : Parse as EDN
104
+ * - "cbor" : Parse as CBOR (base64 encoded)
105
+ */
106
+ protected static Object loadInput(@CConst CCharPointer input_format,
107
+ @CConst CCharPointer raw_input) {
108
+ String format = CTypeConversion.toJavaString(input_format);
109
+ String formats[] = format.split(":");
110
+ switch (formats[0]) {
111
+ case "db":
112
+ return Datahike.deref(Datahike.connect(readConfig(raw_input)));
113
+ case "history":
114
+ return Datahike.history(Datahike.deref(Datahike.connect(readConfig(raw_input))));
115
+ case "since":
116
+ return Datahike.since(Datahike.deref(Datahike.connect(readConfig(raw_input))),
117
+ new Date(Long.parseLong(formats[1])));
118
+ case "asof":
119
+ return Datahike.asOf(Datahike.deref(Datahike.connect(readConfig(raw_input))),
120
+ new Date(Long.parseLong(formats[1])));
121
+ case "json":
122
+ return libdatahike.parseJSON(CTypeConversion.toJavaString(raw_input));
123
+ case "edn":
124
+ return libdatahike.parseEdn(CTypeConversion.toJavaString(raw_input));
125
+ case "cbor":
126
+ return libdatahike.parseCBOR(CTypeConversion.toJavaString(raw_input).getBytes());
127
+ default:
128
+ throw new IllegalArgumentException("Input format not supported: " + format);
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Load multiple inputs for query operations.
134
+ */
135
+ protected static Object[] loadInputs(@CConst long num_inputs,
136
+ @CConst CCharPointerPointer input_formats,
137
+ @CConst CCharPointerPointer raw_inputs) {
138
+ Object[] inputs = new Object[(int) num_inputs];
139
+ for (int i = 0; i < num_inputs; i++) {
140
+ inputs[i] = loadInput(input_formats.read(i), raw_inputs.read(i));
141
+ }
142
+ return inputs;
143
+ }
144
+
145
+ // =========================================================================
146
+ // Output Format Handling
147
+ // =========================================================================
148
+
149
+ /**
150
+ * Serialize output based on format specification.
151
+ *
152
+ * Supported formats:
153
+ * - "json" : Serialize as JSON string
154
+ * - "edn" : Serialize as EDN string
155
+ * - "cbor" : Serialize as CBOR (base64 encoded)
156
+ */
157
+ protected static @CConst CCharPointer toOutput(@CConst CCharPointer output_format,
158
+ Object output) {
159
+ String format = CTypeConversion.toJavaString(output_format);
160
+ switch (format) {
161
+ case "json":
162
+ return toCCharPointer(libdatahike.toJSONString(output));
163
+ case "edn":
164
+ return toCCharPointer(libdatahike.toEdnString(output));
165
+ case "cbor":
166
+ return toCCharPointer(libdatahike.toCBOR(output));
167
+ default:
168
+ throw new IllegalArgumentException("Output format not supported: " + format);
169
+ }
170
+ }
171
+
172
+ // =========================================================================
173
+ // Helper Methods for Generated Code
174
+ // =========================================================================
175
+
176
+ /**
177
+ * Parse keyword from EDN string (e.g., ":eavt" -> Keyword).
178
+ */
179
+ protected static Keyword parseKeyword(CCharPointer kwd_edn) {
180
+ return Util.kwd(CTypeConversion.toJavaString(kwd_edn));
181
+ }
182
+
183
+ /**
184
+ * Parse EDN to Iterable (for eids, etc).
185
+ */
186
+ protected static Iterable<?> parseIterable(CCharPointer edn) {
187
+ return (Iterable<?>) libdatahike.parseEdn(CTypeConversion.toJavaString(edn));
188
+ }
189
+
190
+ /**
191
+ * Convert datoms to vectors for serialization.
192
+ */
193
+ protected static Iterable<?> datomsToVecs(Iterable<?> datoms) {
194
+ return libdatahike.datomsToVecs(datoms);
195
+ }
196
+
197
+ /**
198
+ * Convert entity to map for serialization.
199
+ */
200
+ protected static Object entityToMap(Object entity) {
201
+ return libdatahike.intoMap(entity);
202
+ }
203
+ }