๐Ÿ‘ฉโ€๐Ÿš’ Firefighters API written in Gleam!
lustre gleam

:rewind: move user query back to the server module

kacaii.dev c3e94313 6b531b30

verified
+73 -152
+1 -6
client/manifest.toml
··· 3 3 4 4 packages = [ 5 5 { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" }, 6 - { name = "backoff", version = "1.1.6", build_tools = ["rebar3"], requirements = [], otp_app = "backoff", source = "hex", outer_checksum = "CF0CFFF8995FB20562F822E5CC47D8CCF664C5ECDC26A684CBE85C225F9D7C39" }, 7 6 { name = "booklet", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "booklet", source = "hex", outer_checksum = "08E0FDB78DC4D8A5D3C80295B021505C7D2A2E7B6C6D5EAB7286C36F4A53C851" }, 8 7 { name = "directories", version = "1.2.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "D13090CFCDF6759B87217E8DDD73A75903A700148A82C1D33799F333E249BF9E" }, 9 8 { name = "envoy", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "850DA9D29D2E5987735872A2B5C81035146D7FE19EFC486129E44440D03FD832" }, ··· 37 36 { name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" }, 38 37 { name = "mist", version = "5.0.4", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_http", "gleam_otp", "gleam_stdlib", "gleam_yielder", "glisten", "gramps", "hpack_erl", "logging"], otp_app = "mist", source = "hex", outer_checksum = "7CED4B2D81FD547ADB093D97B9928B9419A7F58B8562A30A6CC17A252B31AD05" }, 39 38 { name = "modem", version = "2.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib", "lustre"], otp_app = "modem", source = "hex", outer_checksum = "3F9682EBCBF4D26045F1038A7507E8C7967E49D43F9CA6BA68EF0C971B195A7F" }, 40 - { name = "opentelemetry_api", version = "1.5.0", build_tools = ["rebar3", "mix"], requirements = [], otp_app = "opentelemetry_api", source = "hex", outer_checksum = "F53EC8A1337AE4A487D43AC89DA4BD3A3C99DDF576655D071DEED8B56A2D5DDA" }, 41 - { name = "pg_types", version = "0.6.0", build_tools = ["rebar3"], requirements = [], otp_app = "pg_types", source = "hex", outer_checksum = "9949A4849DD13408FA249AB7B745E0D2DFDB9532AEE2B9722326E33CD082A778" }, 42 - { name = "pgo", version = "0.20.0", build_tools = ["rebar3"], requirements = ["backoff", "opentelemetry_api", "pg_types"], otp_app = "pgo", source = "hex", outer_checksum = "2F11E6649CEB38E569EF56B16BE1D04874AE5B11A02867080A2817CE423C683B" }, 43 39 { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" }, 44 - { name = "pog", version = "4.1.0", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_otp", "gleam_stdlib", "gleam_time", "pgo"], otp_app = "pog", source = "hex", outer_checksum = "E4AFBA39A5FAA2E77291836C9683ADE882E65A06AB28CA7D61AE7A3AD61EBBD5" }, 45 40 { name = "polly", version = "3.0.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_erlang", "gleam_otp", "gleam_stdlib", "simplifile"], otp_app = "polly", source = "hex", outer_checksum = "35B11497B998618CEE216415A7853C3FED3F0F2148DC86BD8FC86B95D67F6DD8" }, 46 41 { name = "rsvp", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_fetch", "gleam_http", "gleam_httpc", "gleam_javascript", "gleam_json", "gleam_stdlib", "lustre"], otp_app = "rsvp", source = "hex", outer_checksum = "40F9E0E662FF258E10C7041A9591261FE802D56625FB444B91510969644F7722" }, 47 - { name = "shared", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib", "pog", "youid"], source = "local", path = "../shared" }, 42 + { name = "shared", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib", "youid"], source = "local", path = "../shared" }, 48 43 { name = "simplifile", version = "2.3.2", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "E049B4DACD4D206D87843BCF4C775A50AE0F50A52031A2FFB40C9ED07D6EC70A" }, 49 44 { name = "snag", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "274F41D6C3ECF99F7686FDCE54183333E41D2C1CA5A3A673F9A8B2C7A4401077" }, 50 45 { name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" },
+1 -1
server/gleam.toml
··· 5 5 [dependencies] 6 6 gleam_stdlib = ">= 0.44.0 and < 2.0.0" 7 7 shared = { path = "../shared" } 8 - pog = ">= 4.1.0 and < 5.0.0" 9 8 wisp = ">= 2.2.0 and < 3.0.0" 10 9 mist = ">= 5.0.4 and < 6.0.0" 11 10 envoy = ">= 1.1.0 and < 2.0.0" ··· 19 18 gleam_http = ">= 4.3.0 and < 5.0.0" 20 19 global_value = ">= 1.0.0 and < 2.0.0" 21 20 gleam_time = ">= 1.7.0 and < 2.0.0" 21 + pog = ">= 4.1.0 and < 5.0.0" 22 22 23 23 [dev-dependencies] 24 24 gleeunit = ">= 1.0.0 and < 2.0.0"
+1 -1
server/manifest.toml
··· 40 40 { name = "pgo", version = "0.20.0", build_tools = ["rebar3"], requirements = ["backoff", "opentelemetry_api", "pg_types"], otp_app = "pgo", source = "hex", outer_checksum = "2F11E6649CEB38E569EF56B16BE1D04874AE5B11A02867080A2817CE423C683B" }, 41 41 { name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" }, 42 42 { name = "pog", version = "4.1.0", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_otp", "gleam_stdlib", "gleam_time", "pgo"], otp_app = "pog", source = "hex", outer_checksum = "E4AFBA39A5FAA2E77291836C9683ADE882E65A06AB28CA7D61AE7A3AD61EBBD5" }, 43 - { name = "shared", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib", "pog", "youid"], source = "local", path = "../shared" }, 43 + { name = "shared", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib", "youid"], source = "local", path = "../shared" }, 44 44 { name = "simplifile", version = "2.3.2", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "E049B4DACD4D206D87843BCF4C775A50AE0F50A52031A2FFB40C9ED07D6EC70A" }, 45 45 { name = "splitter", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "splitter", source = "hex", outer_checksum = "3DFD6B6C49E61EDAF6F7B27A42054A17CFF6CA2135FF553D0CB61C234D281DD0" }, 46 46 { name = "squirrel", version = "4.6.0", build_tools = ["gleam"], requirements = ["argv", "envoy", "eval", "filepath", "glam", "gleam_community_ansi", "gleam_crypto", "gleam_json", "gleam_regexp", "gleam_stdlib", "gleam_time", "glexer", "justin", "mug", "non_empty_list", "pog", "simplifile", "term_size", "tom", "tote", "youid"], otp_app = "squirrel", source = "hex", outer_checksum = "0ED10A868BDD1A5D4B68D99CD1C72DC3F23C6E36E16D33454C5F0C31BAC9CB1E" },
+19
server/src/server/auth.gleam
··· 6 6 import pog 7 7 import server/auth/sql 8 8 import server/context 9 + import shared/user 9 10 import wisp 10 11 import youid/uuid 11 12 ··· 62 63 True -> Ok(row.id) 63 64 False -> Error(WrongPassword) 64 65 } 66 + } 67 + 68 + /// Query an user by Uuid 69 + pub fn whoami( 70 + db: pog.Connection, 71 + uuid: uuid.Uuid, 72 + ) -> Result(user.User, AuthError) { 73 + use returned <- result.try( 74 + sql.whoami(db, uuid) 75 + |> result.map_error(Database), 76 + ) 77 + 78 + use row <- result.map( 79 + list.first(returned.rows) 80 + |> result.replace_error(NotFound), 81 + ) 82 + 83 + user.User(uuid:, full_name: row.full_name, email: row.email, phone: row.phone) 65 84 } 66 85 67 86 pub fn handle_error(err: AuthError) {
+42
server/src/server/auth/sql.gleam
··· 48 48 |> pog.execute(db) 49 49 } 50 50 51 + /// A row you get from running the `whoami` query 52 + /// defined in `./src/server/auth/sql/whoami.sql`. 53 + /// 54 + /// > ๐Ÿฟ๏ธ This type definition was generated automatically using v4.6.0 of the 55 + /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). 56 + /// 57 + pub type WhoamiRow { 58 + WhoamiRow(id: Uuid, full_name: String, email: String, phone: String) 59 + } 60 + 61 + /// Runs the `whoami` query 62 + /// defined in `./src/server/auth/sql/whoami.sql`. 63 + /// 64 + /// > ๐Ÿฟ๏ธ This function was generated automatically using v4.6.0 of 65 + /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 66 + /// 67 + pub fn whoami( 68 + db: pog.Connection, 69 + arg_1: Uuid, 70 + ) -> Result(pog.Returned(WhoamiRow), pog.QueryError) { 71 + let decoder = { 72 + use id <- decode.field(0, uuid_decoder()) 73 + use full_name <- decode.field(1, decode.string) 74 + use email <- decode.field(2, decode.string) 75 + use phone <- decode.field(3, decode.string) 76 + decode.success(WhoamiRow(id:, full_name:, email:, phone:)) 77 + } 78 + 79 + "select 80 + u.id, 81 + u.full_name, 82 + u.email, 83 + u.phone 84 + from public.user_account as u 85 + where u.id = $1; 86 + " 87 + |> pog.query 88 + |> pog.parameter(pog.text(uuid.to_string(arg_1))) 89 + |> pog.returning(decoder) 90 + |> pog.execute(db) 91 + } 92 + 51 93 // --- Encoding/decoding utils ------------------------------------------------- 52 94 53 95 /// A decoder to decode `Uuid`s coming from a Postgres query.
+2 -1
server/src/server/auth/sql/authenticate.sql
··· 4 4 u.password_hash, 5 5 u.is_active 6 6 from public.user_account as u 7 - where u.email = $1; 7 + where u.email = 8 + $1;
+2 -10
server/src/server/router/login.gleam
··· 8 8 import server/auth 9 9 import server/context.{type Context} 10 10 import shared/session 11 - import shared/user 12 11 import wisp.{type Request, type Response} 13 12 import youid/uuid 14 13 15 14 type LoginError { 16 15 Auth(auth.AuthError) 17 - QueryError(user.UserError) 18 16 } 19 17 20 18 /// ๎ธฌ Queries the database and store a session token containing the user uuid ··· 46 44 ) -> Response { 47 45 let query_result = { 48 46 use user <- result.map( 49 - user.find(db, user_uuid) 50 - |> result.map_error(QueryError), 47 + auth.whoami(db, user_uuid) 48 + |> result.map_error(Auth), 51 49 ) 52 50 53 51 session.Authenticated(user) ··· 74 72 fn handle_error(err: LoginError) -> Response { 75 73 case err { 76 74 Auth(err) -> auth.handle_error(err) 77 - 78 - QueryError(err) -> 79 - case err { 80 - user.NotFound -> wisp.not_found() 81 - user.Database(_) -> wisp.internal_server_error() 82 - } 83 75 } 84 76 } 85 77
+4 -10
server/src/server/router/whoami.gleam
··· 4 4 import server/auth 5 5 import server/context.{type Context} 6 6 import shared/session 7 - import shared/user 8 7 import wisp.{type Request, type Response} 9 8 import youid/uuid 10 9 11 10 type WhoamiError { 12 - UserError(user.UserError) 13 11 MissingToken 14 12 InvalidUuidFormat 13 + Auth(auth.AuthError) 15 14 NotFound 16 15 } 17 16 ··· 31 30 |> result.replace_error(InvalidUuidFormat), 32 31 ) 33 32 34 - user.find(ctx.db, uuid) 35 - |> result.map_error(UserError) 33 + auth.whoami(ctx.db, uuid) 34 + |> result.map_error(Auth) 36 35 } 37 36 38 37 case query_result { ··· 49 48 case err { 50 49 InvalidUuidFormat -> wisp.bad_request("Invalid Uuid format") 51 50 NotFound -> wisp.not_found() 51 + Auth(err) -> auth.handle_error(err) 52 52 53 53 MissingToken -> 54 54 "Missing token" 55 55 |> wisp.Text 56 56 |> wisp.set_body(wisp.response(401), _) 57 - 58 - UserError(err) -> 59 - case err { 60 - user.NotFound -> wisp.not_found() 61 - user.Database(_) -> wisp.internal_server_error() 62 - } 63 57 } 64 58 }
-2
shared/gleam.toml
··· 16 16 gleam_stdlib = ">= 0.44.0 and < 2.0.0" 17 17 gleam_json = ">= 3.1.0 and < 4.0.0" 18 18 youid = ">= 1.5.1 and < 2.0.0" 19 - pog = ">= 4.1.0 and < 5.0.0" 20 19 21 20 [dev-dependencies] 22 21 gleeunit = ">= 1.0.0 and < 2.0.0" 23 - squirrel = ">= 4.6.0 and < 5.0.0"
-4
shared/justfile
··· 8 8 # Lint project 9 9 lint: 10 10 gleam check 11 - 12 - # Generate queries 13 - sql: 14 - gleam run -m squirrel
-28
shared/manifest.toml
··· 2 2 # You typically do not need to edit this file 3 3 4 4 packages = [ 5 - { name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" }, 6 - { name = "backoff", version = "1.1.6", build_tools = ["rebar3"], requirements = [], otp_app = "backoff", source = "hex", outer_checksum = "CF0CFFF8995FB20562F822E5CC47D8CCF664C5ECDC26A684CBE85C225F9D7C39" }, 7 - { name = "envoy", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "850DA9D29D2E5987735872A2B5C81035146D7FE19EFC486129E44440D03FD832" }, 8 - { name = "eval", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "eval", source = "hex", outer_checksum = "264DAF4B49DF807F303CA4A4E4EBC012070429E40BE384C58FE094C4958F9BDA" }, 9 - { name = "exception", version = "2.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "exception", source = "hex", outer_checksum = "329D269D5C2A314F7364BD2711372B6F2C58FA6F39981572E5CA68624D291F8C" }, 10 - { name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" }, 11 - { name = "glam", version = "2.0.3", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "237C2CE218A2A0A5D46D625F8EF5B78F964BC91018B78D692B17E1AB84295229" }, 12 - { name = "gleam_community_ansi", version = "1.4.4", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "1B3AEA6074AB34D5F0674744F36DDC7290303A03295507E2DEC61EDD6F5777FE" }, 13 - { name = "gleam_community_colour", version = "2.0.4", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "6DB4665555D7D2B27F0EA32EF47E8BEBC4303821765F9C73D483F38EE24894F0" }, 14 5 { name = "gleam_crypto", version = "1.5.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_crypto", source = "hex", outer_checksum = "50774BAFFF1144E7872814C566C5D653D83A3EBF23ACC3156B757A1B6819086E" }, 15 - { name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" }, 16 6 { name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" }, 17 - { name = "gleam_otp", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "BA6A294E295E428EC1562DC1C11EA7530DCB981E8359134BEABC8493B7B2258E" }, 18 - { name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" }, 19 7 { name = "gleam_stdlib", version = "0.69.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "AAB0962BEBFAA67A2FBEE9EEE218B057756808DC9AF77430F5182C6115B3A315" }, 20 8 { name = "gleam_time", version = "1.7.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "56DB0EF9433826D3B99DB0B4AF7A2BFED13D09755EC64B1DAAB46F804A9AD47D" }, 21 9 { name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" }, 22 - { name = "glexer", version = "2.3.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "splitter"], otp_app = "glexer", source = "hex", outer_checksum = "41D8D2E855AEA87ADC94B7AF26A5FEA3C90268D4CF2CCBBD64FD6863714EE085" }, 23 - { name = "justin", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "justin", source = "hex", outer_checksum = "7FA0C6DB78640C6DC5FBFD59BF3456009F3F8B485BF6825E97E1EB44E9A1E2CD" }, 24 - { name = "mug", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "mug", source = "hex", outer_checksum = "C01279D98E40371DA23461774B63F0E3581B8F1396049D881B0C7EB32799D93F" }, 25 - { name = "non_empty_list", version = "2.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "non_empty_list", source = "hex", outer_checksum = "1CA43D18C07E98E9ED5A60D9CB2FFE0FF40DEFFA45D58A3FF589589F05658F7B" }, 26 - { name = "opentelemetry_api", version = "1.5.0", build_tools = ["rebar3", "mix"], requirements = [], otp_app = "opentelemetry_api", source = "hex", outer_checksum = "F53EC8A1337AE4A487D43AC89DA4BD3A3C99DDF576655D071DEED8B56A2D5DDA" }, 27 - { name = "pg_types", version = "0.6.0", build_tools = ["rebar3"], requirements = [], otp_app = "pg_types", source = "hex", outer_checksum = "9949A4849DD13408FA249AB7B745E0D2DFDB9532AEE2B9722326E33CD082A778" }, 28 - { name = "pgo", version = "0.20.0", build_tools = ["rebar3"], requirements = ["backoff", "opentelemetry_api", "pg_types"], otp_app = "pgo", source = "hex", outer_checksum = "2F11E6649CEB38E569EF56B16BE1D04874AE5B11A02867080A2817CE423C683B" }, 29 - { name = "pog", version = "4.1.0", build_tools = ["gleam"], requirements = ["exception", "gleam_erlang", "gleam_otp", "gleam_stdlib", "gleam_time", "pgo"], otp_app = "pog", source = "hex", outer_checksum = "E4AFBA39A5FAA2E77291836C9683ADE882E65A06AB28CA7D61AE7A3AD61EBBD5" }, 30 - { name = "simplifile", version = "2.3.2", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "E049B4DACD4D206D87843BCF4C775A50AE0F50A52031A2FFB40C9ED07D6EC70A" }, 31 - { name = "splitter", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "splitter", source = "hex", outer_checksum = "3DFD6B6C49E61EDAF6F7B27A42054A17CFF6CA2135FF553D0CB61C234D281DD0" }, 32 - { name = "squirrel", version = "4.6.0", build_tools = ["gleam"], requirements = ["argv", "envoy", "eval", "filepath", "glam", "gleam_community_ansi", "gleam_crypto", "gleam_json", "gleam_regexp", "gleam_stdlib", "gleam_time", "glexer", "justin", "mug", "non_empty_list", "pog", "simplifile", "term_size", "tom", "tote", "youid"], otp_app = "squirrel", source = "hex", outer_checksum = "0ED10A868BDD1A5D4B68D99CD1C72DC3F23C6E36E16D33454C5F0C31BAC9CB1E" }, 33 - { name = "term_size", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "term_size", source = "hex", outer_checksum = "D00BD2BC8FB3EBB7E6AE076F3F1FF2AC9D5ED1805F004D0896C784D06C6645F1" }, 34 - { name = "tom", version = "2.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "90791DA4AACE637E30081FE77049B8DB850FBC8CACC31515376BCC4E59BE1DD2" }, 35 - { name = "tote", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "tote", source = "hex", outer_checksum = "A249892E26A53C668897F8D47845B0007EEE07707A1A03437487F0CD5A452CA5" }, 36 10 { name = "youid", version = "1.5.1", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_stdlib", "gleam_time"], otp_app = "youid", source = "hex", outer_checksum = "580E909FD704DB16416D5CB080618EDC2DA0F1BE4D21B490C0683335E3FFC5AF" }, 37 11 ] 38 12 ··· 40 14 gleam_json = { version = ">= 3.1.0 and < 4.0.0" } 41 15 gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" } 42 16 gleeunit = { version = ">= 1.0.0 and < 2.0.0" } 43 - pog = { version = ">= 4.1.0 and < 5.0.0" } 44 - squirrel = { version = ">= 4.6.0 and < 5.0.0" } 45 17 youid = { version = ">= 1.5.1 and < 2.0.0" }
-24
shared/src/shared/user.gleam
··· 1 1 import gleam/dynamic/decode 2 2 import gleam/json 3 - import gleam/list 4 - import gleam/result 5 - import pog 6 - import shared/user/sql 7 3 import youid/uuid 8 - 9 - pub type UserError { 10 - Database(pog.QueryError) 11 - NotFound 12 - } 13 4 14 5 pub type User { 15 6 User(uuid: uuid.Uuid, full_name: String, email: String, phone: String) ··· 30 21 use email <- decode.field("email", decode.string) 31 22 use phone <- decode.field("phone", decode.string) 32 23 decode.success(User(uuid:, full_name:, email:, phone:)) 33 - } 34 - 35 - /// Query an user by Uuid 36 - pub fn find(db: pog.Connection, uuid: uuid.Uuid) -> Result(User, UserError) { 37 - use returned <- result.try( 38 - sql.find_by_id(db, uuid) 39 - |> result.map_error(Database), 40 - ) 41 - 42 - use row <- result.map( 43 - list.first(returned.rows) 44 - |> result.replace_error(NotFound), 45 - ) 46 - 47 - User(uuid:, full_name: row.full_name, email: row.email, phone: row.phone) 48 24 } 49 25 50 26 // helpers
-64
shared/src/shared/user/sql.gleam
··· 1 - //// This module contains the code to run the sql queries defined in 2 - //// `./src/shared/user/sql`. 3 - //// > ๐Ÿฟ๏ธ This module was generated automatically using v4.6.0 of 4 - //// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 5 - //// 6 - 7 - import gleam/dynamic/decode 8 - import pog 9 - import youid/uuid.{type Uuid} 10 - 11 - /// A row you get from running the `find_by_id` query 12 - /// defined in `./src/shared/user/sql/find_by_id.sql`. 13 - /// 14 - /// > ๐Ÿฟ๏ธ This type definition was generated automatically using v4.6.0 of the 15 - /// > [squirrel package](https://github.com/giacomocavalieri/squirrel). 16 - /// 17 - pub type FindByIdRow { 18 - FindByIdRow(id: Uuid, full_name: String, email: String, phone: String) 19 - } 20 - 21 - /// Runs the `find_by_id` query 22 - /// defined in `./src/shared/user/sql/find_by_id.sql`. 23 - /// 24 - /// > ๐Ÿฟ๏ธ This function was generated automatically using v4.6.0 of 25 - /// > the [squirrel package](https://github.com/giacomocavalieri/squirrel). 26 - /// 27 - pub fn find_by_id( 28 - db: pog.Connection, 29 - arg_1: Uuid, 30 - ) -> Result(pog.Returned(FindByIdRow), pog.QueryError) { 31 - let decoder = { 32 - use id <- decode.field(0, uuid_decoder()) 33 - use full_name <- decode.field(1, decode.string) 34 - use email <- decode.field(2, decode.string) 35 - use phone <- decode.field(3, decode.string) 36 - decode.success(FindByIdRow(id:, full_name:, email:, phone:)) 37 - } 38 - 39 - "select 40 - u.id, 41 - u.full_name, 42 - u.email, 43 - u.phone 44 - from public.user_account as u 45 - where u.id = 46 - $1; 47 - " 48 - |> pog.query 49 - |> pog.parameter(pog.text(uuid.to_string(arg_1))) 50 - |> pog.returning(decoder) 51 - |> pog.execute(db) 52 - } 53 - 54 - // --- Encoding/decoding utils ------------------------------------------------- 55 - 56 - /// A decoder to decode `Uuid`s coming from a Postgres query. 57 - /// 58 - fn uuid_decoder() { 59 - use bit_array <- decode.then(decode.bit_array) 60 - case uuid.from_bit_array(bit_array) { 61 - Ok(uuid) -> decode.success(uuid) 62 - Error(_) -> decode.failure(uuid.v7(), "Uuid") 63 - } 64 - }
+1 -1
shared/src/shared/user/sql/find_by_id.sql server/src/server/auth/sql/whoami.sql
··· 5 5 u.phone 6 6 from public.user_account as u 7 7 where u.id = 8 - $1; 8 + $1 ;