All Projects → hodur-org → hodur-lacinia-schema

hodur-org / hodur-lacinia-schema

Licence: MIT license
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.

Programming Languages

clojure
4091 projects

Projects that are alternatives of or similar to hodur-lacinia-schema

hodur-visualizer-schema
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.
Stars: ✭ 16 (-20%)
Mutual labels:  schema, modeling
Hodur Engine
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.
Stars: ✭ 208 (+940%)
Mutual labels:  schema, modeling
mixedvines
Python package for canonical vine copula trees with mixed continuous and discrete marginals
Stars: ✭ 36 (+80%)
Mutual labels:  modeling
storage
Mongoose-like schema validation, collections and documents on browser (client-side)
Stars: ✭ 17 (-15%)
Mutual labels:  schema
graphql-directive-sql
Unify your SQL schema and your GraphQL Schema. Use GraphQL SDL as the lingua franca to define your data requirements.
Stars: ✭ 28 (+40%)
Mutual labels:  schema
vs-code-bpmn-io
Edit BPMN 2.0 files. Based on bpmn.io tools.
Stars: ✭ 87 (+335%)
Mutual labels:  modeling
querymen
Querystring parser middleware for MongoDB, Express and Nodejs (MEN)
Stars: ✭ 128 (+540%)
Mutual labels:  schema
lc-spring-data-r2dbc
An extension of spring-data-r2dbc to provide features such as relationships, joins, cascading save/delete, lazy loading, sequence, schema generation, composite id
Stars: ✭ 30 (+50%)
Mutual labels:  schema
DSTC6-End-to-End-Conversation-Modeling
DSTC6: End-to-End Conversation Modeling Track
Stars: ✭ 56 (+180%)
Mutual labels:  modeling
sf-java-ui
Json Schema Form java based library allow developers to define schema and form using field annotations
Stars: ✭ 23 (+15%)
Mutual labels:  schema
cassandra-migration
Apache Cassandra / DataStax Enterprise database migration (schema evolution) library
Stars: ✭ 51 (+155%)
Mutual labels:  schema
schema-builder
Laravel/Lumen schema builder & migration generator
Stars: ✭ 51 (+155%)
Mutual labels:  schema
element-schema-form
A schema-based element-ui form component for Vue2.x.
Stars: ✭ 31 (+55%)
Mutual labels:  schema
to-json-schema
Converts JS objects to JSON Schema
Stars: ✭ 83 (+315%)
Mutual labels:  schema
albion
Migrated to: https://gitlab.com/Oslandia/albion
Stars: ✭ 47 (+135%)
Mutual labels:  modeling
hcl-lang
Schema and decoder to be used as building blocks for an HCL2-based language server.
Stars: ✭ 44 (+120%)
Mutual labels:  schema
SICP
✨practice for SICP, the wizard book < Structure and Interpretation of Computer Programs >
Stars: ✭ 89 (+345%)
Mutual labels:  schema
computational-neuroscience
Short undergraduate course taught at University of Pennsylvania on computational and theoretical neuroscience. Provides an introduction to programming in MATLAB, single-neuron models, ion channel models, basic neural networks, and neural decoding.
Stars: ✭ 36 (+80%)
Mutual labels:  modeling
Mail
RiiConnect24 Mail Scripts. OSS.
Stars: ✭ 11 (-45%)
Mutual labels:  schema
spark-hats
Nested array transformation helper extensions for Apache Spark
Stars: ✭ 21 (+5%)
Mutual labels:  schema

Hodur Lacinia Schema

CI Clojars Clojars License Status

Logo

Hodur is a descriptive domain modeling approach and related collection of libraries for 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 making your apps respond to the defined model or use one of the many plugins to help you achieve mechanical, repetitive results faster and in a purely functional manner.

This Hodur plugin provides the ability to generate Lacinia schemas out of your Hodur model. Lacinia will let you spin off a GraphQL server in minutes.

Motivation

For a deeper insight into the motivations behind Hodur, check the motivation doc.

Getting Started

Hodur has a highly modular architecture. Hodur Engine is always required as it provides the meta-database functions and APIs consumed by plugins.

Therefore, refer the Hodur Engine's Getting Started first and then return here for Datomic-specific setup.

After having set up hodur-engine as described above, we also need to add hodur/lacinia-schema, a plugin that creates Lacinia Schemas out of your model to the deps.edn file:

  {:deps {hodur/engine         {:mvn/version "0.1.9"}
          hodur/lacinia-schema {:mvn/version "0.2.1"}}}

You should require it any way you see fit:

  (require '[hodur-engine.core :as hodur])
  (require '[hodur-lacinia-schema.core :as hodur-lacinia])

Let's expand our Person model from the original getting started by "tagging" the Person entity for Lacinia. You can read more about the concept of tagging for plugins in the sessions below but, in short, this is the way we, model designers, use to specify which entities we want to be exposed to which plugins.

  (def meta-db (hodur/init-schema
                '[^{:lacinia/tag-recursive true}
                  Person
                  [^String first-name
                   ^String last-name]]))

The hodur-lacinia-schema plugin exposes a function called schema that generates your model as a Lacinia schema payload:

  (def lacinia-schema (hodur-lacinia/schema meta-db))

When you inspect lacinia-schema, this is what you have:

  {:objects
   {:Person
    {:fields
     {:firstName {:type (non-null String)},
      :lastName {:type (non-null String)}}}}}

Assuming Lacinia's com.walmartlabs.lacinia.schema is bound to schema, you can initialize your instance by compiling the schema like this:

  (def compiled-schema (-> lacinia-schema
                           schema/compile))

Most certainly you will have some resolvers defined in your schema (say :person-query/resolver that you want to bind to function person-query-resolver). In this case, attach the resolvers using Lacinia's com.walmartlabs.lacinia.util/attach-resolvers function (shown in this next example as bound to util/attach-resolvers:

  (def compiled-schema (-> lacinia-schema
                           (util/attach-resolvers
                            {:person-query/resolver person-query-resolver})
                           schema/compile))

You can also use com.walmartlabs.lacinia.util/inject-resolvers instead if you prefer to keep your schema free of resolver markers.

Model Definition

All Hodur plugins follow the Model Definition as described on Hodur Engine's documentation.

Query, Mutation, and Subscription Roots

GraphQL is not a pure graph interface in the sense of enabling consumers to start traversing from any node. Instead, it has the concept of "roots" where queries, mutations, or subscriptions can start.

To define a query root, use the marker :lacinia/query. In the example below we are defining an entity named QueryRoot marked as Lacinia's query root. It has a single field game-by-id that returns a BoardGame.

  [^{:lacinia/tag-recursive true
     :lacinia/query true}
   QueryRoot
   [^BoardGame game-by-id [^{:type ID
                             :optional true} id]]]

The same principle applies to mutations and subscriptions. A root entity must be defined for each and marked with :lacinia/mutation and :lacinia/subscription respectively.

Resolvers and Streamers

In order to provide functionality to your GraphQL interface you will need to create resolvers and attach them to your graph tree. Lacinia will take care of building the call stack and stitching up the response.

A resolver is defined by using the marker :lacinia/resolve that can be used in any field. This marker takes a key that will later be used by com.walmartlabs.lacinia.util/attach-resolvers to map to real functions. The following example shows how to mark the game-by-id field to the resolver :query/game-by-id:

  [^:lacinia/query
   QueryRoot
   [^{:type BoardGame
      :lacinia/resolve :query/game-by-id}
    game-by-id [^{:type ID
                  :optional true} id]]]

Subscriptions use streamer functions instead of resolvers. Lacinia invokes a streamer function once, to initialize the subscription stream. The streamer is provided with a source stream callback function; as new values are available they are passed to this callback. Typically, the streamer will create a thread, core.async process, or other long-lived construct to feed values to the source stream.

Streamers are defined by using the marker :lacinia/stream:

  [^:lacinia/subscription
   SubscriptionRoot
   [^{:type Person
      :lacinia/stream :person/stream}
    listen-to-person [^ID id]]]

Both resolvers and streamers can also be attached to your Lacinia schema much later using com.walmartlabs.lacinia.util/inject-resolvers and com.walmartlabs.lacinia.util/inject-streamers instead. This is ideal if you prefer to keep your schema free of resolver and streamer markers.

Interfaces, Unions, and Enums

GraphQL supports interfaces, unions and enums. Simply marking your entities accordingly is enough to signal to Hodur Lacinia Schema that you want to use them.

Refer to Hodur Engine's Model Definition documentation for more details.

Input Objects

GraphQL requires that objects that are sent as parameters to mutations be defined as separate entities.

In the Hodur Lacinia schema this can be drastically simplified by using the marker :lacinia/input on the entity you want to use as an input object as shown below:

  [^{:lacinia/tag-recursive true
     :lacinia/input true}
   Employee
   [^{:type String} name
    ^{:type Float}  salary]]

Optional and Default Params

By default, Hodur assumes that all parameters are mandatory. In order to make them optional, they need to be marked with :optional. A common pattern is to make a parameter optional while also assigning a default value to it with :default:

  [QueryRoot
   [employees-by-location [^{:type String
                             :optional true
                             :default "HQ"} location]]]

GraphQL Directives

Hodur supports marking types, fields, enums, enum values, and params with GraphQL directives through the use of the tag :lacinia/directives.

A common usage is when using GraphQL federation where an internal entity needs to have a @key tag with a fields argument that indicates the key of this entity:

[^{:lacinia/tag-recursive true
   :lacinia/directives [{:key {:fields "id"}}]}
 Employee
 [^{:type ID} id
  ^{:type String} name
  ^{:type Float}  salary]]

Hodur supports either a map with a single entry where the key of the entry is the name of the directive and its value is a map of directive arguments (as shown above) or a simple keyword for a directive without arguments. I.e. consider marking the id field with hypothetical important and external directives:

[^{:lacinia/tag-recursive true}
 Employee
 [^{:type ID
    :lacinia/directives [:important :external]} id
  ^{:type String} name
  ^{:type Float}  salary]]

Schema Definition Language (SDL)

GraphQL Spec defines a Schema Definition Language and this Lacinia plugin for Hodur supports it as a target format instead of the default Lacinia schema format.

In order to use that, pass an additional map with {:output :sdl} to the schema function. It will return the SDL as a string:

(def sdl-schema (hodur-lacinia/schema meta-db {:output :sdl}))

The SDL might be useful if you don't want to or can't use Lacinia or if you prefer to bootstrap your Lacinia server with an SDL instead..

In fact, in order to enable Apollo GraphQL Federation with Lacinia, at this time only initializing it with a schema defined in Schema Definition Language is supported..

Bugs

If you find a bug, submit a GitHub issue.

Help!

This project is looking for team members who can help this project succeed! If you are interested in becoming a team member please open an issue.

License

Copyright © 2019 Tiago Luchini

Distributed under the MIT License (see LICENSE).

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].