All Projects → wandersoncferreira → meta-schema

wandersoncferreira / meta-schema

Licence: EPL-2.0 license
Little DSL to make data processing sane with clojure.spec and spec-tools

Programming Languages

clojure
4091 projects
shell
77523 projects

Projects that are alternatives of or similar to meta-schema

cq
Clojure Command-line Data Processor for JSON, YAML, EDN, XML and more
Stars: ✭ 111 (+344%)
Mutual labels:  data-processing, edn
wdio-spec-reporter
A WebdriverIO v4 plugin. Reporter that creates 'spec'-style reports
Stars: ✭ 20 (-20%)
Mutual labels:  spec
Anatomy-of-System-Engineering
System Engineering Memory Map
Stars: ✭ 17 (-32%)
Mutual labels:  data-processing
spartan.spec
A spartan version of clojure.spec compatible with babashka
Stars: ✭ 29 (+16%)
Mutual labels:  clojure-spec
clausejs
Write contract once. Get data & function validators & conformers, an accurate & readable project contract, auto-generated API documentation, generative test coverage, plus more. A tool that enables a more predictable workflow for developing your JavaScript projects.
Stars: ✭ 29 (+16%)
Mutual labels:  clojure-spec
mech
🦾 Main repository for the Mech programming language. Start here!
Stars: ✭ 135 (+440%)
Mutual labels:  data-processing
ECG analysis
No description or website provided.
Stars: ✭ 32 (+28%)
Mutual labels:  data-processing
sparklanes
A lightweight data processing framework for Apache Spark
Stars: ✭ 17 (-32%)
Mutual labels:  data-processing
edamame
Configurable EDN/Clojure parser with location metadata
Stars: ✭ 129 (+416%)
Mutual labels:  edn
stargate
An Apache Pulsar client written in Elixir
Stars: ✭ 33 (+32%)
Mutual labels:  data-processing
lines
A pure bash clojureish CI pipeline
Stars: ✭ 72 (+188%)
Mutual labels:  edn
dataset
qri dataset definition
Stars: ✭ 16 (-36%)
Mutual labels:  spec
Speech-Recognition
End-to-end Automatic Speech Recognition for Madarian and English in Tensorflow
Stars: ✭ 21 (-16%)
Mutual labels:  data-processing
rewrite-edn
Utility lib on top of rewrite-clj with common operations to update EDN while preserving whitespace and comments.
Stars: ✭ 65 (+160%)
Mutual labels:  edn
advent-of-cljc
Cross platform Clojure Advent of Code solutions
Stars: ✭ 44 (+76%)
Mutual labels:  clojure-spec
defn-spec
Define Clojure specs inline with your function definitions
Stars: ✭ 67 (+168%)
Mutual labels:  clojure-spec
traceml
Engine for ML/Data tracking, visualization, dashboards, and model UI for Polyaxon.
Stars: ✭ 445 (+1680%)
Mutual labels:  data-processing
pyGAPS
A framework for processing adsorption data and isotherm fitting
Stars: ✭ 36 (+44%)
Mutual labels:  data-processing
bonobo-sqlalchemy
PREVIEW - SQL databases in Bonobo, using sqlalchemy
Stars: ✭ 23 (-8%)
Mutual labels:  data-processing
falcon-apispec
apispec plugin that generates OpenAPI specification (aka Swagger Docs) for Falcon web applications.
Stars: ✭ 44 (+76%)
Mutual labels:  spec

meta-schema Build Status Coverage Status

Clojars Project

Designed to help data processing using clojure.spec.

Provide users the ability to combine several pre-defined clojure.spec into some specific shape at runtime.

For now, it only supports JSON files. This library is in alpha-stage, still needs many test cases and refactors, although the Public API must not change.

Installation

Leiningen/Boot

[meta-schema "0.1.4"]

Clojure CLI/deps.edn

meta-schema {:mvn/version "0.1.4"}

Usage

In your project you need to define EDN files inside a folder and provide a list of java.io.Files to the (setup! ..) function. These files are simple and provides the location and intent of your pre-defined specs.

{:zipcode {:intent "Validation to ZipCodes in Brazil"
           :location :my-project.spec/zipcode-br}
 :money {:intent "How we understand money around here? Anything >= 0 either long, float, double, or decimal"
         :location :my-project.other-spec/money-br}
}

Make sure that all this namespaces are loaded before invoke meta-schema.core/setup!.

Example of specification provided to the library at runtime.

  (require '[meta-schema.core :as ms])
  (require '[clojure.alpha.spec :as s])
  (require '[clojure.java.io :as io])

  (ms/setup! (-> (io/resources "specs")
                 (io/file)
                 (file-seq)))

  (def file-spec {:spec-name :my-project.client/payload
                  :zip [{:spec :zipcode
                         :optional? false
                         :nullable? false}

                        {:house-price {:spec :money
                                       :nullable? true}}]

                  :rent {:spec :money
                         :optional? false
                         :nullable? false}

                  :university {:departments [{:zip {:address {:spec :zipcode
                                                              :optional? false}}}]}})

  (def my-parser (ms/create-parser file-spec))

  (def my-data-1 {:zip ["my zipcode is text"]
                  :rent 10
                  :university {:departments [{:zip {:address "deep structures"}}]}})

  (s/valid? my-parser my-data-1) ;; => true

  (s/valid? my-parser {:zip [{:house-price 230} "either or both here.."]
                       :rent 10
                       :university {:departments [{:zip {:address "deep structures"}}]}}) ;; => true

Cool, 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!

  (def client-data {:zip ["101030-201", "987621-281"]
                    :rent 980.322
                    :university {:departments [{:zip {:address "University at Medium Inc.,"}}]}})

  (def client-spec {:spec-name :my-project.client/payload
                    :zip [{:spec :zipcode
                           :destination :zipcode}]

                    :rent {:spec :money
                           :destination :value}

                    :university {:departments [{:zip {:address {:spec :zipcode
                                                                :destination :university-address}}}]}})

  (def target-fmt {:my-internal-zipcode :zipcode
                   :my-internal-value   :value
                   :my-internal-address :university-address})

  (setup! (-> (io/resource "specs")
              (io/file)
              (file-seq)))

  (input-data->target-data client-data client-spec target-fmt)

  ;; => {:my-internal-zipcode ["101030-201" "987621-281"],
  ;;     :my-internal-value 980.322,
  ;;     :my-internal-address "University at Medium Inc.,"}

The clojure.spec to validate the data is created at runtime and applied to the provided data. If it passes, we start the transformation to the target-shape specified.

Rationale

The DSL is simple:

  1. When the field is a list, more than one spec inside it will produce a or operator
  2. When the field is optional, it means that may or may not be present at coersion time
  3. When the field is nullable, it means that nil is a valid input.
  4. By default all the fields are not nullable and not optionals.
  5. You can nest the options as you desired

TODO list

  • Finish the second part of the library, input-data->target-data conversions
  • Improve interfaces of public API
  • Write a parser to spec the DSL in the input-file
  • Provide support for sets and enums (?)
  • Extend it to XML

License

Copyright © 2020 Wanderson Ferreira (@bartuka)

This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.

This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].