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,172 @@
|
|
|
1
|
+
(ns datahike.js.api
|
|
2
|
+
"JavaScript API for Datahike with Promise conversion and data transformation"
|
|
3
|
+
(:refer-clojure :exclude [filter])
|
|
4
|
+
(:require [datahike.api.specification :refer [api-specification]]
|
|
5
|
+
[datahike.api.impl]
|
|
6
|
+
[datahike.store] ;; Register :mem backend
|
|
7
|
+
[datahike.db.interface]
|
|
8
|
+
[datahike.datom]
|
|
9
|
+
[cljs.core.async :refer [<!]]
|
|
10
|
+
[clojure.string :as str]
|
|
11
|
+
[clojure.walk :as walk]
|
|
12
|
+
[goog.object :as gobj])
|
|
13
|
+
(:require-macros [cljs.core.async.macros :refer [go]]
|
|
14
|
+
[datahike.js.api-macros :refer [emit-js-api]]))
|
|
15
|
+
|
|
16
|
+
;; Register Node.js file backend - conditional require
|
|
17
|
+
;; For Node.js: konserve.node-filestore is added to shadow-cljs :entries
|
|
18
|
+
;; For browser: module is excluded from build
|
|
19
|
+
(when (and (exists? js/require)
|
|
20
|
+
(fn? js/require))
|
|
21
|
+
(try
|
|
22
|
+
(js/require "./konserve.node_filestore")
|
|
23
|
+
(catch :default _ nil)))
|
|
24
|
+
|
|
25
|
+
;; =============================================================================
|
|
26
|
+
;; Data Conversion Helpers
|
|
27
|
+
;;
|
|
28
|
+
;; Universal EDN Conversion Rules (consistent across Python, JavaScript, Java):
|
|
29
|
+
;; - Keys: always keywordized
|
|
30
|
+
;; - Values: ":" prefix = keyword, else literal
|
|
31
|
+
;; - Escape: "\\:" for literal colon strings
|
|
32
|
+
;; - Bonus: UUID auto-detection for convenience
|
|
33
|
+
;; =============================================================================
|
|
34
|
+
|
|
35
|
+
(def ^:private uuid-regex
|
|
36
|
+
"Regex pattern for UUID strings (8-4-4-4-12 hex digits)"
|
|
37
|
+
#"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$")
|
|
38
|
+
|
|
39
|
+
(defn- uuid-string?
|
|
40
|
+
"Check if a string is a valid UUID format"
|
|
41
|
+
[s]
|
|
42
|
+
(and (string? s) (re-matches uuid-regex s)))
|
|
43
|
+
|
|
44
|
+
(defn- convert-string
|
|
45
|
+
"Convert a string to appropriate Clojure type following universal EDN rules:
|
|
46
|
+
- '\\:literal' -> ':literal' (escaped colon becomes literal string with :)
|
|
47
|
+
- ':keyword' -> keyword
|
|
48
|
+
- UUID format -> UUID object (convenience)
|
|
49
|
+
- otherwise -> string"
|
|
50
|
+
[s]
|
|
51
|
+
(cond
|
|
52
|
+
;; Escaped colon - strip backslash and return literal string
|
|
53
|
+
(str/starts-with? s "\\:") (subs s 1)
|
|
54
|
+
;; Colon prefix - convert to keyword
|
|
55
|
+
(str/starts-with? s ":") (keyword (subs s 1))
|
|
56
|
+
;; UUID auto-detection (convenience feature)
|
|
57
|
+
(uuid-string? s) (uuid s)
|
|
58
|
+
;; Regular string
|
|
59
|
+
:else s))
|
|
60
|
+
|
|
61
|
+
(defn js->clj-recursive
|
|
62
|
+
"Recursively convert JS objects to Clojure data with keyword keys.
|
|
63
|
+
Also converts strings like ':keyword' to keywords and UUID strings to UUIDs."
|
|
64
|
+
[x]
|
|
65
|
+
(cond
|
|
66
|
+
;; Check for JS object first (but not arrays, functions, or null)
|
|
67
|
+
(and (object? x)
|
|
68
|
+
(not (array? x))
|
|
69
|
+
(not (fn? x))
|
|
70
|
+
(not (nil? x)))
|
|
71
|
+
(into {} (for [k (js-keys x)]
|
|
72
|
+
(let [v (gobj/get x k)
|
|
73
|
+
;; Convert keys to keywords, stripping leading : if present
|
|
74
|
+
k-kw (if (str/starts-with? k ":")
|
|
75
|
+
(keyword (subs k 1))
|
|
76
|
+
(keyword k))]
|
|
77
|
+
[k-kw (js->clj-recursive v)])))
|
|
78
|
+
|
|
79
|
+
;; Arrays become vectors
|
|
80
|
+
(array? x)
|
|
81
|
+
(mapv js->clj-recursive x)
|
|
82
|
+
|
|
83
|
+
;; Strings: convert keywords, UUIDs, or pass through
|
|
84
|
+
(string? x)
|
|
85
|
+
(convert-string x)
|
|
86
|
+
|
|
87
|
+
;; Everything else passes through
|
|
88
|
+
:else x))
|
|
89
|
+
|
|
90
|
+
(defn clj->js-recursive
|
|
91
|
+
"Recursively convert Clojure data to JS objects.
|
|
92
|
+
Converts keywords to strings with ':' prefix.
|
|
93
|
+
Datahike objects (DB, connections, datoms) pass through unchanged."
|
|
94
|
+
[x]
|
|
95
|
+
(cond
|
|
96
|
+
;; Datahike DB objects - pass through unchanged
|
|
97
|
+
(satisfies? datahike.db.interface/IDB x)
|
|
98
|
+
x
|
|
99
|
+
|
|
100
|
+
;; Datoms - pass through unchanged
|
|
101
|
+
(= (type x) datahike.datom.Datom)
|
|
102
|
+
x
|
|
103
|
+
|
|
104
|
+
;; Connections (check for typical connection keys)
|
|
105
|
+
(and (map? x) (:conn-atom x))
|
|
106
|
+
x
|
|
107
|
+
|
|
108
|
+
;; Keywords become strings with ":"
|
|
109
|
+
(keyword? x)
|
|
110
|
+
(str x)
|
|
111
|
+
|
|
112
|
+
;; Maps become JS objects
|
|
113
|
+
(map? x)
|
|
114
|
+
(let [obj (js-obj)]
|
|
115
|
+
(doseq [[k v] x]
|
|
116
|
+
(gobj/set obj
|
|
117
|
+
(if (keyword? k) (name k) (str k))
|
|
118
|
+
(clj->js-recursive v)))
|
|
119
|
+
obj)
|
|
120
|
+
|
|
121
|
+
;; Sequential collections become arrays
|
|
122
|
+
(sequential? x)
|
|
123
|
+
(into-array (map clj->js-recursive x))
|
|
124
|
+
|
|
125
|
+
;; Sets become arrays
|
|
126
|
+
(set? x)
|
|
127
|
+
(into-array (map clj->js-recursive x))
|
|
128
|
+
|
|
129
|
+
;; Everything else passes through
|
|
130
|
+
:else x))
|
|
131
|
+
|
|
132
|
+
;; =============================================================================
|
|
133
|
+
;; Async/Promise Conversion
|
|
134
|
+
;; =============================================================================
|
|
135
|
+
|
|
136
|
+
(defn maybe-chan->promise
|
|
137
|
+
"Convert a core.async channel to a Promise, or return value directly if not a channel.
|
|
138
|
+
This handles the dynamic async/sync execution in Datahike API.
|
|
139
|
+
|
|
140
|
+
Errors returned on the channel (not thrown) are properly rejected by checking
|
|
141
|
+
if the result is a js/Error or ExceptionInfo."
|
|
142
|
+
[x]
|
|
143
|
+
(if (satisfies? cljs.core.async.impl.protocols/Channel x)
|
|
144
|
+
(js/Promise.
|
|
145
|
+
(fn [resolve reject]
|
|
146
|
+
(go
|
|
147
|
+
(try
|
|
148
|
+
(let [result (<! x)]
|
|
149
|
+
;; Check if result is an error object - reject promise if so
|
|
150
|
+
(if (or (instance? js/Error result)
|
|
151
|
+
(instance? ExceptionInfo result))
|
|
152
|
+
(reject result)
|
|
153
|
+
(resolve result)))
|
|
154
|
+
(catch :default e
|
|
155
|
+
;; Catch any exceptions thrown during channel operations
|
|
156
|
+
(reject e))))))
|
|
157
|
+
(js/Promise.resolve x)))
|
|
158
|
+
|
|
159
|
+
;; =============================================================================
|
|
160
|
+
;; Generate All API Functions
|
|
161
|
+
;; =============================================================================
|
|
162
|
+
|
|
163
|
+
(emit-js-api)
|
|
164
|
+
|
|
165
|
+
;; =============================================================================
|
|
166
|
+
;; Additional JS-specific Helpers
|
|
167
|
+
;; =============================================================================
|
|
168
|
+
|
|
169
|
+
(defn ^:export isPromise
|
|
170
|
+
"Check if a value is a Promise."
|
|
171
|
+
[x]
|
|
172
|
+
(instance? js/Promise x))
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
(ns datahike.js.api-macros
|
|
2
|
+
"Macros for generating JavaScript API."
|
|
3
|
+
(:require [datahike.api.specification :refer [api-specification]]
|
|
4
|
+
[datahike.codegen.naming :refer [js-skip-list clj-name->js-name]]))
|
|
5
|
+
|
|
6
|
+
(defmacro emit-js-api
|
|
7
|
+
"Generate JavaScript API functions from api-specification.
|
|
8
|
+
This macro must be in a .clj file since it's used by ClojureScript."
|
|
9
|
+
[]
|
|
10
|
+
`(do
|
|
11
|
+
~@(for [[clj-fn-name {:keys [doc impl]}] api-specification
|
|
12
|
+
:when (not (contains? js-skip-list clj-fn-name))
|
|
13
|
+
:let [js-fn-name (symbol (clj-name->js-name clj-fn-name))
|
|
14
|
+
impl-fn (symbol (namespace impl) (name impl))]]
|
|
15
|
+
`(defn ~(with-meta js-fn-name {:export true :doc doc})
|
|
16
|
+
[& args#]
|
|
17
|
+
(let [clj-args# (map datahike.js.api/js->clj-recursive args#)
|
|
18
|
+
result# (apply ~impl-fn clj-args#)]
|
|
19
|
+
(-> result#
|
|
20
|
+
datahike.js.api/maybe-chan->promise
|
|
21
|
+
(.then datahike.js.api/clj->js-recursive)))))))
|
|
22
|
+
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
(ns ^:no-doc datahike.js
|
|
2
|
+
(:refer-clojure :exclude [filter])
|
|
3
|
+
(:require
|
|
4
|
+
[goog.object :as go]
|
|
5
|
+
[datahike.core :as d]
|
|
6
|
+
[clojure.walk :as walk]
|
|
7
|
+
[cljs.reader]))
|
|
8
|
+
|
|
9
|
+
;; Conversions
|
|
10
|
+
|
|
11
|
+
(defn- keywordize [s]
|
|
12
|
+
(if (and (string? s) (= (subs s 0 1) ":"))
|
|
13
|
+
(keyword (subs s 1))
|
|
14
|
+
s))
|
|
15
|
+
|
|
16
|
+
(defn- schema->clj [schema]
|
|
17
|
+
(->> (js->clj schema)
|
|
18
|
+
(reduce-kv
|
|
19
|
+
(fn [m k v] (assoc m k (walk/postwalk keywordize v))) {})))
|
|
20
|
+
|
|
21
|
+
(declare entities->clj)
|
|
22
|
+
|
|
23
|
+
(defn- entity-map->clj [e]
|
|
24
|
+
(walk/postwalk
|
|
25
|
+
(fn [form]
|
|
26
|
+
(if (and (map? form) (contains? form ":db/id"))
|
|
27
|
+
(-> form
|
|
28
|
+
(dissoc ":db/id")
|
|
29
|
+
(assoc :db/id (get form ":db/id")))
|
|
30
|
+
form))
|
|
31
|
+
e))
|
|
32
|
+
|
|
33
|
+
(defn- entity->clj [e]
|
|
34
|
+
(cond
|
|
35
|
+
(map? e)
|
|
36
|
+
(entity-map->clj e)
|
|
37
|
+
|
|
38
|
+
(= (first e) ":db.fn/call")
|
|
39
|
+
(let [[_ f & args] e]
|
|
40
|
+
(concat [:db.fn/call (fn [& args] (entities->clj (apply f args)))] args))
|
|
41
|
+
|
|
42
|
+
(sequential? e)
|
|
43
|
+
(let [[op & entity] e]
|
|
44
|
+
(concat [(keywordize op)] entity))))
|
|
45
|
+
|
|
46
|
+
(defn- entities->clj [entities]
|
|
47
|
+
(->> (js->clj entities)
|
|
48
|
+
(map entity->clj)))
|
|
49
|
+
|
|
50
|
+
(defn- tempids->js [tempids]
|
|
51
|
+
(let [obj (js-obj)]
|
|
52
|
+
(doseq [[k v] tempids]
|
|
53
|
+
(go/set obj (str k) v))
|
|
54
|
+
obj))
|
|
55
|
+
|
|
56
|
+
(defn- tx-report->js [report]
|
|
57
|
+
#js {:db_before (:db-before report)
|
|
58
|
+
:db_after (:db-after report)
|
|
59
|
+
:tx_data (->> (:tx-data report) into-array)
|
|
60
|
+
:tempids (tempids->js (:tempids report))
|
|
61
|
+
:tx_meta (:tx-meta report)})
|
|
62
|
+
|
|
63
|
+
(defn js->Datom [d]
|
|
64
|
+
(if (array? d)
|
|
65
|
+
(d/datom (aget d 0) (aget d 1) (aget d 2) (or (aget d 3) d/tx0) (or (aget d 4) true))
|
|
66
|
+
(d/datom (.-e d) (.-a d) (.-v d) (or (.-tx d) d/tx0) (or (.-added d) true))))
|
|
67
|
+
|
|
68
|
+
(defn- pull-result->js
|
|
69
|
+
[result]
|
|
70
|
+
(->> result
|
|
71
|
+
(walk/postwalk #(if (keyword? %) (str %) %))
|
|
72
|
+
clj->js))
|
|
73
|
+
|
|
74
|
+
;; Public API
|
|
75
|
+
|
|
76
|
+
(defn ^:export empty_db [& [schema]]
|
|
77
|
+
(d/empty-db (schema->clj schema)))
|
|
78
|
+
|
|
79
|
+
(defn ^:export init_db [datoms & [schema]]
|
|
80
|
+
(d/init-db (map js->Datom datoms) (schema->clj schema)))
|
|
81
|
+
|
|
82
|
+
(defn ^:export q [query & sources]
|
|
83
|
+
(let [query (cljs.reader/read-string query)
|
|
84
|
+
results (apply d/q query sources)]
|
|
85
|
+
(clj->js results)))
|
|
86
|
+
|
|
87
|
+
(defn ^:export pull [db pattern eid]
|
|
88
|
+
(let [pattern (cljs.reader/read-string pattern)
|
|
89
|
+
eid (js->clj eid)
|
|
90
|
+
results (d/pull db pattern eid)]
|
|
91
|
+
(pull-result->js results)))
|
|
92
|
+
|
|
93
|
+
(defn ^:export pull_many [db pattern eids]
|
|
94
|
+
(let [pattern (cljs.reader/read-string pattern)
|
|
95
|
+
eids (js->clj eids)
|
|
96
|
+
results (d/pull-many db pattern eids)]
|
|
97
|
+
(pull-result->js results)))
|
|
98
|
+
|
|
99
|
+
(defn ^:export db_with [db entities]
|
|
100
|
+
(d/db-with db (entities->clj entities)))
|
|
101
|
+
|
|
102
|
+
(defn ^:export entity [db eid]
|
|
103
|
+
(d/entity db (js->clj eid)))
|
|
104
|
+
|
|
105
|
+
(def ^:export touch d/touch)
|
|
106
|
+
(def ^:export entity_db d/entity-db)
|
|
107
|
+
(def ^:export filter d/filter)
|
|
108
|
+
(def ^:export is_filtered d/is-filtered)
|
|
109
|
+
|
|
110
|
+
(defn ^:export create_conn [& [schema]]
|
|
111
|
+
(d/create-conn (schema->clj schema)))
|
|
112
|
+
|
|
113
|
+
(def ^:export conn_from_db d/conn-from-db)
|
|
114
|
+
|
|
115
|
+
(defn ^:export conn_from_datoms
|
|
116
|
+
([datoms] (conn_from_db (init_db datoms)))
|
|
117
|
+
([datoms schema] (conn_from_db (init_db datoms schema))))
|
|
118
|
+
|
|
119
|
+
(defn ^:export db [conn] @conn)
|
|
120
|
+
|
|
121
|
+
(defn ^:export transact [conn entities & [tx-meta]]
|
|
122
|
+
(let [entities (entities->clj entities)
|
|
123
|
+
report (-> (d/-transact! conn entities tx-meta)
|
|
124
|
+
tx-report->js)]
|
|
125
|
+
(doseq [[_ callback] @(:listeners (meta conn))]
|
|
126
|
+
(callback report))
|
|
127
|
+
report))
|
|
128
|
+
|
|
129
|
+
(defn ^:export reset_conn [conn db & [tx-meta]]
|
|
130
|
+
(let [report #js {:db_before @conn
|
|
131
|
+
:db_after db
|
|
132
|
+
:tx_data (into-array
|
|
133
|
+
(concat
|
|
134
|
+
(map #(assoc % :added false) (d/datoms @conn :eavt))
|
|
135
|
+
(d/datoms db :eavt)))
|
|
136
|
+
:tx_meta tx-meta}]
|
|
137
|
+
(reset! conn db)
|
|
138
|
+
(doseq [[_ callback] @(:listeners (meta conn))]
|
|
139
|
+
(callback report))
|
|
140
|
+
db))
|
|
141
|
+
|
|
142
|
+
(def ^:export listen d/listen!)
|
|
143
|
+
(def ^:export unlisten d/unlisten!)
|
|
144
|
+
|
|
145
|
+
(defn ^:export resolve_tempid [tempids tempid]
|
|
146
|
+
(go/get tempids (str tempid)))
|
|
147
|
+
|
|
148
|
+
(defn ^:export datoms [db index & components]
|
|
149
|
+
(->> (apply d/datoms db (keywordize index) components)
|
|
150
|
+
into-array))
|
|
151
|
+
|
|
152
|
+
(defn ^:export seek_datoms [db index & components]
|
|
153
|
+
(->> (apply d/seek-datoms db (keywordize index) components)
|
|
154
|
+
into-array))
|
|
155
|
+
|
|
156
|
+
(defn ^:export index_range [db attr start end]
|
|
157
|
+
(into-array (d/index-range db attr start end)))
|
|
158
|
+
|
|
159
|
+
(defn ^:export squuid []
|
|
160
|
+
(str (d/squuid)))
|
|
161
|
+
|
|
162
|
+
(defn ^:export squuid_time_millis [uuid]
|
|
163
|
+
(d/squuid-time-millis (cljs.core/uuid uuid)))
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
(ns datahike.json
|
|
2
|
+
"JSON related translations."
|
|
3
|
+
(:require [clojure.edn :as edn]
|
|
4
|
+
[clojure.walk :as walk]
|
|
5
|
+
[datahike.store :refer [store-identity]]
|
|
6
|
+
[datahike.readers :as readers]
|
|
7
|
+
[datahike.connector]
|
|
8
|
+
[datahike.datom :as dd]
|
|
9
|
+
[datahike.schema :as s]
|
|
10
|
+
[jsonista.core :as j]
|
|
11
|
+
[jsonista.tagged :as jt])
|
|
12
|
+
#?(:clj
|
|
13
|
+
(:import [datahike.datom Datom]
|
|
14
|
+
[datahike.impl.entity Entity]
|
|
15
|
+
[com.fasterxml.jackson.core JsonGenerator]
|
|
16
|
+
[datahike.db HistoricalDB AsOfDB SinceDB])))
|
|
17
|
+
|
|
18
|
+
(defn config->store-id [config]
|
|
19
|
+
[(store-identity (:store config))
|
|
20
|
+
(:branch config)])
|
|
21
|
+
|
|
22
|
+
(defn db->map [db]
|
|
23
|
+
(let [{:keys [config meta max-eid max-tx]} db]
|
|
24
|
+
{:store-id (config->store-id config)
|
|
25
|
+
:commit-id (:datahike/commit-id meta)
|
|
26
|
+
:max-eid max-eid
|
|
27
|
+
:max-tx max-tx}))
|
|
28
|
+
|
|
29
|
+
(declare mapper)
|
|
30
|
+
|
|
31
|
+
(defn write-to-generator [f]
|
|
32
|
+
(fn [x ^JsonGenerator gen]
|
|
33
|
+
(.writeRawValue gen (j/write-value-as-string (f x) mapper))))
|
|
34
|
+
|
|
35
|
+
(def json-base-handlers
|
|
36
|
+
{clojure.lang.Keyword
|
|
37
|
+
{:tag "!kw"
|
|
38
|
+
:encode jt/encode-keyword
|
|
39
|
+
:decode keyword}
|
|
40
|
+
|
|
41
|
+
clojure.lang.Symbol
|
|
42
|
+
{:tag "!sym"
|
|
43
|
+
:encode jt/encode-str
|
|
44
|
+
:decode symbol}
|
|
45
|
+
|
|
46
|
+
clojure.lang.PersistentHashSet
|
|
47
|
+
{:tag "!set"
|
|
48
|
+
:encode jt/encode-collection
|
|
49
|
+
:decode set}
|
|
50
|
+
|
|
51
|
+
java.util.UUID
|
|
52
|
+
{:tag "!uuid"
|
|
53
|
+
:encode jt/encode-str
|
|
54
|
+
:decode #(java.util.UUID/fromString %)}
|
|
55
|
+
|
|
56
|
+
java.util.Date
|
|
57
|
+
{:tag "!date"
|
|
58
|
+
:encode #(jt/encode-str (.getTime ^java.util.Date %1) %2)
|
|
59
|
+
:decode #(java.util.Date. (Long/parseLong %))}})
|
|
60
|
+
|
|
61
|
+
(def mapper-opts
|
|
62
|
+
{:encode-key-fn true
|
|
63
|
+
:decode-key-fn true
|
|
64
|
+
:modules [(jt/module
|
|
65
|
+
{:handlers
|
|
66
|
+
(merge
|
|
67
|
+
json-base-handlers
|
|
68
|
+
{datahike.connector.Connection
|
|
69
|
+
{:tag "!datahike/Connection"
|
|
70
|
+
:encode (write-to-generator #(config->store-id (:config @(:wrapped-atom %))))
|
|
71
|
+
:decode datahike.readers/connection-from-reader}
|
|
72
|
+
|
|
73
|
+
datahike.datom.Datom
|
|
74
|
+
{:tag "!datahike/Datom"
|
|
75
|
+
:encode (write-to-generator
|
|
76
|
+
(fn [^Datom d]
|
|
77
|
+
[(.-e d) (.-a d) (.-v d) (dd/datom-tx d) (dd/datom-added d)]))
|
|
78
|
+
:decode datahike.readers/datom-from-reader}
|
|
79
|
+
|
|
80
|
+
datahike.db.TxReport
|
|
81
|
+
{:tag "!datahike/TxReport"
|
|
82
|
+
:encode (write-to-generator #(into {} %))
|
|
83
|
+
:decode datahike.db/map->TxReport}
|
|
84
|
+
|
|
85
|
+
datahike.db.DB
|
|
86
|
+
{:tag "!datahike/DB"
|
|
87
|
+
:encode (write-to-generator db->map)
|
|
88
|
+
:decode datahike.readers/db-from-reader}
|
|
89
|
+
|
|
90
|
+
datahike.db.HistoricalDB
|
|
91
|
+
{:tag "!datahike/HistoricalDB"
|
|
92
|
+
:encode (write-to-generator
|
|
93
|
+
(fn [{:keys [origin-db]}]
|
|
94
|
+
{:origin origin-db}))
|
|
95
|
+
:decode datahike.readers/history-from-reader}
|
|
96
|
+
|
|
97
|
+
datahike.db.SinceDB
|
|
98
|
+
{:tag "!datahike/SinceDB"
|
|
99
|
+
:encode (write-to-generator
|
|
100
|
+
(fn [{:keys [origin-db time-point]}]
|
|
101
|
+
{:origin origin-db
|
|
102
|
+
:time-point time-point}))
|
|
103
|
+
:decode datahike.readers/since-from-reader}
|
|
104
|
+
|
|
105
|
+
datahike.db.AsOfDB
|
|
106
|
+
{:tag "!datahike/AsOfDB"
|
|
107
|
+
:encode (write-to-generator
|
|
108
|
+
(fn [{:keys [origin-db time-point]}]
|
|
109
|
+
{:origin origin-db
|
|
110
|
+
:time-point time-point}))
|
|
111
|
+
:decode datahike.readers/as-of-from-reader}
|
|
112
|
+
|
|
113
|
+
datahike.impl.entity.Entity
|
|
114
|
+
{:tag "!datahike/Entity"
|
|
115
|
+
:encode (write-to-generator
|
|
116
|
+
(fn [^Entity e]
|
|
117
|
+
(assoc (into {} e)
|
|
118
|
+
:db (.-db e)
|
|
119
|
+
:eid (.-eid e))))
|
|
120
|
+
:decode datahike.readers/entity-from-reader}})})]})
|
|
121
|
+
|
|
122
|
+
(def mapper (j/object-mapper mapper-opts))
|
|
123
|
+
|
|
124
|
+
;; import from datahike-server for JSON transact support with this code you can
|
|
125
|
+
;; pass normal JSON maps or arrays of Datoms and strings will be automatically
|
|
126
|
+
;; converted to keywords depending on their position
|
|
127
|
+
|
|
128
|
+
(def number-re #"\d+(\.\d+)?")
|
|
129
|
+
(def number-format-instance (java.text.NumberFormat/getInstance))
|
|
130
|
+
|
|
131
|
+
(defn- filter-value-type-attrs [valtypes schema]
|
|
132
|
+
(into #{} (filter #(-> % schema :db/valueType valtypes) (keys schema))))
|
|
133
|
+
|
|
134
|
+
(def ^:private filter-kw-attrs
|
|
135
|
+
(partial filter-value-type-attrs #{:db.type/keyword :db.type/value :db.type/cardinality :db.type/unique}))
|
|
136
|
+
|
|
137
|
+
(def keyword-valued-schema-attrs (filter-kw-attrs s/implicit-schema-spec))
|
|
138
|
+
|
|
139
|
+
(defn- xf-val [f v]
|
|
140
|
+
(if (vector? v) (map f v) (f v)))
|
|
141
|
+
|
|
142
|
+
(declare handle-id-or-av-pair)
|
|
143
|
+
|
|
144
|
+
(defn- xf-ref-val [v valtype-attrs-map db]
|
|
145
|
+
(if (vector? v)
|
|
146
|
+
(walk/prewalk #(handle-id-or-av-pair % valtype-attrs-map db) v)
|
|
147
|
+
v))
|
|
148
|
+
|
|
149
|
+
(defn keywordize-string [s]
|
|
150
|
+
(if (string? s) (keyword s) s))
|
|
151
|
+
|
|
152
|
+
(defn ident-for [^datahike.db.DB db a]
|
|
153
|
+
(if (and (number? a) (some? db)) (.-ident-for db a) a))
|
|
154
|
+
|
|
155
|
+
(defn cond-xf-val
|
|
156
|
+
[a-ident v {:keys [ref-attrs long-attrs keyword-attrs symbol-attrs] :as valtype-attrs-map} db]
|
|
157
|
+
(cond
|
|
158
|
+
(contains? ref-attrs a-ident) (xf-ref-val v valtype-attrs-map db)
|
|
159
|
+
(contains? long-attrs a-ident) (xf-val long v)
|
|
160
|
+
(contains? keyword-attrs a-ident) (xf-val keyword v)
|
|
161
|
+
(contains? symbol-attrs a-ident) (xf-val symbol v)
|
|
162
|
+
:else v))
|
|
163
|
+
|
|
164
|
+
(defn handle-id-or-av-pair
|
|
165
|
+
([v valtype-attrs-map]
|
|
166
|
+
(handle-id-or-av-pair v valtype-attrs-map nil))
|
|
167
|
+
([v valtype-attrs-map db]
|
|
168
|
+
(if (and (vector? v) (= (count v) 2))
|
|
169
|
+
(let [a (keywordize-string (first v))]
|
|
170
|
+
[a (cond-xf-val (ident-for db a) (nth v 1) valtype-attrs-map db)])
|
|
171
|
+
v)))
|
|
172
|
+
|
|
173
|
+
(defn- xf-tx-data-map [m valtype-attrs-map db]
|
|
174
|
+
(into {}
|
|
175
|
+
(map (fn [[a v]]
|
|
176
|
+
[a (if (= :db/id a)
|
|
177
|
+
(handle-id-or-av-pair [a v] valtype-attrs-map db)
|
|
178
|
+
(cond-xf-val a v valtype-attrs-map db))])
|
|
179
|
+
m)))
|
|
180
|
+
|
|
181
|
+
(defn- xf-tx-data-vec [tx-vec valtype-attrs-map db]
|
|
182
|
+
(let [op (first tx-vec)
|
|
183
|
+
[e a v] (rest tx-vec)
|
|
184
|
+
a (keywordize-string a)]
|
|
185
|
+
(vec (filter some? (list (keyword op)
|
|
186
|
+
(handle-id-or-av-pair e valtype-attrs-map db)
|
|
187
|
+
a
|
|
188
|
+
(cond-xf-val (ident-for db a) v valtype-attrs-map db))))))
|
|
189
|
+
|
|
190
|
+
(defn get-valtype-attrs-map [schema]
|
|
191
|
+
(let [ref-valued-attrs (filter-value-type-attrs #{:db.type/ref} schema)
|
|
192
|
+
long-valued-attrs (filter-value-type-attrs #{:db.type/long} schema)
|
|
193
|
+
kw-valued-attrs (clojure.set/union keyword-valued-schema-attrs (filter-kw-attrs schema))
|
|
194
|
+
sym-valued-attrs (filter-value-type-attrs #{:db.type/symbol} schema)]
|
|
195
|
+
{:ref-attrs ref-valued-attrs
|
|
196
|
+
:long-attrs long-valued-attrs
|
|
197
|
+
:keyword-attrs kw-valued-attrs
|
|
198
|
+
:symbol-attrs sym-valued-attrs}))
|
|
199
|
+
|
|
200
|
+
(defn xf-data-for-tx [tx-data db]
|
|
201
|
+
(let [valtype-attrs-map (get-valtype-attrs-map (:schema db))]
|
|
202
|
+
(map #(let [xf-fn (cond (map? %) xf-tx-data-map
|
|
203
|
+
(vector? %) xf-tx-data-vec
|
|
204
|
+
; Q: Is this error appropriate?
|
|
205
|
+
:else (throw (ex-info "Only maps and vectors allowed in :tx-data and :tx-meta"
|
|
206
|
+
{:event :handlers/transact :data tx-data})))]
|
|
207
|
+
(xf-fn % valtype-attrs-map db))
|
|
208
|
+
tx-data)))
|
|
209
|
+
|