Explorar el Código

feat: Initial commit

Douglas Andreani hace 1 año
commit
9e75cb9456
Se han modificado 10 ficheros con 286 adiciones y 0 borrados
  1. 23 0
      .github/workflows/test.yml
  2. 4 0
      .gitignore
  3. 25 0
      README.md
  4. 24 0
      gleam.toml
  5. 27 0
      manifest.toml
  6. 13 0
      public/index.html
  7. 105 0
      src/forms.gleam
  8. 50 0
      src/routes/routes.gleam
  9. 3 0
      src/state.gleam
  10. 12 0
      test/forms_test.gleam

+ 23 - 0
.github/workflows/test.yml

@@ -0,0 +1,23 @@
+name: test
+
+on:
+  push:
+    branches:
+      - master
+      - main
+  pull_request:
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: erlef/setup-beam@v1
+        with:
+          otp-version: "26.0.2"
+          gleam-version: "1.0.0"
+          rebar3-version: "3"
+          # elixir-version: "1.15.4"
+      - run: gleam deps download
+      - run: gleam test
+      - run: gleam format --check src test

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+*.beam
+*.ez
+/build
+erl_crash.dump

+ 25 - 0
README.md

@@ -0,0 +1,25 @@
+# forms
+
+[![Package Version](https://img.shields.io/hexpm/v/forms)](https://hex.pm/packages/forms)
+[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/forms/)
+
+```sh
+gleam add forms
+```
+```gleam
+import forms
+
+pub fn main() {
+  // TODO: An example of the project in use
+}
+```
+
+Further documentation can be found at <https://hexdocs.pm/forms>.
+
+## Development
+
+```sh
+gleam run   # Run the project
+gleam test  # Run the tests
+gleam shell # Run an Erlang shell
+```

+ 24 - 0
gleam.toml

@@ -0,0 +1,24 @@
+name = "forms"
+version = "1.0.0"
+
+# Fill out these fields if you intend to generate HTML documentation or publish
+# your project to the Hex package manager.
+#
+# description = ""
+# licences = ["Apache-2.0"]
+# repository = { type = "github", user = "username", repo = "project" }
+# links = [{ title = "Website", href = "https://gleam.run" }]
+#
+# For a full reference of all the available options, you can have a look at
+# https://gleam.run/writing-gleam/gleam-toml/. 
+
+[dependencies]
+gleam_stdlib = "~> 0.34 or ~> 1.0"
+mist = "~> 1.0"
+gleam_http = "~> 3.6"
+gleam_erlang = "~> 0.25"
+htmz = "~> 0.1"
+gluid = "~> 1.0"
+
+[dev-dependencies]
+gleeunit = "~> 1.0"

+ 27 - 0
manifest.toml

@@ -0,0 +1,27 @@
+# This file was generated by Gleam
+# You typically do not need to edit this file
+
+packages = [
+  { name = "birl", version = "1.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "ranger"], otp_app = "birl", source = "hex", outer_checksum = "0757CFE97DA52F19BC3262AC3DD284D9DAD2718D4C1830888DE483FB147477D4" },
+  { name = "gleam_erlang", version = "0.25.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "054D571A7092D2A9727B3E5D183B7507DAB0DA41556EC9133606F09C15497373" },
+  { name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" },
+  { name = "gleam_otp", version = "0.10.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "0B04FE915ACECE539B317F9652CAADBBC0F000184D586AAAF2D94C100945D72B" },
+  { name = "gleam_stdlib", version = "0.36.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "C0D14D807FEC6F8A08A7C9EF8DFDE6AE5C10E40E21325B2B29365965D82EB3D4" },
+  { name = "gleeunit", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "D364C87AFEB26BDB4FB8A5ABDE67D635DC9FA52D6AB68416044C35B096C6882D" },
+  { name = "glisten", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "glisten", source = "hex", outer_checksum = "CF3A9383E9BA4A8CBAF2F7B799716290D02F2AC34E7A77556B49376B662B9314" },
+  { name = "gluid", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gluid", source = "hex", outer_checksum = "9C0D64DC9A345B7DCC76A2EFDC1F3479E3C6A08A1FB81156E9CCED959F8DEB78" },
+  { name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
+  { name = "htmz", version = "0.1.3", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "htmz", source = "hex", outer_checksum = "ADBFE7898CDEB7274EFF88351610554F40A8C6AA4A423E6907C029C36AD5F75A" },
+  { name = "logging", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "82C112ED9B6C30C1772A6FE2613B94B13F62EA35F5869A2630D13948D297BD39" },
+  { name = "mist", version = "1.0.0", build_tools = ["gleam"], requirements = ["birl", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "glisten", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "7765E53DCC9ACCACF217B8E0CA3DE7E848C783BFAE5118B75011E81C2C80385C" },
+  { name = "ranger", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "ranger", source = "hex", outer_checksum = "28E615AE7590ED922AF1510DDF606A2ECBBC2A9609AF36D412EDC925F06DFD20" },
+]
+
+[requirements]
+gleam_erlang = { version = "~> 0.25" }
+gleam_http = { version = "~> 3.6" }
+gleam_stdlib = { version = "~> 0.34 or ~> 1.0" }
+gleeunit = { version = "~> 1.0" }
+gluid = { version = "~> 1.0"}
+htmz = { version = "~> 0.1" }
+mist = { version = "~> 1.0" }

+ 13 - 0
public/index.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Document</title>
+</head>
+<body>
+    <h1>Hello World</h1>
+
+    <script src="https://unpkg.com/htmx.org@1.9.11"></script>
+</body>
+</html>

+ 105 - 0
src/forms.gleam

@@ -0,0 +1,105 @@
+import gleam/http/response.{type Response}
+import gleam/http/request.{type Request}
+import gleam/http.{method_to_string}
+import mist.{type Connection, type ResponseData}
+import gleam/bytes_builder
+import gleam/erlang/process
+import routes/routes
+import gleam/io
+import gleam/string
+import gleam/int
+import gluid
+import state.{type State}
+
+pub fn main() {
+  let assert Ok(_) =
+    fn(req: Request(Connection)) -> Response(ResponseData) {
+      let response = start(req, main_handler, end)
+
+      response
+    }
+    |> mist.new
+    |> mist.port(8000)
+    |> mist.start_http
+
+  process.sleep_forever()
+}
+
+fn start(
+  req: Request(Connection),
+  next: fn(Request(Connection), State) -> Response(ResponseData),
+  end: fn(Int, state.State) -> Nil,
+) -> Response(ResponseData) {
+  let state = state.State(gluid.guidv4())
+
+  io.print("START: ")
+  io.print(state.uuid)
+  io.print(" HOST: ")
+  io.println(req.host)
+
+  let response = next(req, state)
+  end(response.status, state)
+  response
+}
+
+fn end(status_code: Int, state: state.State) {
+  io.print("END: ")
+  io.print(state.uuid)
+  io.print(" Status Code: ")
+  io.println(int.to_string(status_code))
+}
+
+fn log(
+  req: Request(Connection),
+  next: fn(Request(Connection), State) -> Response(ResponseData),
+  state: State,
+) -> Response(ResponseData) {
+  io.print("INFO: ")
+  io.print(state.uuid)
+  io.print(" ")
+  io.print(string.uppercase(method_to_string(req.method)))
+  io.print(" ")
+  io.print(req.path)
+  io.println(" ")
+
+  next(req, state)
+}
+
+fn main_handler(
+  req: Request(Connection),
+  state: State,
+) -> Response(ResponseData) {
+  case request.path_segments(req) {
+    [""] -> log(req, routes.index, state)
+    ["health_check"] -> log(req, routes.health_check, state)
+
+    _ -> {
+      case
+        req.path
+        |> string.length()
+      {
+        // if only 1 char in string, it means path is '/', so we return the index route
+        1 -> log(req, routes.index, state)
+
+        // otherwise, return page not found: 404
+        _ -> {
+          log(req, not_found, state)
+        }
+      }
+    }
+  }
+}
+
+fn not_found(
+  request: Request(Connection),
+  state: state.State,
+) -> Response(ResponseData) {
+  io.print("ERROR: ")
+  io.print(state.uuid)
+  io.print(" Page not found: ")
+  io.print(request.path)
+  io.println("")
+
+  response.new(404)
+  |> response.set_body(mist.Bytes(bytes_builder.new()))
+}

+ 50 - 0
src/routes/routes.gleam

@@ -0,0 +1,50 @@
+import gleam/http/request.{type Request}
+import gleam/http/response.{type Response}
+import mist.{type Connection, type ResponseData}
+import gleam/bytes_builder
+import gleam/option.{None}
+import gleam/result
+import gleam/string_builder
+import gleam/io
+import state
+
+pub fn file_not_found(
+  file_path: String,
+  request: Request(Connection),
+  state: state.State,
+) -> Response(ResponseData) {
+  let body_msg =
+    string_builder.new()
+    |> string_builder.append(suffix: "File not found: ")
+    |> string_builder.append(suffix: file_path)
+  io.print("ERROR: ")
+  io.print(state.uuid)
+  io.print(" Page not found: ")
+  io.print(request.path)
+  io.println("")
+  response.new(404)
+  |> response.set_body(mist.Bytes(bytes_builder.from_string_builder(body_msg)))
+}
+
+pub fn health_check(
+  _request: Request(Connection),
+  _state: state.State,
+) -> Response(ResponseData) {
+  response.new(200)
+  |> response.set_body(mist.Bytes(bytes_builder.from_string("OK")))
+}
+
+pub fn index(
+  request: Request(Connection),
+  state: state.State,
+) -> Response(ResponseData) {
+  let file_path = "public/index.html"
+  mist.send_file(file_path, offset: 0, limit: None)
+  |> result.map(fn(file) {
+    let content_type = "text/html"
+    response.new(200)
+    |> response.prepend_header("content-type", content_type)
+    |> response.set_body(file)
+  })
+  |> result.lazy_unwrap(fn() { file_not_found(file_path, request, state) })
+}

+ 3 - 0
src/state.gleam

@@ -0,0 +1,3 @@
+pub type State {
+  State(uuid: String)
+}

+ 12 - 0
test/forms_test.gleam

@@ -0,0 +1,12 @@
+import gleeunit
+import gleeunit/should
+
+pub fn main() {
+  gleeunit.main()
+}
+
+// gleeunit test functions end in `_test`
+pub fn hello_world_test() {
+  1
+  |> should.equal(1)
+}