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,488 @@
|
|
|
1
|
+
(ns datahike.codegen.pod
|
|
2
|
+
"Generate Babashka pod bindings from API specification.
|
|
3
|
+
|
|
4
|
+
This namespace provides pod-specific configuration and logic for:
|
|
5
|
+
- Mapping API operations to pod functions with ID-based references
|
|
6
|
+
- Managing connection and database caching
|
|
7
|
+
- Generating describe-map for pod protocol
|
|
8
|
+
- Handling argument resolution and result transforms"
|
|
9
|
+
(:require [clojure.set :as set]
|
|
10
|
+
[clojure.string :as str]
|
|
11
|
+
[datahike.api.specification :refer [api-specification]]))
|
|
12
|
+
|
|
13
|
+
;; =============================================================================
|
|
14
|
+
;; Pod-Specific Configuration (Overlay)
|
|
15
|
+
;; =============================================================================
|
|
16
|
+
|
|
17
|
+
(def pod-operations
|
|
18
|
+
"Pod-specific configuration extending the universal API specification.
|
|
19
|
+
|
|
20
|
+
Keys:
|
|
21
|
+
- :resolve - Map of arg positions to resolver type (:conn, :db)
|
|
22
|
+
- :returns - What the function returns (:conn-id, :db-id, :value)
|
|
23
|
+
- :transform - Named transform to apply to result
|
|
24
|
+
- :post-action - Action after main operation (:remove-conn)
|
|
25
|
+
- :custom-fn - Custom function body (quoted) for operations needing special handling"
|
|
26
|
+
|
|
27
|
+
'{;; Database lifecycle - direct pass-through
|
|
28
|
+
database-exists? {:returns :value}
|
|
29
|
+
create-database {:returns :value}
|
|
30
|
+
delete-database {:returns :value}
|
|
31
|
+
|
|
32
|
+
;; Connection lifecycle
|
|
33
|
+
connect {:returns :conn-id}
|
|
34
|
+
release {:resolve {0 :conn}
|
|
35
|
+
:returns :value
|
|
36
|
+
:post-action :remove-conn}
|
|
37
|
+
|
|
38
|
+
;; DB access
|
|
39
|
+
db {:resolve {0 :conn}
|
|
40
|
+
:returns :db-id}
|
|
41
|
+
|
|
42
|
+
;; Temporal - derive from db
|
|
43
|
+
as-of {:resolve {0 :db} :returns :db-id}
|
|
44
|
+
since {:resolve {0 :db} :returns :db-id}
|
|
45
|
+
history {:resolve {0 :db} :returns :db-id}
|
|
46
|
+
db-with {:resolve {0 :db} :returns :db-id}
|
|
47
|
+
|
|
48
|
+
;; Query - has custom implementation due to multiple calling conventions
|
|
49
|
+
q {:custom-fn
|
|
50
|
+
(fn [& args]
|
|
51
|
+
(let [resolve-db-arg (fn [arg]
|
|
52
|
+
(if-let [entry (get @dbs arg)]
|
|
53
|
+
(:db entry)
|
|
54
|
+
arg))]
|
|
55
|
+
(if (map? (first args))
|
|
56
|
+
;; Map syntax: {:query ... :args [...]}
|
|
57
|
+
(d/q (update (first args) :args (fn [a] (mapv resolve-db-arg a))))
|
|
58
|
+
;; Vector syntax: query db & args
|
|
59
|
+
(apply d/q (first args) (mapv resolve-db-arg (rest args))))))}
|
|
60
|
+
|
|
61
|
+
;; DB consumers - resolve db, return value
|
|
62
|
+
pull {:resolve {0 :db} :returns :value}
|
|
63
|
+
pull-many {:resolve {0 :db} :returns :value}
|
|
64
|
+
entity {:resolve {0 :db} :returns :value :transform :entity->map}
|
|
65
|
+
datoms {:resolve {0 :db} :returns :value :transform :datoms->seqs}
|
|
66
|
+
seek-datoms {:resolve {0 :db} :returns :value :transform :datoms->seqs}
|
|
67
|
+
schema {:resolve {0 :db} :returns :value}
|
|
68
|
+
reverse-schema {:resolve {0 :db} :returns :value}
|
|
69
|
+
metrics {:resolve {0 :db} :returns :value}
|
|
70
|
+
|
|
71
|
+
;; Connection consumers
|
|
72
|
+
transact {:resolve {0 :conn}
|
|
73
|
+
:returns :value
|
|
74
|
+
:transform :tx-report->summary}})
|
|
75
|
+
|
|
76
|
+
(def pod-excluded-operations
|
|
77
|
+
"Operations excluded from pod with documented reasons."
|
|
78
|
+
'{listen "Requires persistent callbacks - not supported in pod protocol"
|
|
79
|
+
unlisten "Requires persistent callbacks - not supported in pod protocol"
|
|
80
|
+
transact! "Async variant - pods are synchronous"
|
|
81
|
+
tempid "Only useful within transaction context"
|
|
82
|
+
entity-db "Returns DB from entity - limited utility in pod context"
|
|
83
|
+
filter "Requires function argument - cannot serialize across pod boundary"
|
|
84
|
+
is-filtered "Limited utility in pod context"
|
|
85
|
+
with "Returns tx-report with db objects - use db-with instead"
|
|
86
|
+
load-entities "Batch loading - use transact instead"
|
|
87
|
+
query-stats "Not yet exposed in pod"
|
|
88
|
+
index-range "Advanced index operation - can add later"
|
|
89
|
+
gc-storage "Maintenance operation - can add later"})
|
|
90
|
+
|
|
91
|
+
(def pod-additions
|
|
92
|
+
"Pod-specific operations not in main API specification."
|
|
93
|
+
'{release-db {:doc "Release a cached database snapshot from pod memory.
|
|
94
|
+
|
|
95
|
+
Takes the db-id that was returned from db, as-of, since, or history.
|
|
96
|
+
Returns an empty map."
|
|
97
|
+
:args [:db-id]
|
|
98
|
+
:returns :value}})
|
|
99
|
+
|
|
100
|
+
(def with-db-macro-code
|
|
101
|
+
"Client-side macro for automatic db cleanup."
|
|
102
|
+
"(defmacro with-db [bindings & body]
|
|
103
|
+
(cond
|
|
104
|
+
(= (count bindings) 0) `(do ~@body)
|
|
105
|
+
(symbol? (bindings 0)) `(let ~(subvec bindings 0 2)
|
|
106
|
+
(try
|
|
107
|
+
(with-db ~(subvec bindings 2) ~@body)
|
|
108
|
+
(finally
|
|
109
|
+
(release-db ~(bindings 0)))))
|
|
110
|
+
:else (throw (IllegalArgumentException.
|
|
111
|
+
\"with-db only allows Symbols in bindings\"))))")
|
|
112
|
+
|
|
113
|
+
;; =============================================================================
|
|
114
|
+
;; Transform Registry
|
|
115
|
+
;; =============================================================================
|
|
116
|
+
|
|
117
|
+
(def transforms
|
|
118
|
+
"Named transforms for pod result processing.
|
|
119
|
+
Values are quoted forms that will be inlined in generated code."
|
|
120
|
+
'{:entity->map
|
|
121
|
+
(fn [e] (reduce-kv #(assoc %1 %2 %3) {} e))
|
|
122
|
+
|
|
123
|
+
:datoms->seqs
|
|
124
|
+
(fn [datoms] (map seq datoms))
|
|
125
|
+
|
|
126
|
+
:tx-report->summary
|
|
127
|
+
(fn [{:keys [db-before db-after tx-meta tx-data tempids]}]
|
|
128
|
+
{:tempids tempids
|
|
129
|
+
:db-before (select-keys db-before [:max-tx :max-eid])
|
|
130
|
+
:db-after (select-keys db-after [:max-tx :max-eid])
|
|
131
|
+
:tx-meta tx-meta
|
|
132
|
+
:tx-data (map seq tx-data)})})
|
|
133
|
+
|
|
134
|
+
;; =============================================================================
|
|
135
|
+
;; Arity Extraction from Malli Schemas
|
|
136
|
+
;; =============================================================================
|
|
137
|
+
|
|
138
|
+
(defn extract-arities
|
|
139
|
+
"Extract argument arities from malli function schema.
|
|
140
|
+
Returns vector of arity vectors, e.g. [[] [config] [config opts]]"
|
|
141
|
+
[schema]
|
|
142
|
+
(cond
|
|
143
|
+
;; [:function [:=> [:cat ...] ret] [:=> [:cat ...] ret] ...]
|
|
144
|
+
(and (vector? schema) (= :function (first schema)))
|
|
145
|
+
(vec (for [arity-schema (rest schema)
|
|
146
|
+
:when (and (vector? arity-schema) (= :=> (first arity-schema)))]
|
|
147
|
+
(let [[_ input-schema _] arity-schema]
|
|
148
|
+
(if (and (vector? input-schema) (= :cat (first input-schema)))
|
|
149
|
+
(vec (rest input-schema))
|
|
150
|
+
[]))))
|
|
151
|
+
|
|
152
|
+
;; [:=> [:cat ...] ret]
|
|
153
|
+
(and (vector? schema) (= :=> (first schema)))
|
|
154
|
+
(let [[_ input-schema _] schema]
|
|
155
|
+
(if (and (vector? input-schema) (= :cat (first input-schema)))
|
|
156
|
+
[(vec (rest input-schema))]
|
|
157
|
+
[[]]))
|
|
158
|
+
|
|
159
|
+
:else
|
|
160
|
+
[[]]))
|
|
161
|
+
|
|
162
|
+
(defn variadic-schema?
|
|
163
|
+
"Check if a schema element is a variadic marker like [:* :any]"
|
|
164
|
+
[schema-elem]
|
|
165
|
+
(and (vector? schema-elem)
|
|
166
|
+
(= :* (first schema-elem))))
|
|
167
|
+
|
|
168
|
+
(defn arity-arg-names
|
|
169
|
+
"Generate argument names for an arity.
|
|
170
|
+
Returns vector of symbols like [arg0 arg1 arg2] or [arg0 arg1 & args] for variadic.
|
|
171
|
+
Also returns metadata {:variadic? bool}"
|
|
172
|
+
[arity-schema]
|
|
173
|
+
(let [;; Check if last element is variadic
|
|
174
|
+
has-variadic? (and (seq arity-schema)
|
|
175
|
+
(variadic-schema? (last arity-schema)))
|
|
176
|
+
;; Fixed args are all but the variadic marker
|
|
177
|
+
fixed-schema (if has-variadic?
|
|
178
|
+
(butlast arity-schema)
|
|
179
|
+
arity-schema)
|
|
180
|
+
fixed-names (vec (map-indexed (fn [i _] (symbol (str "arg" i))) fixed-schema))]
|
|
181
|
+
(if has-variadic?
|
|
182
|
+
{:args (vec (concat fixed-names ['& 'rest-args]))
|
|
183
|
+
:variadic? true
|
|
184
|
+
:fixed-count (count fixed-names)}
|
|
185
|
+
{:args fixed-names
|
|
186
|
+
:variadic? false
|
|
187
|
+
:fixed-count (count fixed-names)})))
|
|
188
|
+
|
|
189
|
+
;; =============================================================================
|
|
190
|
+
;; Code Generation - Simplified Approach
|
|
191
|
+
;; =============================================================================
|
|
192
|
+
|
|
193
|
+
(defn wrap-with-transform
|
|
194
|
+
"Wrap result expression with transform if specified."
|
|
195
|
+
[transform result-expr]
|
|
196
|
+
(if transform
|
|
197
|
+
(list (get transforms transform) result-expr)
|
|
198
|
+
result-expr))
|
|
199
|
+
|
|
200
|
+
;; =============================================================================
|
|
201
|
+
;; Function Generation
|
|
202
|
+
;; =============================================================================
|
|
203
|
+
|
|
204
|
+
(defn generate-api-call
|
|
205
|
+
"Generate the API call expression, handling variadic args with apply."
|
|
206
|
+
[api-impl fixed-args variadic?]
|
|
207
|
+
(if variadic?
|
|
208
|
+
`(apply ~api-impl ~@fixed-args ~'rest-args)
|
|
209
|
+
`(~api-impl ~@fixed-args)))
|
|
210
|
+
|
|
211
|
+
(defn generate-arity-body
|
|
212
|
+
"Generate the body for a single arity of a pod function.
|
|
213
|
+
Uses explicit symbols instead of gensyms for clarity in generated code.
|
|
214
|
+
arity-info is {:args [...] :variadic? bool :fixed-count n}"
|
|
215
|
+
[op-name overlay arity-info api-impl]
|
|
216
|
+
(let [{:keys [resolve returns transform post-action]} overlay
|
|
217
|
+
{:keys [args variadic? fixed-count]} arity-info
|
|
218
|
+
;; Extract just the named args (excluding & and rest-args)
|
|
219
|
+
named-args (if variadic?
|
|
220
|
+
(take fixed-count args)
|
|
221
|
+
args)
|
|
222
|
+
;; Symbols for generated code
|
|
223
|
+
result-sym 'result
|
|
224
|
+
db-id-sym 'db-id
|
|
225
|
+
conn-id-sym 'conn-id
|
|
226
|
+
;; First arg is typically the one being resolved
|
|
227
|
+
first-arg (first named-args)
|
|
228
|
+
rest-named-args (rest named-args)
|
|
229
|
+
;; Check what kind of resolution we need
|
|
230
|
+
resolves-conn? (= :conn (get resolve 0))
|
|
231
|
+
resolves-db? (= :db (get resolve 0))]
|
|
232
|
+
|
|
233
|
+
(cond
|
|
234
|
+
;; Case: resolve conn, return conn-id (connect)
|
|
235
|
+
(and resolves-conn? (= returns :conn-id))
|
|
236
|
+
`(let [~result-sym ~(generate-api-call api-impl named-args variadic?)
|
|
237
|
+
~conn-id-sym (~'generate-conn-id ~(or first-arg {}))]
|
|
238
|
+
(swap! ~'conns assoc ~conn-id-sym ~result-sym)
|
|
239
|
+
~conn-id-sym)
|
|
240
|
+
|
|
241
|
+
;; Case: resolve conn, return db-id (db from conn)
|
|
242
|
+
(and resolves-conn? (= returns :db-id))
|
|
243
|
+
`(let [~'conn (~'resolve-conn ~first-arg)
|
|
244
|
+
~result-sym (~'d/db ~'conn)
|
|
245
|
+
~db-id-sym (~'generate-db-id ~result-sym)]
|
|
246
|
+
(swap! ~'dbs assoc ~db-id-sym {:db ~result-sym :conn-id ~first-arg})
|
|
247
|
+
~db-id-sym)
|
|
248
|
+
|
|
249
|
+
;; Case: resolve conn, return value (transact, release)
|
|
250
|
+
(and resolves-conn? (= returns :value))
|
|
251
|
+
(let [call-expr (if variadic?
|
|
252
|
+
`(apply ~api-impl ~'conn ~@rest-named-args ~'rest-args)
|
|
253
|
+
`(~api-impl ~'conn ~@rest-named-args))
|
|
254
|
+
call-with-resolved `(let [~'conn (~'resolve-conn ~first-arg)
|
|
255
|
+
~result-sym ~call-expr]
|
|
256
|
+
~(wrap-with-transform transform result-sym))]
|
|
257
|
+
(if post-action
|
|
258
|
+
`(let [~'ret ~call-with-resolved]
|
|
259
|
+
~(case post-action
|
|
260
|
+
:remove-conn `(swap! ~'conns dissoc ~first-arg)
|
|
261
|
+
nil)
|
|
262
|
+
~'ret)
|
|
263
|
+
call-with-resolved))
|
|
264
|
+
|
|
265
|
+
;; Case: resolve db, return db-id (as-of, since, history, db-with)
|
|
266
|
+
(and resolves-db? (= returns :db-id))
|
|
267
|
+
(let [call-expr (if variadic?
|
|
268
|
+
`(apply ~api-impl ~'origin-db ~@rest-named-args ~'rest-args)
|
|
269
|
+
`(~api-impl ~'origin-db ~@rest-named-args))]
|
|
270
|
+
`(let [~'origin-db (~'resolve-db ~first-arg)
|
|
271
|
+
~'parent-conn-id (get-in @~'dbs [~first-arg :conn-id])
|
|
272
|
+
~result-sym ~call-expr
|
|
273
|
+
~db-id-sym (~'generate-db-id ~result-sym)]
|
|
274
|
+
(swap! ~'dbs assoc ~db-id-sym {:db ~result-sym :conn-id ~'parent-conn-id})
|
|
275
|
+
~db-id-sym))
|
|
276
|
+
|
|
277
|
+
;; Case: resolve db, return value (pull, entity, datoms, etc.)
|
|
278
|
+
(and resolves-db? (= returns :value))
|
|
279
|
+
(let [call-expr (if variadic?
|
|
280
|
+
`(apply ~api-impl ~'db ~@rest-named-args ~'rest-args)
|
|
281
|
+
`(~api-impl ~'db ~@rest-named-args))]
|
|
282
|
+
`(let [~'db (~'resolve-db ~first-arg)
|
|
283
|
+
~result-sym ~call-expr]
|
|
284
|
+
~(wrap-with-transform transform result-sym)))
|
|
285
|
+
|
|
286
|
+
;; Case: no resolution, return conn-id
|
|
287
|
+
(= returns :conn-id)
|
|
288
|
+
`(let [~result-sym ~(generate-api-call api-impl named-args variadic?)
|
|
289
|
+
~conn-id-sym (~'generate-conn-id ~(or first-arg {}))]
|
|
290
|
+
(swap! ~'conns assoc ~conn-id-sym ~result-sym)
|
|
291
|
+
~conn-id-sym)
|
|
292
|
+
|
|
293
|
+
;; Case: no resolution, return value (database-exists?, create-database, etc.)
|
|
294
|
+
:else
|
|
295
|
+
`(let [~result-sym ~(generate-api-call api-impl named-args variadic?)]
|
|
296
|
+
~(wrap-with-transform transform result-sym)))))
|
|
297
|
+
|
|
298
|
+
(defn generate-function
|
|
299
|
+
"Generate a complete pod function definition."
|
|
300
|
+
[op-name]
|
|
301
|
+
(let [spec (get api-specification op-name)
|
|
302
|
+
overlay (get pod-operations op-name)
|
|
303
|
+
custom-fn (:custom-fn overlay)]
|
|
304
|
+
|
|
305
|
+
(if custom-fn
|
|
306
|
+
;; Use custom function body from overlay
|
|
307
|
+
`(def ~op-name ~custom-fn)
|
|
308
|
+
|
|
309
|
+
;; Generate function from specification
|
|
310
|
+
(let [arities (extract-arities (:args spec))
|
|
311
|
+
api-impl (symbol "d" (name op-name))]
|
|
312
|
+
(if (= 1 (count arities))
|
|
313
|
+
;; Single arity
|
|
314
|
+
(let [arity-info (arity-arg-names (first arities))]
|
|
315
|
+
`(defn ~op-name ~(:args arity-info)
|
|
316
|
+
~(generate-arity-body op-name overlay arity-info api-impl)))
|
|
317
|
+
|
|
318
|
+
;; Multiple arities
|
|
319
|
+
`(defn ~op-name
|
|
320
|
+
~@(for [arity arities
|
|
321
|
+
:let [arity-info (arity-arg-names arity)]]
|
|
322
|
+
`(~(:args arity-info)
|
|
323
|
+
~(generate-arity-body op-name overlay arity-info api-impl)))))))))
|
|
324
|
+
|
|
325
|
+
;; =============================================================================
|
|
326
|
+
;; Describe Map Generation
|
|
327
|
+
;; =============================================================================
|
|
328
|
+
|
|
329
|
+
(defn first-sentence
|
|
330
|
+
"Extract first sentence from docstring."
|
|
331
|
+
[doc]
|
|
332
|
+
(when doc
|
|
333
|
+
(-> doc
|
|
334
|
+
(str/split #"\.\s")
|
|
335
|
+
first
|
|
336
|
+
(str "."))))
|
|
337
|
+
|
|
338
|
+
(defn generate-var-entry
|
|
339
|
+
"Generate a describe-map entry for an operation."
|
|
340
|
+
[op-name]
|
|
341
|
+
{"name" (name op-name)})
|
|
342
|
+
|
|
343
|
+
(defn generate-describe-map
|
|
344
|
+
"Generate the complete describe-map for pod protocol."
|
|
345
|
+
[]
|
|
346
|
+
(let [;; Operations from overlay
|
|
347
|
+
op-entries (for [op-name (keys pod-operations)]
|
|
348
|
+
(generate-var-entry op-name))
|
|
349
|
+
;; Pod additions
|
|
350
|
+
addition-entries (for [[op-name config] pod-additions]
|
|
351
|
+
{"name" (name op-name)})
|
|
352
|
+
;; with-db macro
|
|
353
|
+
macro-entry {"name" "with-db" "code" with-db-macro-code}]
|
|
354
|
+
(vec (concat op-entries addition-entries [macro-entry]))))
|
|
355
|
+
|
|
356
|
+
;; =============================================================================
|
|
357
|
+
;; Publics Map Generation
|
|
358
|
+
;; =============================================================================
|
|
359
|
+
|
|
360
|
+
(defn generate-publics-map
|
|
361
|
+
"Generate the publics lookup map."
|
|
362
|
+
[]
|
|
363
|
+
(let [ops (for [op-name (keys pod-operations)]
|
|
364
|
+
[(list 'quote op-name) op-name])
|
|
365
|
+
additions (for [[op-name _] pod-additions]
|
|
366
|
+
[(list 'quote op-name) op-name])]
|
|
367
|
+
`(def ~'publics
|
|
368
|
+
~(into {} (concat ops additions)))))
|
|
369
|
+
|
|
370
|
+
;; =============================================================================
|
|
371
|
+
;; Full Code Generation
|
|
372
|
+
;; =============================================================================
|
|
373
|
+
|
|
374
|
+
(defn generate-runtime-code
|
|
375
|
+
"Generate the pod runtime infrastructure code."
|
|
376
|
+
[]
|
|
377
|
+
'((def conns (atom {}))
|
|
378
|
+
(def dbs (atom {}))
|
|
379
|
+
|
|
380
|
+
(defn generate-conn-id [config]
|
|
381
|
+
(str "conn:" (hash config)))
|
|
382
|
+
|
|
383
|
+
(defn generate-db-id
|
|
384
|
+
"Generate a unique ID for a database snapshot.
|
|
385
|
+
Always creates a fresh ID to ensure speculative dbs (from db-with)
|
|
386
|
+
don't collide with their source dbs."
|
|
387
|
+
[db]
|
|
388
|
+
(str (datahike.writing/create-commit-id db)))
|
|
389
|
+
|
|
390
|
+
(defn resolve-conn [conn-id]
|
|
391
|
+
(or (get @conns conn-id)
|
|
392
|
+
(throw (ex-info "Connection not found" {:conn-id conn-id}))))
|
|
393
|
+
|
|
394
|
+
(defn resolve-db [db-id]
|
|
395
|
+
(or (get-in @dbs [db-id :db])
|
|
396
|
+
(throw (ex-info "Database not found" {:db-id db-id}))))
|
|
397
|
+
|
|
398
|
+
(defn release-db [db-id]
|
|
399
|
+
(swap! dbs dissoc db-id)
|
|
400
|
+
{})))
|
|
401
|
+
|
|
402
|
+
(defn generate-all-functions
|
|
403
|
+
"Generate all pod function definitions."
|
|
404
|
+
[]
|
|
405
|
+
(for [op-name (keys pod-operations)]
|
|
406
|
+
(generate-function op-name)))
|
|
407
|
+
|
|
408
|
+
(defn generate-pod-namespace
|
|
409
|
+
"Generate the complete pod namespace code."
|
|
410
|
+
[]
|
|
411
|
+
(let [runtime (generate-runtime-code)
|
|
412
|
+
functions (generate-all-functions)
|
|
413
|
+
publics (generate-publics-map)
|
|
414
|
+
describe-map `(def ~'describe-map ~(generate-describe-map))]
|
|
415
|
+
{:runtime runtime
|
|
416
|
+
:functions functions
|
|
417
|
+
:publics publics
|
|
418
|
+
:describe-map describe-map}))
|
|
419
|
+
|
|
420
|
+
;; =============================================================================
|
|
421
|
+
;; Validation
|
|
422
|
+
;; =============================================================================
|
|
423
|
+
|
|
424
|
+
(defn validate-coverage
|
|
425
|
+
"Validate that all API operations are either implemented or excluded."
|
|
426
|
+
[]
|
|
427
|
+
(let [all-ops (set (keys api-specification))
|
|
428
|
+
implemented (set (keys pod-operations))
|
|
429
|
+
excluded (set (keys pod-excluded-operations))
|
|
430
|
+
covered (set/union implemented excluded)
|
|
431
|
+
missing (set/difference all-ops covered)]
|
|
432
|
+
(when (seq missing)
|
|
433
|
+
(println "WARNING: Operations missing from pod overlay:")
|
|
434
|
+
(doseq [op missing]
|
|
435
|
+
(println " -" op)))
|
|
436
|
+
(empty? missing)))
|
|
437
|
+
|
|
438
|
+
;; =============================================================================
|
|
439
|
+
;; Debug / Development
|
|
440
|
+
;; =============================================================================
|
|
441
|
+
|
|
442
|
+
(defn print-generated-function
|
|
443
|
+
"Print generated code for a single function (for debugging)."
|
|
444
|
+
[op-name]
|
|
445
|
+
(clojure.pprint/pprint (generate-function op-name)))
|
|
446
|
+
|
|
447
|
+
(defn print-all-generated
|
|
448
|
+
"Print all generated code (for debugging)."
|
|
449
|
+
[]
|
|
450
|
+
(let [{:keys [runtime functions publics describe-map]} (generate-pod-namespace)]
|
|
451
|
+
(println ";; Runtime")
|
|
452
|
+
(doseq [form runtime]
|
|
453
|
+
(clojure.pprint/pprint form)
|
|
454
|
+
(println))
|
|
455
|
+
(println "\n;; Functions")
|
|
456
|
+
(doseq [form functions]
|
|
457
|
+
(clojure.pprint/pprint form)
|
|
458
|
+
(println))
|
|
459
|
+
(println "\n;; Publics")
|
|
460
|
+
(clojure.pprint/pprint publics)
|
|
461
|
+
(println "\n;; Describe Map")
|
|
462
|
+
(clojure.pprint/pprint describe-map)))
|
|
463
|
+
|
|
464
|
+
;; =============================================================================
|
|
465
|
+
;; Compile-Time Code Generation Macros
|
|
466
|
+
;; =============================================================================
|
|
467
|
+
|
|
468
|
+
(defmacro defpod-runtime
|
|
469
|
+
"Generate pod runtime infrastructure (atoms, helper functions)."
|
|
470
|
+
[]
|
|
471
|
+
`(do
|
|
472
|
+
~@(generate-runtime-code)))
|
|
473
|
+
|
|
474
|
+
(defmacro defpod-functions
|
|
475
|
+
"Generate all pod API functions from the overlay specification."
|
|
476
|
+
[]
|
|
477
|
+
`(do
|
|
478
|
+
~@(generate-all-functions)))
|
|
479
|
+
|
|
480
|
+
(defmacro defpod-publics
|
|
481
|
+
"Generate the publics map for pod protocol lookup."
|
|
482
|
+
[]
|
|
483
|
+
(generate-publics-map))
|
|
484
|
+
|
|
485
|
+
(defmacro defpod-describe-map
|
|
486
|
+
"Generate the describe-map for pod protocol."
|
|
487
|
+
[]
|
|
488
|
+
`(def ~'describe-map ~(generate-describe-map)))
|