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.
- package/.circleci/config.yml +405 -0
- package/.circleci/scripts/gen_ci.clj +194 -0
- package/.cirrus.yml +60 -0
- package/.clj-kondo/babashka/sci/config.edn +1 -0
- package/.clj-kondo/babashka/sci/sci/core.clj +9 -0
- package/.clj-kondo/config.edn +95 -0
- package/.dir-locals.el +2 -0
- package/.github/FUNDING.yml +3 -0
- package/.github/ISSUE_TEMPLATE/1-bug-report.yml +68 -0
- package/.github/ISSUE_TEMPLATE/2-feature-request.yml +28 -0
- package/.github/ISSUE_TEMPLATE/config.yml +6 -0
- package/.github/pull_request_template.md +24 -0
- package/.github/workflows/native-image.yml +84 -0
- package/LICENSE +203 -0
- package/README.md +273 -0
- package/bb/deps.edn +9 -0
- package/bb/resources/github-fingerprints +3 -0
- package/bb/resources/native-image-tests/run-bb-pod-tests.clj +162 -0
- package/bb/resources/native-image-tests/run-libdatahike-tests +12 -0
- package/bb/resources/native-image-tests/run-native-image-tests +74 -0
- package/bb/resources/native-image-tests/run-python-tests +22 -0
- package/bb/resources/native-image-tests/testconfig.attr-refs.edn +6 -0
- package/bb/resources/native-image-tests/testconfig.edn +5 -0
- package/bb/resources/template/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
- package/bb/resources/template/.settings/org.eclipse.jdt.core.prefs +9 -0
- package/bb/resources/template/.settings/org.eclipse.m2e.core.prefs +4 -0
- package/bb/resources/template/pom.xml +22 -0
- package/bb/src/tools/build.clj +132 -0
- package/bb/src/tools/clj_kondo.clj +32 -0
- package/bb/src/tools/deploy.clj +26 -0
- package/bb/src/tools/examples.clj +19 -0
- package/bb/src/tools/npm.clj +100 -0
- package/bb/src/tools/python.clj +14 -0
- package/bb/src/tools/release.clj +94 -0
- package/bb/src/tools/test.clj +148 -0
- package/bb/src/tools/version.clj +47 -0
- package/bb.edn +269 -0
- package/benchmark/src/benchmark/cli.clj +195 -0
- package/benchmark/src/benchmark/compare.clj +157 -0
- package/benchmark/src/benchmark/config.clj +316 -0
- package/benchmark/src/benchmark/measure.clj +187 -0
- package/benchmark/src/benchmark/store.clj +190 -0
- package/benchmark/test/benchmark/measure_test.clj +156 -0
- package/build.clj +30 -0
- package/config.edn +49 -0
- package/deps.edn +138 -0
- package/dev/sandbox.clj +82 -0
- package/dev/sandbox.cljs +127 -0
- package/dev/sandbox_benchmarks.clj +27 -0
- package/dev/sandbox_client.clj +87 -0
- package/dev/sandbox_transact_bench.clj +109 -0
- package/dev/user.clj +79 -0
- package/doc/README.md +96 -0
- package/doc/adl/README.md +6 -0
- package/doc/adl/adr-000-adr.org +28 -0
- package/doc/adl/adr-001-attribute-references.org +15 -0
- package/doc/adl/adr-002-build-tooling.org +54 -0
- package/doc/adl/adr-003-db-meta-data.md +52 -0
- package/doc/adl/adr-004-github-flow.md +40 -0
- package/doc/adl/adr-XYZ-template.md +30 -0
- package/doc/adl/index.org +3 -0
- package/doc/assets/datahike-logo.svg +3 -0
- package/doc/assets/datahiking-invoice.org +85 -0
- package/doc/assets/hhtree2.png +0 -0
- package/doc/assets/network_topology.svg +624 -0
- package/doc/assets/perf.png +0 -0
- package/doc/assets/schema_mindmap.mm +132 -0
- package/doc/assets/schema_mindmap.svg +970 -0
- package/doc/assets/temporal_index.mm +74 -0
- package/doc/backend-development.md +78 -0
- package/doc/bb-pod.md +89 -0
- package/doc/benchmarking.md +360 -0
- package/doc/bindings/edn-conversion.md +383 -0
- package/doc/cli.md +162 -0
- package/doc/cljdoc.edn +27 -0
- package/doc/cljs-support.md +133 -0
- package/doc/config.md +406 -0
- package/doc/contributing.md +114 -0
- package/doc/datalog-vs-sql.md +210 -0
- package/doc/datomic_differences.md +109 -0
- package/doc/development/pull-api-ns.md +186 -0
- package/doc/development/pull-frame-state-diagram.jpg +0 -0
- package/doc/distributed.md +566 -0
- package/doc/entity_spec.md +92 -0
- package/doc/gc.md +273 -0
- package/doc/java-api.md +808 -0
- package/doc/javascript-api.md +421 -0
- package/doc/libdatahike.md +86 -0
- package/doc/logging_and_error_handling.md +43 -0
- package/doc/norms.md +66 -0
- package/doc/schema-migration.md +85 -0
- package/doc/schema.md +287 -0
- package/doc/storage-backends.md +363 -0
- package/doc/store-id-refactoring.md +596 -0
- package/doc/time_variance.md +325 -0
- package/doc/unstructured.md +167 -0
- package/doc/versioning.md +261 -0
- package/examples/basic/README.md +19 -0
- package/examples/basic/deps.edn +6 -0
- package/examples/basic/docker-compose.yml +13 -0
- package/examples/basic/src/examples/core.clj +60 -0
- package/examples/basic/src/examples/schema.clj +155 -0
- package/examples/basic/src/examples/store.clj +60 -0
- package/examples/basic/src/examples/time_travel.clj +185 -0
- package/examples/java/.settings/org.eclipse.core.resources.prefs +3 -0
- package/examples/java/.settings/org.eclipse.jdt.apt.core.prefs +2 -0
- package/examples/java/.settings/org.eclipse.jdt.core.prefs +9 -0
- package/examples/java/.settings/org.eclipse.m2e.core.prefs +4 -0
- package/examples/java/README.md +162 -0
- package/examples/java/pom.xml +62 -0
- package/examples/java/src/main/java/examples/QuickStart.java +115 -0
- package/examples/java/src/main/java/examples/SchemaExample.java +148 -0
- package/examples/java/src/main/java/examples/TimeTravelExample.java +121 -0
- package/flake.lock +27 -0
- package/flake.nix +27 -0
- package/http-server/datahike/http/middleware.clj +75 -0
- package/http-server/datahike/http/server.clj +269 -0
- package/java/src/datahike/java/Database.java +274 -0
- package/java/src/datahike/java/Datahike.java +281 -0
- package/java/src/datahike/java/DatahikeGeneratedTest.java +349 -0
- package/java/src/datahike/java/DatahikeTest.java +370 -0
- package/java/src/datahike/java/EDN.java +170 -0
- package/java/src/datahike/java/IEntity.java +11 -0
- package/java/src/datahike/java/Keywords.java +161 -0
- package/java/src/datahike/java/SchemaFlexibility.java +52 -0
- package/java/src/datahike/java/Util.java +219 -0
- package/karma.conf.js +19 -0
- package/libdatahike/compile-cpp +7 -0
- package/libdatahike/src/datahike/impl/LibDatahikeBase.java +203 -0
- package/libdatahike/src/datahike/impl/libdatahike.clj +59 -0
- package/libdatahike/src/test_cpp.cpp +61 -0
- package/npm-package/PUBLISHING.md +140 -0
- package/npm-package/README.md +226 -0
- package/npm-package/package.template.json +34 -0
- package/npm-package/test-isomorphic.ts +281 -0
- package/npm-package/test.js +557 -0
- package/npm-package/typescript-test.ts +70 -0
- package/package.json +16 -0
- package/pydatahike/README.md +569 -0
- package/pydatahike/pyproject.toml +91 -0
- package/pydatahike/setup.py +42 -0
- package/pydatahike/src/datahike/__init__.py +134 -0
- package/pydatahike/src/datahike/_native.py +250 -0
- package/pydatahike/src/datahike/_version.py +2 -0
- package/pydatahike/src/datahike/database.py +722 -0
- package/pydatahike/src/datahike/edn.py +311 -0
- package/pydatahike/src/datahike/py.typed +0 -0
- package/pydatahike/tests/conftest.py +17 -0
- package/pydatahike/tests/test_basic.py +170 -0
- package/pydatahike/tests/test_database.py +51 -0
- package/pydatahike/tests/test_edn_conversion.py +299 -0
- package/pydatahike/tests/test_query.py +99 -0
- package/pydatahike/tests/test_schema.py +55 -0
- package/resources/clj-kondo.exports/io.replikativ/datahike/config.edn +5 -0
- package/resources/example_server.edn +4 -0
- package/shadow-cljs.edn +56 -0
- package/src/data_readers.clj +7 -0
- package/src/datahike/api/impl.cljc +176 -0
- package/src/datahike/api/specification.cljc +633 -0
- package/src/datahike/api/types.cljc +261 -0
- package/src/datahike/api.cljc +41 -0
- package/src/datahike/array.cljc +99 -0
- package/src/datahike/cli.clj +166 -0
- package/src/datahike/cljs.cljs +6 -0
- package/src/datahike/codegen/cli.clj +406 -0
- package/src/datahike/codegen/clj_kondo.clj +291 -0
- package/src/datahike/codegen/java.clj +403 -0
- package/src/datahike/codegen/naming.cljc +33 -0
- package/src/datahike/codegen/native.clj +559 -0
- package/src/datahike/codegen/pod.clj +488 -0
- package/src/datahike/codegen/python.clj +838 -0
- package/src/datahike/codegen/report.clj +55 -0
- package/src/datahike/codegen/typescript.clj +262 -0
- package/src/datahike/codegen/validation.clj +145 -0
- package/src/datahike/config.cljc +294 -0
- package/src/datahike/connections.cljc +16 -0
- package/src/datahike/connector.cljc +265 -0
- package/src/datahike/constants.cljc +142 -0
- package/src/datahike/core.cljc +297 -0
- package/src/datahike/datom.cljc +459 -0
- package/src/datahike/db/interface.cljc +119 -0
- package/src/datahike/db/search.cljc +305 -0
- package/src/datahike/db/transaction.cljc +937 -0
- package/src/datahike/db/utils.cljc +338 -0
- package/src/datahike/db.cljc +956 -0
- package/src/datahike/experimental/unstructured.cljc +126 -0
- package/src/datahike/experimental/versioning.cljc +172 -0
- package/src/datahike/externs.js +31 -0
- package/src/datahike/gc.cljc +69 -0
- package/src/datahike/http/client.clj +188 -0
- package/src/datahike/http/writer.clj +79 -0
- package/src/datahike/impl/entity.cljc +218 -0
- package/src/datahike/index/interface.cljc +93 -0
- package/src/datahike/index/persistent_set.cljc +469 -0
- package/src/datahike/index/utils.cljc +44 -0
- package/src/datahike/index.cljc +32 -0
- package/src/datahike/js/api.cljs +172 -0
- package/src/datahike/js/api_macros.clj +22 -0
- package/src/datahike/js.cljs +163 -0
- package/src/datahike/json.cljc +209 -0
- package/src/datahike/lru.cljc +146 -0
- package/src/datahike/migrate.clj +39 -0
- package/src/datahike/norm/norm.clj +245 -0
- package/src/datahike/online_gc.cljc +252 -0
- package/src/datahike/pod.clj +155 -0
- package/src/datahike/pull_api.cljc +325 -0
- package/src/datahike/query.cljc +1945 -0
- package/src/datahike/query_stats.cljc +88 -0
- package/src/datahike/readers.cljc +62 -0
- package/src/datahike/remote.cljc +218 -0
- package/src/datahike/schema.cljc +228 -0
- package/src/datahike/schema_cache.cljc +42 -0
- package/src/datahike/spec.cljc +101 -0
- package/src/datahike/store.cljc +80 -0
- package/src/datahike/tools.cljc +308 -0
- package/src/datahike/transit.cljc +80 -0
- package/src/datahike/writer.cljc +239 -0
- package/src/datahike/writing.cljc +362 -0
- package/src/deps.cljs +1 -0
- package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/insert.cljc +76 -0
- package/src-hitchhiker-tree/datahike/index/hitchhiker_tree/upsert.cljc +128 -0
- package/src-hitchhiker-tree/datahike/index/hitchhiker_tree.cljc +213 -0
- package/test/datahike/backward_compatibility_test/src/backward_test.clj +37 -0
- package/test/datahike/integration_test/config_record_file_test.clj +14 -0
- package/test/datahike/integration_test/config_record_test.clj +14 -0
- package/test/datahike/integration_test/depr_config_uri_test.clj +15 -0
- package/test/datahike/integration_test/return_map_test.clj +62 -0
- package/test/datahike/integration_test.cljc +67 -0
- package/test/datahike/norm/norm_test.clj +124 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/001-a1-example.edn +5 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/002-a2-example.edn +5 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/003-tx-fn-test.edn +1 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/004-tx-data-and-tx-fn-test.edn +5 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/01-transact-basic-characters.edn +2 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/02 add occupation.edn +5 -0
- package/test/datahike/norm/resources/naming-and-sorting-test/checksums.edn +12 -0
- package/test/datahike/norm/resources/simple-test/001-a1-example.edn +5 -0
- package/test/datahike/norm/resources/simple-test/002-a2-example.edn +5 -0
- package/test/datahike/norm/resources/simple-test/checksums.edn +4 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/001-a1-example.edn +5 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/002-a2-example.edn +5 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/003-tx-fn-test.edn +1 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/first/checksums.edn +6 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/004-tx-data-and-tx-fn-test.edn +5 -0
- package/test/datahike/norm/resources/tx-data-and-tx-fn-test/second/checksums.edn +2 -0
- package/test/datahike/norm/resources/tx-fn-test/first/001-a1-example.edn +5 -0
- package/test/datahike/norm/resources/tx-fn-test/first/002-a2-example.edn +5 -0
- package/test/datahike/norm/resources/tx-fn-test/first/checksums.edn +4 -0
- package/test/datahike/norm/resources/tx-fn-test/second/003-tx-fn-test.edn +1 -0
- package/test/datahike/norm/resources/tx-fn-test/second/checksums.edn +2 -0
- package/test/datahike/test/api_test.cljc +895 -0
- package/test/datahike/test/array_test.cljc +40 -0
- package/test/datahike/test/attribute_refs/datoms_test.cljc +140 -0
- package/test/datahike/test/attribute_refs/db_test.cljc +42 -0
- package/test/datahike/test/attribute_refs/differences_test.cljc +515 -0
- package/test/datahike/test/attribute_refs/entity_test.cljc +89 -0
- package/test/datahike/test/attribute_refs/pull_api_test.cljc +320 -0
- package/test/datahike/test/attribute_refs/query_find_specs_test.cljc +59 -0
- package/test/datahike/test/attribute_refs/query_fns_test.cljc +130 -0
- package/test/datahike/test/attribute_refs/query_interop_test.cljc +47 -0
- package/test/datahike/test/attribute_refs/query_not_test.cljc +193 -0
- package/test/datahike/test/attribute_refs/query_or_test.cljc +137 -0
- package/test/datahike/test/attribute_refs/query_pull_test.cljc +156 -0
- package/test/datahike/test/attribute_refs/query_rules_test.cljc +176 -0
- package/test/datahike/test/attribute_refs/query_test.cljc +241 -0
- package/test/datahike/test/attribute_refs/temporal_search.cljc +22 -0
- package/test/datahike/test/attribute_refs/transact_test.cljc +220 -0
- package/test/datahike/test/attribute_refs/utils.cljc +128 -0
- package/test/datahike/test/cache_test.cljc +38 -0
- package/test/datahike/test/components_test.cljc +92 -0
- package/test/datahike/test/config_test.cljc +158 -0
- package/test/datahike/test/core_test.cljc +105 -0
- package/test/datahike/test/datom_test.cljc +44 -0
- package/test/datahike/test/db_test.cljc +54 -0
- package/test/datahike/test/entity_spec_test.cljc +159 -0
- package/test/datahike/test/entity_test.cljc +103 -0
- package/test/datahike/test/explode_test.cljc +143 -0
- package/test/datahike/test/filter_test.cljc +75 -0
- package/test/datahike/test/gc_test.cljc +159 -0
- package/test/datahike/test/http/server_test.clj +192 -0
- package/test/datahike/test/http/writer_test.clj +86 -0
- package/test/datahike/test/ident_test.cljc +32 -0
- package/test/datahike/test/index_test.cljc +345 -0
- package/test/datahike/test/insert.cljc +125 -0
- package/test/datahike/test/java_bindings_test.clj +6 -0
- package/test/datahike/test/listen_test.cljc +41 -0
- package/test/datahike/test/lookup_refs_test.cljc +266 -0
- package/test/datahike/test/lru_test.cljc +27 -0
- package/test/datahike/test/migrate_test.clj +297 -0
- package/test/datahike/test/model/core.cljc +376 -0
- package/test/datahike/test/model/invariant.cljc +142 -0
- package/test/datahike/test/model/rng.cljc +82 -0
- package/test/datahike/test/model_test.clj +217 -0
- package/test/datahike/test/nodejs_test.cljs +262 -0
- package/test/datahike/test/online_gc_test.cljc +475 -0
- package/test/datahike/test/pod_test.clj +369 -0
- package/test/datahike/test/pull_api_test.cljc +474 -0
- package/test/datahike/test/purge_test.cljc +144 -0
- package/test/datahike/test/query_aggregates_test.cljc +101 -0
- package/test/datahike/test/query_find_specs_test.cljc +52 -0
- package/test/datahike/test/query_fns_test.cljc +523 -0
- package/test/datahike/test/query_interop_test.cljc +47 -0
- package/test/datahike/test/query_not_test.cljc +189 -0
- package/test/datahike/test/query_or_test.cljc +158 -0
- package/test/datahike/test/query_pull_test.cljc +147 -0
- package/test/datahike/test/query_rules_test.cljc +248 -0
- package/test/datahike/test/query_stats_test.cljc +218 -0
- package/test/datahike/test/query_test.cljc +984 -0
- package/test/datahike/test/schema_test.cljc +424 -0
- package/test/datahike/test/specification_test.cljc +30 -0
- package/test/datahike/test/store_test.cljc +78 -0
- package/test/datahike/test/stress_test.cljc +57 -0
- package/test/datahike/test/time_variance_test.cljc +518 -0
- package/test/datahike/test/tools_test.clj +134 -0
- package/test/datahike/test/transact_test.cljc +518 -0
- package/test/datahike/test/tuples_test.cljc +564 -0
- package/test/datahike/test/unstructured_test.cljc +291 -0
- package/test/datahike/test/upsert_impl_test.cljc +205 -0
- package/test/datahike/test/upsert_test.cljc +363 -0
- package/test/datahike/test/utils.cljc +110 -0
- package/test/datahike/test/validation_test.cljc +48 -0
- package/test/datahike/test/versioning_test.cljc +56 -0
- package/test/datahike/test.cljc +66 -0
- 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.
|