{"id":21734081,"url":"https://github.com/hodur-org/hodur-datomic-schema","last_synced_at":"2025-12-12T01:32:32.893Z","repository":{"id":62432914,"uuid":"143537454","full_name":"hodur-org/hodur-datomic-schema","owner":"hodur-org","description":"Hodur is a domain modeling approach and collection of libraries to Clojure.  By using Hodur you can define your domain model as data, parse and validate it, and then either consume your model via an API or use one of the many plugins to help you achieve mechanical results faster and in a purely functional manner.","archived":false,"fork":false,"pushed_at":"2022-01-20T02:15:10.000Z","size":110,"stargazers_count":32,"open_issues_count":2,"forks_count":9,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-10T17:14:23.516Z","etag":null,"topics":["clojure","data","database","datomic","modeling","schema"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hodur-org.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-04T14:50:19.000Z","updated_at":"2024-10-22T18:31:25.000Z","dependencies_parsed_at":"2022-11-01T20:47:17.236Z","dependency_job_id":null,"html_url":"https://github.com/hodur-org/hodur-datomic-schema","commit_stats":null,"previous_names":["luchiniatwork/hodur-datomic-schema"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hodur-org%2Fhodur-datomic-schema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hodur-org%2Fhodur-datomic-schema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hodur-org%2Fhodur-datomic-schema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hodur-org%2Fhodur-datomic-schema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hodur-org","download_url":"https://codeload.github.com/hodur-org/hodur-datomic-schema/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654045,"owners_count":21140236,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","data","database","datomic","modeling","schema"],"created_at":"2024-11-26T05:07:44.387Z","updated_at":"2025-12-12T01:32:32.819Z","avatar_url":"https://github.com/hodur-org.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"[ci-badge]: https://github.com/hodur-org/hodur-datomic-schema/actions/workflows/test.yml/badge.svg\n[ci-link]: https://github.com/hodur-org/hodur-datomic-schema/actions/workflows/test.yml\n[clojars-badge]: https://img.shields.io/clojars/v/hodur/datomic-schema.svg\n[clojars]: http://clojars.org/hodur/datomic-schema\n[datomic]: https://docs.datomic.com/\n[github-issues]: https://github.com/hodur-org/hodur-datomic-schema/issues\n[hodur-engine]: https://github.com/hodur-org/hodur-engine\n[hodur-engine-clojars-badge]: https://img.shields.io/clojars/v/hodur/engine.svg\n[hodur-engine-clojars]: http://clojars.org/hodur/engine\n[hodur-engine-definition]: https://github.com/hodur-org/hodur-engine#model-definition\n[hodur-engine-started]: https://github.com/hodur-org/hodur-engine#getting-started\n[license-badge]: https://img.shields.io/badge/license-MIT-blue.svg\n[license]: ./LICENSE\n[logo]: ./docs/logo-tag-line.png\n[motivation]: https://github.com/hodur-org/hodur-engine/blob/master/docs/MOTIVATION.org\n[plugins]: https://github.com/hodur-org/hodur-engine#hodur-plugins\n[status-badge]: https://img.shields.io/badge/project%20status-beta-brightgreen.svg\n\n# Hodur Datomic Schema\n\n[![CI][ci-badge]][ci-link]\n[![Clojars][hodur-engine-clojars-badge]][hodur-engine-clojars]\n[![Clojars][clojars-badge]][clojars]\n[![License][license-badge]][license]\n![Status][status-badge]\n\n![Logo][logo]\n\nHodur is a descriptive domain modeling approach and related collection\nof libraries for Clojure.\n\nBy using Hodur you can define your domain model as data, parse and\nvalidate it, and then either consume your model via an API making your\napps respond to the defined model or use one of the many plugins to\nhelp you achieve mechanical, repetitive results faster and in a purely\nfunctional manner.\n\n\u003e This repo is the Datomic schema plugin that leverages Hodur models\n\u003e as Datomic schemas.  For a list of what you can do once your model\n\u003e is in Hodur [check here][plugins].\n\n## Motivation\n\nFor a deeper insight into the motivations behind Hodur, check the\n[motivation doc][motivation].\n\n## Getting Started\n\nHodur has a highly modular architecture. [Hodur Engine][hodur-engine]\nis always required as it provides the meta-database functions and APIs\nconsumed by plugins.\n\nTherefore, refer the [Hodur Engine's Getting\nStarted][hodur-engine-started] first and then return here for\nDatomic-specific setup.\n\nAfter having set up `hodur-engine` as described above, we also need to\nadd `hodur/datomic-schema`, a plugin that creates Datomic Schemas out\nof your model to the `deps.edn` file:\n\n``` clojure\n  {:deps {hodur/engine         {:mvn/version \"0.1.9\"}\n          hodur/datomic-schema {:mvn/version \"0.1.1\"}}}\n```\n\nYou should `require` it any way you see fit:\n\n``` clojure\n  (require '[hodur-datomic-schema.core :as hodur-datomic])\n```\n\nLet's expand our `Person` model above by \"tagging\" the `Person` entity\nfor Datomic. You can read more about the concept of tagging for\nplugins in the sessions below but, in short, this is the way we, model\ndesigners, use to specify which entities we want to be exposed to\nwhich plugins.\n\n``` clojure\n  (def meta-db (hodur/init-schema\n                '[^{:datomic/tag-recursive true}\n                  Person\n                  [^String first-name\n                   ^String last-name]]))\n```\n\nThe `hodur-datomic-schema` plugin exposes a function called `schema`\nthat generates your model as a Datomic schema payload:\n\n``` clojure\n  (def datomic-schema (hodur-datomic/schema meta-db))\n```\n\nWhen you inspect `datomic-schema`, this is what you have:\n\n``` clojure\n  [{:db/ident       :person/first-name\n    :db/valueType   :db.type/string\n    :db/cardinality :db.cardinality/one}\n   {:db/ident       :person/last-name\n    :db/valueType   :db.type/string\n    :db/cardinality :db.cardinality/one}]\n```\n\nAssuming the Datomic client API is bound to `datomic`, and your\nconnection to the Database cluster is bound to `db-conn`, you can\nsimply transact your schema like this:\n\n``` clojure\n  (datomic/transact db-conn {:tx-data datomic-schema})\n```\n\n## Model Definition\n\nAll Hodur plugins follow the [Model\nDefinition][hodur-engine-definition] as described on Hodur [Engine's\ndocumentation][hodur-engine].\n\n## Attribute Naming Convention\n\nDatomic's foundational modeling unit is the atom. An atom is the\nrelationship between an Entity, an Attribute, its Value, and the Time\nat which the combination was valid.\n\nWith such an approach, Datomic attributes become central to the\nmodeling effort and Hodur takes advantage of that.\n\nA Datomic attribute such as `:person/name` will be defined in Hodur as\nthe `name` attribute of the `Person` entity:\n\n``` clojure\n  [Person\n   [^String name]]\n```\n\nIn the example above we are describing the Datomic attribute\n`:person/name` a little more than just by giving its name. By tagging\nit as a `String`, the schema generator understands the above as:\n\n``` clojure\n  [{:db/ident :person/name\n    :db/valueType :db.type/string\n    :db/cardinality :db.cardinality/one}]\n```\n\nAll naming conversions by this plugin are for a kebab-cased approach.\n\n## Attribute Properties\n\nDatomic attributes can have a series of properties. In order to\nutilize them simple mark the Hodur attribute as described in the table\nbelow:\n\n| Hodur marker           | Datomic equivalent | Notes                                       |\n|------------------------|--------------------|---------------------------------------------|\n| `:datomic/unique`      | `:db/unique`       | `:db.unique/identity` or `:db.unique/value` |\n| `:datomic/index`       | `:db/index`        | `true` or `false` (default)                 |\n| `:datomic/fulltext`    | `:db/fulltext`     | `true` or `false` (default)                 |\n| `:datomic/isComponent` | `:db/isComponent`  | `true` or `false` (default)                 |\n| `:datomic/noHistory`   | `:db/noHistory`    | `true` or `false` (default)                 |\n\nYou can find more details about each of these on the [Datomic\ndocumentation][datomic]. Do be aware that the modeling options are\nslightly different between Datomic Cloud and Datomic On-Prem.\n\n## Scalar Types and Finer Grained Control\n\nThe table below shows how Hodur's primitive scalar types are mapped by\ndefault to Datomic scalar types:\n\n| Hodur Scalar | Datomic Scalar     |\n|--------------|--------------------|\n| `String`     | `:db.type/string`  |\n| `Float`      | `:db.type/float`   |\n| `Integer`    | `:db.type/long`    |\n| `Boolean`    | `:db.type/boolean` |\n| `DateTime`   | `:db.type/instant` |\n| `ID`         | `:db.type/uuid`    |\n\nIf you need to have access to specific types you can override Hodur's\nautomatic behavior by using the marker `:datomic/type`:\n\n``` clojure\n  [ExampleEntity\n   [^{:datomic/type :db.type/keyword}\n    keyword-type\n    ^{:datomic/type :db.type/uri}\n    uri-type\n    ^{:datomic/type :db.type/double}\n    double-type\n    ^{:datomic/type :db.type/bigdec}\n    bigdec-type\n    ^{:datomic/type :db.type/tuple\n      :datomic/tupleAttrs [keyword-type uri-type]} composite+tuple]]\n```\n\nEach of the attributes above are now using Datomic-specific\nscalars. The schema below is a result of the definition above:\n\n``` clojure\n  [{:db/ident       :example-entity/bigdec-type\n    :db/valueType   :db.type/bigdec\n    :db/cardinality :db.cardinality/one}\n   {:db/ident       :example-entity/composite+tuple\n    :db/valueType   :db.type/tuple\n    :db/cardinality :db.cardinality/one\n    :db/tupleAttrs  [:example-entity/keyword-type :example-entity/uri-type]}\n   {:db/ident       :example-entity/double-type\n    :db/valueType   :db.type/double,\n    :db/cardinality :db.cardinality/one}\n   {:db/ident       :example-entity/keyword-type\n    :db/valueType   :db.type/keyword\n    :db/cardinality :db.cardinality/one}\n   {:db/ident       :example-entity/uri-type\n    :db/valueType   :db.type/uri\n    :db/cardinality :db.cardinality/one}]\n```\n\n## Cardinality\n\nThe `:cardinality` marker is respected by Hodur Datomic Schema in\nrelation to `one` vs. `many`. Datomic does not have the finer control\nthat Hodur has so the plugin simply converts cardinalities to either\n`:db.cardinality/one` or `:db.cardinality/many`.\n\nIn the example below the attribute `supervisor` has a cardinality of 1\nto an `Employee` while the attribute `co-workers` has a complex\ncardinality of `0` to `n` to potentially many `Employee`:\n\n``` clojure\n  [Employee\n   [^String name\n    ^Employee supervisor\n    ^{:type Employee\n      :cardinality [0 n]}\n    co-workers]]\n```\n\nHodur will infer that:\n\n- `:employee/supervisor` is a `:db.type/ref` of `:db.cardinality/one`\n- `:employee/co-workers` is a `:db.type/ref` of `:db.cardinality/many`\n\nThe above definition leads to:\n\n``` clojure\n  [{:db/ident       :employee/co-workers,\n    :db/valueType   :db.type/ref,\n    :db/cardinality :db.cardinality/many}\n   {:db/ident       :employee/name,\n    :db/valueType   :db.type/string,\n    :db/cardinality :db.cardinality/one}\n   {:db/ident       :employee/supervisor,\n    :db/valueType   :db.type/ref,\n    :db/cardinality :db.cardinality/one}]\n```\n\n## Special Treatments\n\n### Interfaces and Unions\n\nInterfaces proper do not exist in Datomic so they are ignored in\nHodur's Datomic plugin.\n\nUnions are also do not exist in Datomic per se. Hodur's Datomic plugin\nalso ignores them. However, they can be emulated by the resulting\nDatomic schema. Datomic's `:db.type/ref` will be used if you specify a\nunion. Therefore, it is possible to relate that attribute to any kind\nof Datomic entity. Of course, this wouldn't respect the boundaries of\nthe union you specified but, if you really need unions, that's a way\nto go about it.\n\n### Enums\n\nThe traditional way to use enums in Datomic is to create one\n`:db/ident` for each option.\n\nThis is the route that Hodur takes then. Example:\n\n``` clojure\n  [Person\n   [^String name\n    ^Gender gender]\n\n   ^:enum\n   Gender\n   [MALE FEMALE PREFER_NOT_TO_REPORT]]\n```\n\nThis is also a good example of how naming conventions are used:\n\n``` clojure\n  [{:db/ident :gender/female}\n   {:db/ident :gender/male}\n   {:db/ident :gender/prefer-not-to-report}\n   {:db/ident :person/gender\n    :db/valueType :db.type/ref\n    :db/cardinality :db.cardinality/one}\n   {:db/ident :person/name\n    :db/valueType :db.type/string\n    :db/cardinality :db.cardinality/one}]\n```\n\n### Parameters\n\nField parameters do not exist on Datomic so they are ignored.\n\n## Documentation and Deprecation\n\nBecause of Datomic's central modeling around attributes, only field\ndocumentation and deprecation is parsed. Enum entries can also be\ndocumented/deprecated as they are considered fields in Hodur.\n\nAll fields marked with `:doc` will immediately get a `:db/doc` entry\nin their Datomic schema definition.\n\nIf a field is marked as deprecated with `:deprecation` a deprecation\nnote is added to Datomic's `:db/doc` entry.\n\n## Bugs\n\nIf you find a bug, submit a [GitHub issue][github-issues].\n\n## Help!\n\nThis project is looking for team members who can help this project\nsucceed! If you are interested in becoming a team member please open\nan issue.\n\n## License\n\nCopyright © 2019 Tiago Luchini\n\nDistributed under the MIT License (see [LICENSE][license]).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhodur-org%2Fhodur-datomic-schema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhodur-org%2Fhodur-datomic-schema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhodur-org%2Fhodur-datomic-schema/lists"}