Skip to content

Latest commit

 

History

History

docs

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 

Markus Documentation

Markus provides a statically-typed way for developers to express the abstract logic and functionality of a certain piece of software without going into implementation details.

Table of contents

  1. Background & Types
  2. Queries
  3. Atomic Types
  4. User Type
  5. Permissions & Guards

Background & Types

In Markus anything is an Object and there is no concept like Table (as in SQL databases) that separates them from one another, anything that is present in the database is a member of Global Set.

Markus Object Model supports Multiple Inheritance, meaning that any object-type can inherit properties from more than one object-types, as an example in the picture above you can see there are some Rectangles and a Triangle and we know that both of them can be categorized as Polygon.

In markus we use the following syntax to define a type:

# type TypeName [: BASE* ] {
#  [property_name[?]: Type;]*
# }

type Polygon {}
type Triangle: Polygon {}

type Carnivorous {}
type Mammal {}

# The cat is a small carnivorous mammal.
type Cat: Carnivorous, Mammal {
  # Let's give our kitty a name.
  name: string;
}

You can also look at the source code that shapes the picture above to understand more.

Click to see source code
type Named {
  name: string;
}

type Colored {
  color: string;
}

# `Shape` is `Named` and `Colored`.
type Shape: Named, Colored {}

# We define `Circle` as a shape.
type Circle: Shape {}

type Polygon: Shape {}

type Triangle: Polygon {}

type Quadrilateral: Polygon {}

type Parallelogram: Polygon {}

type Rectangle: Parallelogram {}

type Person: Named {
  height: number;
}

# Data:
# Rectangle(name: "A", color: "green")
# Parallelogram(name: "B", color: "red")
# Parallelogram(name: "C", color: "blue")
# Rectangle(name: "D", color: "red")
# Rectangle(name: "E", color: "green")
# Circle(name: "F", color: "green")
# Circle(name: "G", color: "red")
# Person(name: "H", height: 160)
# Triangle(name: "I", color: "yellow")
# Person(name: "J", height: 185)

Looking at things in this way gives us the ability to write some powerful queries, let's look at them in the next section.

Queries

Now that we know how to start defining things in Markus using types, it's time to learn about querying our database.

Let's start with the most basic query -an empty query-:

query myQuery() {}
Click to see the result
Rectangle(name: "A", color: "green")
Parallelogram(name: "B", color: "red")
Parallelogram(name: "C", color: "blue")
Rectangle(name: "D", color: "red")
Rectangle(name: "E", color: "green")
Circle(name: "F", color: "green")
Circle(name: "G", color: "red")
Person(name: "H", height: 160)
Triangle(name: "I", color: "yellow")
Person(name: "J", height: 185)

As you have already guessed the empty query will return all of the things in the database!

Filters

We can achieve more complex queries using subsequential filters, the most important one of which is the is filter, this filter takes a type name as an argument and filters the set so that only the objects that are based on the given type will stay in the result set.

Here is an example that returns all of the Quadrilateral shapes in the set:

query allOfQuadrilaterals() {
  is(Quadrilateral)
}
Click to see the result
Rectangle(name: "A", color: "green")
Parallelogram(name: "B", color: "red")
Parallelogram(name: "C", color: "blue")
Rectangle(name: "D", color: "red")
Rectangle(name: "E", color: "green")

Now let's go one step further and try to return things that are red.

query redStuff() {
  is(Colored),
  eq(.color, "red")
}
Click to see the result
Parallelogram(name: "B", color: "red")
Rectangle(name: "D", color: "red")
Circle(name: "G", color: "red")

You can see that we can use eq filter to filter the set based on an equality expression, you can learn more about querying data.

Parameters

One of the features of Markus is its dynamic queries, you can define a query in the following way to let the client send some parameters to you and return a result accordingly.

The following example will takes a color from the client and returns everything in the set that is of the given color:

query withColor($color: string) {
  is(Colored),
  eq(.color, $color)
}
Click to see the result
# withColor("green")
Rectangle(name: "A", color: "green")
Rectangle(name: "E", color: "green")
Circle(name: "F", color: "green")