-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Example for parsing a select via glibsql/http
- Loading branch information
1 parent
3ca6f6c
commit 93bbbba
Showing
8 changed files
with
322 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.beam | ||
*.ez | ||
/build | ||
erl_crash.dump |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# app | ||
|
||
[![Package Version](https://img.shields.io/hexpm/v/app)](https://hex.pm/packages/app) | ||
[![Hex Docs](https://img.shields.io/badge/hex-docs-ffaff3)](https://hexdocs.pm/app/) | ||
|
||
```sh | ||
gleam add app@1 | ||
``` | ||
```gleam | ||
import app | ||
pub fn main() { | ||
// TODO: An example of the project in use | ||
} | ||
``` | ||
|
||
Further documentation can be found at <https://hexdocs.pm/app>. | ||
|
||
## Development | ||
|
||
```sh | ||
gleam run # Run the project | ||
gleam test # Run the tests | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name = "app" | ||
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 = "", repo = "" } | ||
# links = [{ title = "Website", href = "" }] | ||
# | ||
# 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.0 and < 2.0.0" | ||
glenv = ">= 0.4.0 and < 1.0.0" | ||
gleam_httpc = ">= 2.2.0 and < 3.0.0" | ||
glibsql = ">= 0.5.1 and < 1.0.0" | ||
decode = ">= 0.2.0 and < 1.0.0" | ||
dot_env = ">= 1.0.0 and < 2.0.0" | ||
thoas = ">= 1.2.1 and < 2.0.0" | ||
|
||
[dev-dependencies] | ||
gleeunit = ">= 1.0.0 and < 2.0.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# This file was generated by Gleam | ||
# You typically do not need to edit this file | ||
|
||
packages = [ | ||
{ name = "decode", version = "0.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "decode", source = "hex", outer_checksum = "965F517F67B8C172CA27A5C8E34C73733139E8C9E64736181B8C3179281F9793" }, | ||
{ name = "dot_env", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "simplifile"], otp_app = "dot_env", source = "hex", outer_checksum = "E7B84DC7B579553AF3B9F0A03B2F8DDB9B44521F553CCFBE633AA595C27F1A05" }, | ||
{ name = "envoy", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "CFAACCCFC47654F7E8B75E614746ED924C65BD08B1DE21101548AC314A8B6A41" }, | ||
{ name = "filepath", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "EFB6FF65C98B2A16378ABC3EE2B14124168C0CE5201553DE652E2644DCFDB594" }, | ||
{ name = "gleam_http", version = "3.6.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "8C07DF9DF8CC7F054C650839A51C30A7D3C26482AC241C899C1CEA86B22DBE51" }, | ||
{ name = "gleam_httpc", version = "2.2.0", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "CF76C71002DEECF6DC5D9CA83D962728FAE166B57926BE442D827004D3C7DF1B" }, | ||
{ name = "gleam_javascript", version = "0.11.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "483631D3001FCE8EB12ADEAD5E1B808440038E96F93DA7A32D326C82F480C0B2" }, | ||
{ name = "gleam_json", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "thoas"], otp_app = "gleam_json", source = "hex", outer_checksum = "9063D14D25406326C0255BDA0021541E797D8A7A12573D849462CAFED459F6EB" }, | ||
{ name = "gleam_stdlib", version = "0.39.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "2D7DE885A6EA7F1D5015D1698920C9BAF7241102836CE0C3837A4F160128A9C4" }, | ||
{ name = "gleeunit", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "F7A7228925D3EE7D0813C922E062BFD6D7E9310F0BEE585D3A42F3307E3CFD13" }, | ||
{ name = "glenv", version = "0.4.0", build_tools = ["gleam"], requirements = ["decode", "envoy", "gleam_stdlib"], otp_app = "glenv", source = "hex", outer_checksum = "46164B9FFEB08927FD2CEBD96C3AFBE082AD5CC2C6F2FC4A78EFDA9EB61E3510" }, | ||
{ name = "glibsql", version = "0.5.1", build_tools = ["gleam"], requirements = ["decode", "gleam_http", "gleam_javascript", "gleam_json", "gleam_stdlib"], otp_app = "glibsql", source = "hex", outer_checksum = "6842D33037AA1D79AD4BB871426354B704E7265F7BB2490BB6D54259F6A5EA01" }, | ||
{ name = "simplifile", version = "2.0.1", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "5FFEBD0CAB39BDD343C3E1CCA6438B2848847DC170BA2386DF9D7064F34DF000" }, | ||
{ name = "thoas", version = "1.2.1", build_tools = ["rebar3"], requirements = [], otp_app = "thoas", source = "hex", outer_checksum = "E38697EDFFD6E91BD12CEA41B155115282630075C2A727E7A6B2947F5408B86A" }, | ||
] | ||
|
||
[requirements] | ||
decode = { version = ">= 0.2.0 and < 1.0.0" } | ||
dot_env = { version = ">= 1.0.0 and < 2.0.0" } | ||
gleam_httpc = { version = ">= 2.2.0 and < 3.0.0" } | ||
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" } | ||
gleeunit = { version = ">= 1.0.0 and < 2.0.0" } | ||
glenv = { version = ">= 0.4.0 and < 1.0.0" } | ||
glibsql = { version = ">= 0.5.1 and < 1.0.0" } | ||
thoas = { version = ">= 1.2.1 and < 2.0.0"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
import app/internal/env | ||
import decode | ||
import gleam/bit_array | ||
import gleam/dynamic | ||
import gleam/httpc | ||
import gleam/int | ||
import gleam/list | ||
import gleam/option.{type Option, None, Some} | ||
import gleam/result | ||
import glibsql/http as glibsql | ||
|
||
pub type User { | ||
User(id: Int, email: String, created_at: String, updated_at: Option(String)) | ||
} | ||
|
||
pub fn main() { | ||
let env = case env.load() { | ||
Ok(env) -> env | ||
Error(reason) -> { | ||
panic as reason | ||
} | ||
} | ||
|
||
let request = | ||
glibsql.new_request() | ||
|> glibsql.with_database(env.database_name) | ||
|> glibsql.with_organization(env.database_organization) | ||
|> glibsql.with_token(env.database_auth_token) | ||
|> glibsql.with_statement(glibsql.ExecuteStatement( | ||
sql: "SELECT id, email, created_at, updated_at FROM users", | ||
)) | ||
|> glibsql.with_statement(glibsql.CloseStatement) | ||
|> glibsql.build | ||
|
||
let assert Ok(request) = request | ||
|
||
use response <- result.try(httpc.send(request)) | ||
|
||
let assert Ok(object) = json_parse(response.body) | ||
|
||
let assert Ok(rows) = | ||
build_decoder() | ||
|> decode.from(object) | ||
|> result.map(fn(resp) { | ||
let assert Ok(first) = list.first(resp.results) | ||
|
||
case first.response.inner_result { | ||
Some(inner_result) -> inner_result.rows | ||
None -> [] | ||
} | ||
}) | ||
|
||
let users = list.map(rows, fn(row) { | ||
let values = list.map(row, fn(column) { column.value |> option.unwrap("") }) | ||
|
||
let assert [id, email, created_at, updated_at] = values | ||
let assert Ok(id) = int.parse(id) | ||
let updated_at = case updated_at { | ||
"" -> None | ||
str -> Some(str) | ||
} | ||
|
||
User(id, email, created_at, updated_at) | ||
}) | ||
|
||
let assert [ | ||
User(1, "[email protected]", "2024-07-12 02:17:13", None), | ||
User(2, "[email protected]", "2024-07-12 02:17:20", None), | ||
User(3, "[email protected]", "2024-07-12 02:17:23", None), | ||
User(4, "[email protected]", "2024-07-12 02:17:28", None), | ||
] = users | ||
|
||
Ok(Nil) | ||
} | ||
|
||
// Turn the response into a Gleam data structure. | ||
|
||
fn json_parse(json: String) { | ||
let ba = bit_array.from_string(json) | ||
use dynamic_value <- result.try(decode_bits(ba)) | ||
|
||
Ok(dynamic_value) | ||
} | ||
|
||
@external(erlang, "app_ffi", "decode") | ||
fn decode_bits(json: BitArray) -> Result(dynamic.Dynamic, Nil) | ||
|
||
// Break down the response. | ||
|
||
type RowColumn { | ||
RowColumn(type_: String, value: Option(String)) | ||
} | ||
|
||
type InnerResult { | ||
InnerResult(rows: List(List(RowColumn))) | ||
} | ||
|
||
type Response { | ||
Response(type_: String, inner_result: Option(InnerResult)) | ||
} | ||
|
||
type IResult { | ||
IResult(type_: String, response: Response) | ||
} | ||
|
||
type GlibsqlHttpResponse { | ||
GlibsqlHttpResponse(results: List(IResult)) | ||
} | ||
|
||
fn build_decoder() { | ||
let row_column_decoder = | ||
decode.into({ | ||
use type_ <- decode.parameter | ||
use value <- decode.parameter | ||
|
||
RowColumn(type_, value) | ||
}) | ||
|> decode.field("type", decode.string) | ||
|> decode.field("value", decode.optional(decode.string)) | ||
|
||
let row_decoder = decode.list(of: row_column_decoder) | ||
|
||
let inner_result_decoder = | ||
decode.into({ | ||
use rows <- decode.parameter | ||
|
||
InnerResult(rows) | ||
}) | ||
|> decode.field("rows", decode.list(of: row_decoder)) | ||
|
||
let response_decoder = | ||
decode.into({ | ||
use type_ <- decode.parameter | ||
use inner_result <- decode.parameter | ||
|
||
Response(type_, inner_result) | ||
}) | ||
|> decode.field("type", decode.string) | ||
|> decode.field("result", decode.optional(inner_result_decoder)) | ||
|
||
let result_decoder = | ||
decode.into({ | ||
use type_ <- decode.parameter | ||
use response <- decode.parameter | ||
|
||
IResult(type_, response) | ||
}) | ||
|> decode.field("type", decode.string) | ||
|> decode.field("response", response_decoder) | ||
|
||
let glibsql_http_response_decoder = | ||
decode.into({ | ||
use results <- decode.parameter | ||
|
||
GlibsqlHttpResponse(results) | ||
}) | ||
|> decode.field("results", decode.list(of: result_decoder)) | ||
|
||
glibsql_http_response_decoder | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import decode | ||
import dot_env | ||
import gleam/list | ||
import gleam/string | ||
import glenv | ||
|
||
pub type Env { | ||
Env( | ||
database_name: String, | ||
database_organization: String, | ||
database_auth_token: String, | ||
) | ||
} | ||
|
||
const definitions = [ | ||
#("DATABASE_NAME", glenv.String), #("DATABASE_ORGANIZATION", glenv.String), | ||
#("DATABASE_AUTH_TOKEN", glenv.String), | ||
] | ||
|
||
pub fn load() -> Result(Env, String) { | ||
dot_env.load_default() | ||
|
||
let decoder = | ||
decode.into({ | ||
use database_name <- decode.parameter | ||
use database_organization <- decode.parameter | ||
use database_auth_token <- decode.parameter | ||
|
||
Env(database_name, database_organization, database_auth_token) | ||
}) | ||
|> decode.field("DATABASE_NAME", decode.string) | ||
|> decode.field("DATABASE_ORGANIZATION", decode.string) | ||
|> decode.field("DATABASE_AUTH_TOKEN", decode.string) | ||
|
||
case glenv.load(decoder, definitions) { | ||
Ok(env) -> Ok(env) | ||
Error(err) -> { | ||
let reason = case err { | ||
glenv.NotFoundError(key) -> "Environment variable not found: " <> key | ||
glenv.ParseError(key, _) -> | ||
"Failed to parse environment variable: " <> key | ||
glenv.DefinitionMismatchError(errors) -> { | ||
let errors = | ||
list.map(errors, fn(error) { | ||
error.expected | ||
<> " expected, got " | ||
<> error.found | ||
<> " at " | ||
<> string.join(error.path, "->") | ||
}) | ||
|
||
"Failed to match environment definition: " | ||
<> string.join(errors, ", ") | ||
} | ||
} | ||
|
||
Error(reason) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
-module(app_ffi). | ||
|
||
-export([ | ||
decode/1 | ||
]). | ||
|
||
decode(Json) -> | ||
thoas:decode(Json). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} |