All Projects → midas-framework → Midas

midas-framework / Midas

Licence: apache-2.0
A web framework for Gleam, Midas makes shiny things.

Programming Languages

elixir
2628 projects
erlang
1774 projects

Projects that are alternatives of or similar to Midas

Zulu
Total environment manager for ZSH
Stars: ✭ 129 (-5.84%)
Mutual labels:  framework
Heksa
CLI hex dumper with colors
Stars: ✭ 133 (-2.92%)
Mutual labels:  hex
Slim
Slim is a PHP micro framework that helps you quickly write simple yet powerful web applications and APIs.
Stars: ✭ 11,171 (+8054.01%)
Mutual labels:  framework
Facelandmarksdetection
Finds facial features such as face contour, eyes, mouth and nose in an image.
Stars: ✭ 130 (-5.11%)
Mutual labels:  framework
Cyclejs.cn
The Cycle.js Chinese documentation website.
Stars: ✭ 132 (-3.65%)
Mutual labels:  framework
Dedsploit
Network protocol auditing framework
Stars: ✭ 133 (-2.92%)
Mutual labels:  framework
Mix
☄️ PHP CLI mode development framework, supports Swoole, WorkerMan, FPM, CLI-Server / PHP 命令行模式开发框架,支持 Swoole、WorkerMan、FPM、CLI-Server
Stars: ✭ 1,753 (+1179.56%)
Mutual labels:  framework
Http
An opinionated framework for scalable web 🌎
Stars: ✭ 136 (-0.73%)
Mutual labels:  framework
Wookiee
Scala based lightweight service framework using akka and other popular technologies.
Stars: ✭ 132 (-3.65%)
Mutual labels:  framework
October
Self-hosted CMS platform based on the Laravel PHP Framework.
Stars: ✭ 10,740 (+7739.42%)
Mutual labels:  framework
Spasm
Write single page applications in D that compile to webassembly
Stars: ✭ 129 (-5.84%)
Mutual labels:  framework
Parlour
A package of UI extensions, components and improvements for Unity's UI frameworks.
Stars: ✭ 132 (-3.65%)
Mutual labels:  framework
Hadron
⚛️Framework for building a testable, modular backend with a dependency injection pattern in plain JavaScript.
Stars: ✭ 135 (-1.46%)
Mutual labels:  framework
Unity Raymarching Framework
A framework to easy implement raymarching in unity. Include lots of hash,noise,fbm,SDF,rotate functions
Stars: ✭ 129 (-5.84%)
Mutual labels:  framework
Portfolio Generator
JS framework to dynamically generate a portfolio site from a JSON file
Stars: ✭ 135 (-1.46%)
Mutual labels:  framework
Meshki
Meshki: A Black-Colored, Responsive Boilerplate for UI Development
Stars: ✭ 129 (-5.84%)
Mutual labels:  framework
Pyrogram
Telegram MTProto API Client Library and Framework in Pure Python for Users and Bots
Stars: ✭ 2,252 (+1543.8%)
Mutual labels:  framework
Easycnn
easy convolution neural network
Stars: ✭ 136 (-0.73%)
Mutual labels:  framework
Muta
Muta is a high-performance blockchain framework.
Stars: ✭ 135 (-1.46%)
Mutual labels:  framework
Bolt Js
A framework to build Slack apps using JavaScript
Stars: ✭ 1,971 (+1338.69%)
Mutual labels:  framework

Midas - web development with Gleam

Gleam brings type safety to erlang. This is a fantastic combination for rapidly building robust web applications. We've been doing it since Gleam 0.10.0 at plummail.co

This repo DOES NOT contain a framework for you to start building web applications. We started building a framework but found that it was not necessary (yet) and instead focused on contributing to back to other Gleam libraries.

Instead this repo is a guide to web development in Gleam.

Gleam & Mix

We use Mix because Elixir has some great libraries that are easy to call from Gleam, and it has been the easiest way to have a project with both languages.

  • Start a project using mix new my_app --sup
  • Add mix_gleam and follow their instructions.

A Server

Battle tested web servers are an erlang speciality, the are Gleam wrappers for cowboy, elli and plug.

Adding cowboy to your supervision tree so that mix will start it.

  children = [
    # ...
    %{
      id: :cowboy,
      start: {
        :gleam@[email protected],
        :start, [&:my_app@[email protected].handle(&1, config), 8080]
      }
    }
  ]

Note :[email protected]@router.handle is a function on a gleam module, we will cover it in the next section.

Routing, Action, Controllers

The gleam_http library defines Request and Response types for HTTP. The utilities in this library and the power of pattern matching is everything we use.

fn route(request, config) {
  case http.path_segments(request) {
    [] -> {
      io.debug("Do something for the homepage")
      http.response(200)
      |> Ok
    }
    ["user", user_id] -> {
      io.debug("Hello user")
      http.response(200)
      |> Ok
    }
    ["api" | rest] -> api_router.route(request, config)
  }
}

pub fn handle(request, config) {
  case route(request, config) {
    Ok(response) -> response
    Error(reason) -> todo("define your error response")
  }
}

We found it convenient to allow routes to return errors because it gives you early return when using the (extremely helpful) try syntax.

Handling input

We don't normally create a controller or action module. All parsing/rendering is done in the case statement show above and we call out to business logic functions. e.g.

// in case statement of router
["posts", "create"] -> {
  try json = parse_form(request)
  try params = create_post.params(json)
  try user_id = load_session(request, config.secret)
  try post = create_post.execute(topic, user_id)
  redirect(string.concat["posts", int.to_string(post.id)])
  |> Ok
}

Note all of our functions at this level return the same Error type. The Error type is defined by our application, functions like parse_form are wrappers around uri.parse_query (part of Gleam standard library) that transform errors into our application specific Error.

JSON

We maintain gleam_json, to handle JSON input we define application helpers than transform errors in the same way as parse_form

Views

Gleam does not (yet) have any string interpolation or templating, the easiest way we found to work around this was to use EExHTML and wrap calls as external function calls. Note this was not very convenient and we are currently not doing this because our service is just a JSON API.

Database Access

We use postgresql and the pgo library, there is a gleam wrapper

This does not give us models, we haven't missed them. (I would argue models have less value in a functional world, but different projects might miss them).

All of our SQL is hand written queries and we have helpers to make sure that errors are wrapped in out application specific error type.

pub fn insert_user(email_address) {
  let sql = "
    INSERT INTO users (email_address)
    VALUES ($1)
    RETURNING id, email_address
  "

  let args = [pgo.text(email_address)]
  try [identifier] = run_sql(sql, args, row_to_user)
}

pub fn row_to_user(row) {
  assert Ok(id) = dynamic.element(row, 0)
  assert Ok(id) = dynamic.int(id)
  assert Ok(email_address) = dynamic.element(row, 1)
  assert Ok(email_address) = dynamic.string(email_address)
  Ok(User(id, email_address))
}

Development process

To start the application run iex -S mix.

There is no live reloading set up, we type recompile() in the shell. Between the assurances of the type system and our tests most of the time we start it up it's already working so manually typing recompile works for us.

Final Note

Scaffolding a project that included sessions/flashes/etc would be great. We think Midas will become a Gleam web framework it just hasn't yet. The rest of this repo contains experiments on some of the pieces that framework would need.

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