{"id":20023304,"url":"https://github.com/wandersoncferreira/meta-schema","last_synced_at":"2025-05-05T02:30:37.873Z","repository":{"id":57716759,"uuid":"235020743","full_name":"wandersoncferreira/meta-schema","owner":"wandersoncferreira","description":"Little DSL to make data processing sane with clojure.spec and spec-tools","archived":false,"fork":false,"pushed_at":"2020-02-03T14:18:53.000Z","size":61,"stargazers_count":26,"open_issues_count":5,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-26T12:41:14.992Z","etag":null,"topics":["clojure","clojure-spec","data-processing","dsl","edn","spec"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wandersoncferreira.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2020-01-20T04:46:27.000Z","updated_at":"2023-07-29T06:29:08.000Z","dependencies_parsed_at":"2022-08-24T01:50:52.002Z","dependency_job_id":null,"html_url":"https://github.com/wandersoncferreira/meta-schema","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wandersoncferreira%2Fmeta-schema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wandersoncferreira%2Fmeta-schema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wandersoncferreira%2Fmeta-schema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wandersoncferreira%2Fmeta-schema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wandersoncferreira","download_url":"https://codeload.github.com/wandersoncferreira/meta-schema/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252427621,"owners_count":21746247,"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","clojure-spec","data-processing","dsl","edn","spec"],"created_at":"2024-11-13T08:45:55.631Z","updated_at":"2025-05-05T02:30:37.543Z","avatar_url":"https://github.com/wandersoncferreira.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# meta-schema [![Build Status](https://travis-ci.org/wandersoncferreira/meta-schema.svg?branch=master)](https://travis-ci.org/wandersoncferreira/meta-schema) [![Coverage Status](https://coveralls.io/repos/github/wandersoncferreira/meta-schema/badge.svg?branch=feature/setup-travis)](https://coveralls.io/github/wandersoncferreira/meta-schema?branch=feature/setup-travis)\n\n[![Clojars Project](https://img.shields.io/clojars/v/meta-schema.svg)](https://clojars.org/meta-schema)\n\n\nDesigned to help data processing using `clojure.spec`.\n\nProvide users the ability to combine several pre-defined\n`clojure.spec` into some specific shape at *runtime*.\n\n\nFor now, it only supports JSON files. This library is in\nalpha-stage, still needs many test cases and refactors,\nalthough the Public API **must** not change.\n\n## Installation\n\nLeiningen/Boot\n\n```clj\n[meta-schema \"0.1.4\"]\n```\n\nClojure CLI/deps.edn\n```clj\nmeta-schema {:mvn/version \"0.1.4\"}\n```\n\n## Usage\n\nIn your project you need to define EDN files inside a folder\nand provide a list of `java.io.File`s to the `(setup!  ..)`\nfunction. These files are simple and provides the location\nand intent of your pre-defined specs.\n\n```clj\n{:zipcode {:intent \"Validation to ZipCodes in Brazil\"\n           :location :my-project.spec/zipcode-br}\n :money {:intent \"How we understand money around here? Anything \u003e= 0 either long, float, double, or decimal\"\n         :location :my-project.other-spec/money-br}\n}\n```\n\nMake sure that all this namespaces are loaded before invoke\n`meta-schema.core/setup!`.\n\n\nExample of specification provided to the library at runtime.\n\n```clj\n  (require '[meta-schema.core :as ms])\n  (require '[clojure.alpha.spec :as s])\n  (require '[clojure.java.io :as io])\n\n  (ms/setup! (-\u003e (io/resources \"specs\")\n                 (io/file)\n                 (file-seq)))\n\n  (def file-spec {:spec-name :my-project.client/payload\n                  :zip [{:spec :zipcode\n                         :optional? false\n                         :nullable? false}\n\n                        {:house-price {:spec :money\n                                       :nullable? true}}]\n\n                  :rent {:spec :money\n                         :optional? false\n                         :nullable? false}\n\n                  :university {:departments [{:zip {:address {:spec :zipcode\n                                                              :optional? false}}}]}})\n\n  (def my-parser (ms/create-parser file-spec))\n\n  (def my-data-1 {:zip [\"my zipcode is text\"]\n                  :rent 10\n                  :university {:departments [{:zip {:address \"deep structures\"}}]}})\n\n  (s/valid? my-parser my-data-1) ;; =\u003e true\n\n  (s/valid? my-parser {:zip [{:house-price 230} \"either or both here..\"]\n                       :rent 10\n                       :university {:departments [{:zip {:address \"deep structures\"}}]}}) ;; =\u003e true\n\n```\n\nCool, now we can finally finish the example above. Let's say your source code only understands a specific `target-fmt` of MAP that can be processed. For sure, your clients does not want to send you that format, right? Because they can't change legacy systems and make something better to help everybody. That's ok!\n\n```clj\n  (def client-data {:zip [\"101030-201\", \"987621-281\"]\n                    :rent 980.322\n                    :university {:departments [{:zip {:address \"University at Medium Inc.,\"}}]}})\n\n  (def client-spec {:spec-name :my-project.client/payload\n                    :zip [{:spec :zipcode\n                           :destination :zipcode}]\n\n                    :rent {:spec :money\n                           :destination :value}\n\n                    :university {:departments [{:zip {:address {:spec :zipcode\n                                                                :destination :university-address}}}]}})\n\n  (def target-fmt {:my-internal-zipcode :zipcode\n                   :my-internal-value   :value\n                   :my-internal-address :university-address})\n\n  (setup! (-\u003e (io/resource \"specs\")\n              (io/file)\n              (file-seq)))\n\n  (input-data-\u003etarget-data client-data client-spec target-fmt)\n\n  ;; =\u003e {:my-internal-zipcode [\"101030-201\" \"987621-281\"],\n  ;;     :my-internal-value 980.322,\n  ;;     :my-internal-address \"University at Medium Inc.,\"}\n```\n\nThe clojure.spec to validate the data is created at runtime\nand applied to the provided data. If it passes, we start the\ntransformation to the `target-shape` specified.\n\n## Rationale\n\nThe DSL is simple:\n\n1. When the field is a list, more than one spec inside it will produce a `or` operator\n2. When the field is `optional`, it means that  may or may not be present at coersion time\n3. When the field is `nullable`, it means that `nil` is a valid input.\n4. By default all the fields are *not* nullable and *not* optionals.\n5. You can nest the options as you desired\n\n\n## TODO list\n\n- [x] Finish the second part of the library, `input-data-\u003etarget-data` conversions\n- [x] Improve interfaces of public API\n- [ ] Write a parser to spec the DSL in the input-file\n- [ ] Provide support for `sets` and `enums` (?)\n- [ ] Extend it to XML\n\n## License\n\nCopyright © 2020 Wanderson Ferreira (@bartuka)\n\nThis program and the accompanying materials are made available under the\nterms of the Eclipse Public License 2.0 which is available at\nhttp://www.eclipse.org/legal/epl-2.0.\n\nThis Source Code may also be made available under the following Secondary\nLicenses when the conditions for such availability set forth in the Eclipse\nPublic License, v. 2.0 are satisfied: GNU General Public License as published by\nthe Free Software Foundation, either version 2 of the License, or (at your\noption) any later version, with the GNU Classpath Exception which is available\nat https://www.gnu.org/software/classpath/license.html.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwandersoncferreira%2Fmeta-schema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwandersoncferreira%2Fmeta-schema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwandersoncferreira%2Fmeta-schema/lists"}