wip: currently rewriting the project as a full stack application tangled.org/kacaii.dev/sigo
gleam

:recycle: use `json.array` instead of `json.preprocessed_array`

+94 -111
+16 -17
src/app/domain/brigade/get_all_brigades.gleam
··· 3 3 import app/web/context.{type Context} 4 4 import gleam/http 5 5 import gleam/json 6 - import gleam/list 7 6 import gleam/result 8 7 import pog 9 8 import wisp ··· 20 19 /// [ 21 20 /// { 22 21 /// "id": "c3d4e5f6-g7h8-9012-cdef-345678901234", 23 - /// "name": "Brigada A", 22 + /// "brigade_name": "Brigada A", 24 23 /// "leader_name": "Pedro Anthony", 25 24 /// "is_active": true, 26 25 /// }, 27 26 /// { 28 27 /// "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", 29 - /// "name": "Brigada B", 28 + /// "brigade_name": "Brigada B", 30 29 /// "leader_name": "Anderson Silva", 31 30 /// "is_active": false, 32 31 /// } ··· 38 37 ) -> wisp.Response { 39 38 use <- wisp.require_method(req, http.Get) 40 39 41 - case query_database(ctx:) { 40 + case query_database(ctx) { 42 41 Error(err) -> handle_error(err) 43 42 Ok(resp) -> wisp.json_response(resp, 200) 44 43 } ··· 50 49 } 51 50 } 52 51 53 - fn query_database(ctx ctx: Context) -> Result(String, QueryAllBrigadesError) { 54 - use returned <- result.try( 52 + fn query_database(ctx: Context) -> Result(String, QueryAllBrigadesError) { 53 + use returned <- result.map( 55 54 sql.query_all_brigades(ctx.db) 56 55 |> result.map_error(DataBase), 57 56 ) 58 57 59 - // 󰅨 Return JSON array 60 - json.preprocessed_array({ 61 - use row <- list.map(returned.rows) 62 - json.object([ 63 - #("id", json.string(uuid.to_string(row.id))), 64 - #("brigade_name", json.string(row.brigade_name)), 65 - #("leader_name", json.nullable(row.leader_name, json.string)), 66 - #("is_active", json.bool(row.is_active)), 67 - ]) 68 - }) 58 + returned.rows 59 + |> json.array(row_to_json) 69 60 |> json.to_string 70 - |> Ok 61 + } 62 + 63 + fn row_to_json(row: sql.QueryAllBrigadesRow) { 64 + json.object([ 65 + #("id", json.string(uuid.to_string(row.id))), 66 + #("brigade_name", json.string(row.brigade_name)), 67 + #("leader_name", json.nullable(row.leader_name, json.string)), 68 + #("is_active", json.bool(row.is_active)), 69 + ]) 71 70 } 72 71 73 72 /// 󰤏 Querying a brigade can fail
+22 -23
src/app/domain/brigade/get_brigade_members.gleam
··· 9 9 import app/web/context.{type Context} 10 10 import gleam/http 11 11 import gleam/json 12 - import gleam/list 13 12 import gleam/result 14 13 import pog 15 14 import wisp ··· 77 76 |> result.replace_error(InvalidUUID(brigade_id)), 78 77 ) 79 78 80 - use returned <- result.try( 79 + use returned <- result.map( 81 80 sql.query_members_info(ctx.db, brigade_uuid) 82 81 |> result.map_error(DataBase), 83 82 ) 84 83 85 - // Building response body 86 - json.preprocessed_array({ 87 - use row <- list.map(returned.rows) 88 - let user_role = 89 - case row.user_role { 90 - sql.Admin -> role.Admin 91 - sql.Analyst -> role.Analyst 92 - sql.Captain -> role.Captain 93 - sql.Developer -> role.Developer 94 - sql.Firefighter -> role.Firefighter 95 - sql.Sargeant -> role.Sargeant 96 - } 97 - |> role.to_string_pt_br() 98 - 99 - json.object([ 100 - #("id", json.string(uuid.to_string(row.id))), 101 - #("full_name", json.string(row.full_name)), 102 - #("user_role", json.string(user_role)), 103 - ]) 104 - }) 84 + returned.rows 85 + |> json.array(row_to_json) 105 86 |> json.to_string 106 - |> Ok 87 + } 88 + 89 + fn row_to_json(row: sql.QueryMembersInfoRow) -> json.Json { 90 + let user_role = 91 + case row.user_role { 92 + sql.Admin -> role.Admin 93 + sql.Analyst -> role.Analyst 94 + sql.Captain -> role.Captain 95 + sql.Developer -> role.Developer 96 + sql.Firefighter -> role.Firefighter 97 + sql.Sargeant -> role.Sargeant 98 + } 99 + |> role.to_string_pt_br() 100 + 101 + json.object([ 102 + #("id", json.string(uuid.to_string(row.id))), 103 + #("full_name", json.string(row.full_name)), 104 + #("user_role", json.string(user_role)), 105 + ]) 107 106 }
+16 -18
src/app/domain/occurrence/get_ocurrences_by_applicant.gleam
··· 28 28 ) -> wisp.Response { 29 29 use <- wisp.require_method(request, http.Get) 30 30 31 - case query_occurrences(ctx:, user_id:) { 31 + case query_occurrences(ctx, user_id) { 32 32 Ok(resp) -> wisp.json_response(resp, 200) 33 33 Error(err) -> handle_error(err) 34 34 } 35 35 } 36 36 37 37 fn query_occurrences( 38 - ctx ctx: Context, 39 - user_id user_id: String, 38 + ctx: Context, 39 + user_id: String, 40 40 ) -> Result(String, GetOccurrencesByApplicantError) { 41 41 use user_uuid <- result.try( 42 42 uuid.from_string(user_id) ··· 51 51 let payload_result = { 52 52 use row <- list.try_map(returned.rows) 53 53 54 - // DECODER FOR BRIGADES 55 54 use brigade_list <- result.map( 56 55 brigade_list_decoder(row.brigade_list) 57 56 |> result.map_error(BrigadeListDecodeError), ··· 86 85 } 87 86 88 87 case payload_result { 89 - Ok(value) -> Ok(json.preprocessed_array(value) |> json.to_string) 88 + Ok(payload) -> 89 + json.preprocessed_array(payload) 90 + |> json.to_string 91 + |> Ok 92 + 90 93 Error(value) -> Error(value) 91 94 } 92 95 } ··· 95 98 data: String, 96 99 ) -> Result(List(PayloadBrigade), json.DecodeError) { 97 100 json.parse(data, { 98 - // UUID Decoder 99 101 let brigade_uuid_decoder = { 100 102 use maybe_uuid <- decode.then(decode.string) 101 103 case uuid.from_string(maybe_uuid) { ··· 199 201 #("coordenadas", occurrence_location_json), 200 202 #("timestamps", payload_timestamp_to_json(data.timestamp)), 201 203 #("metadata", payload_metadata_to_json(data.metadata)), 202 - #("equipes", payload_brigade_list_to_json(data.brigade_list)), 204 + #("equipes", json.array(data.brigade_list, payload_brigade_to_json)), 203 205 ]) 204 206 } 205 207 ··· 290 292 ) 291 293 } 292 294 293 - fn payload_brigade_list_to_json(data: List(PayloadBrigade)) -> json.Json { 294 - json.preprocessed_array( 295 - list.map(data, fn(row) { 296 - json.object([ 297 - #("id", json.string(uuid.to_string(row.id))), 298 - #("nomeEquipe", json.string(row.brigade_name)), 299 - #("lider", json.string(row.leader_name)), 300 - #("codigoViatura", json.string(row.vehicle_code)), 301 - ]) 302 - }), 303 - ) 295 + fn payload_brigade_to_json(row: PayloadBrigade) -> json.Json { 296 + json.object([ 297 + #("id", json.string(uuid.to_string(row.id))), 298 + #("nomeEquipe", json.string(row.brigade_name)), 299 + #("lider", json.string(row.leader_name)), 300 + #("codigoViatura", json.string(row.vehicle_code)), 301 + ]) 304 302 }
+10 -7
src/app/domain/role.gleam
··· 1 1 import gleam/dynamic/decode 2 2 import gleam/json 3 - import gleam/list 4 3 import gleam/string 5 4 import glight 6 5 import wisp ··· 78 77 user_role user_role: Role, 79 78 required required: List(Role), 80 79 ) -> Nil { 81 - let required_roles_string = 82 - json.preprocessed_array({ 83 - use user_role <- list.map(required) 84 - json.string(to_string(user_role)) 85 - }) 80 + let required_roles = 81 + required 82 + |> json.array(to_json) 86 83 |> json.to_string 87 84 88 85 glight.logger() 89 86 |> glight.with("path", request.path) 90 87 |> glight.with("user", uuid.to_string(user_uuid)) 91 88 |> glight.with("role", to_string(user_role)) 92 - |> glight.with("required", required_roles_string) 89 + |> glight.with("required", required_roles) 93 90 |> glight.notice("unauthorized_access_attempt") 94 91 95 92 Nil 96 93 } 94 + 95 + pub fn to_json(role: Role) -> json.Json { 96 + role 97 + |> to_string 98 + |> json.string 99 + }
+12 -18
src/app/domain/role/get_role_list.gleam
··· 4 4 import app/web/context.{type Context} 5 5 import gleam/http 6 6 import gleam/json 7 - import gleam/list 8 7 import gleam/result 9 8 import pog 10 9 import wisp ··· 23 22 ) -> wisp.Response { 24 23 use <- wisp.require_method(request, http.Get) 25 24 26 - // 󰡦 Find available roles 27 25 case query_user_roles(ctx) { 28 - // Send data back to the Client 29 - Ok(role_list) -> wisp.json_response(json.to_string(role_list), 200) 30 - 31 - // Handle possible errors 26 + Ok(body) -> wisp.json_response(body, 200) 32 27 Error(err) -> handle_error(err) 33 28 } 34 29 } ··· 46 41 } 47 42 48 43 /// 󰆼 Queries the database to collect all available role names 49 - fn query_user_roles(ctx: Context) -> Result(json.Json, GetRoleListError) { 50 - use returned <- result.try( 44 + fn query_user_roles(ctx: Context) -> Result(String, GetRoleListError) { 45 + use returned <- result.map( 51 46 sql.query_available_user_roles(ctx.db) 52 47 |> result.map_error(DataBase), 53 48 ) 54 49 55 - let available_roles = 56 - { 57 - use row <- list.map(returned.rows) 58 - row.available_role 59 - |> enum_to_role() 60 - |> role.to_string_pt_br() 61 - |> json.string 62 - } 63 - |> json.preprocessed_array 50 + returned.rows 51 + |> json.array(row_to_json) 52 + |> json.to_string 53 + } 64 54 65 - Ok(available_roles) 55 + fn row_to_json(row: sql.QueryAvailableUserRolesRow) -> json.Json { 56 + row.available_role 57 + |> enum_to_role() 58 + |> role.to_string_pt_br() 59 + |> json.string 66 60 } 67 61 68 62 fn enum_to_role(user_role: sql.UserRoleEnum) -> role.Role {
+3 -7
src/app/domain/user/get_all_user_profiles.gleam
··· 5 5 import app/web/context.{type Context} 6 6 import gleam/http 7 7 import gleam/json 8 - import gleam/list 9 8 import gleam/result 10 9 import pog 11 10 import wisp ··· 76 75 |> result.map_error(AccessControl), 77 76 ) 78 77 79 - use returned <- result.try( 78 + use returned <- result.map( 80 79 sql.get_complete_user_profiles(ctx.db) 81 80 |> result.map_error(DataBase), 82 81 ) 83 82 84 - json.preprocessed_array({ 85 - use row <- list.map(returned.rows) 86 - row_to_json(row) 87 - }) 83 + returned.rows 84 + |> json.array(row_to_json) 88 85 |> json.to_string 89 - |> Ok 90 86 } 91 87 92 88 fn row_to_json(row: sql.GetCompleteUserProfilesRow) -> json.Json {
+15 -21
src/app/domain/user/get_crew_members.gleam
··· 6 6 import app/web/context.{type Context} 7 7 import gleam/http 8 8 import gleam/json 9 - import gleam/list 10 9 import gleam/result 11 10 import pog 12 11 import wisp ··· 52 51 } 53 52 } 54 53 54 + type GetCrewMembersError { 55 + /// User has invalid Uuid fornmat 56 + InvalidUUID(String) 57 + /// An error occurred while accessing the DataBase 58 + DataBase(pog.QueryError) 59 + } 60 + 55 61 fn try_query_database( 56 62 ctx ctx: Context, 57 63 user_id user_id: String, ··· 61 67 |> result.replace_error(InvalidUUID(user_id)), 62 68 ) 63 69 64 - use returned <- result.try( 70 + use returned <- result.map( 65 71 sql.query_crew_members(ctx.db, user_uuid) 66 72 |> result.map_error(DataBase), 67 73 ) 68 74 69 - let fellow_members_list = { 70 - use fellow_brigade_member <- list.map(returned.rows) 71 - get_crew_members_row_to_json(fellow_brigade_member) 72 - } 73 - 74 - json.preprocessed_array(fellow_members_list) 75 + returned.rows 76 + |> json.array(row_to_json) 75 77 |> json.to_string 76 - |> Ok 77 78 } 78 79 79 - fn get_crew_members_row_to_json(row: sql.QueryCrewMembersRow) -> json.Json { 80 + fn row_to_json(row: sql.QueryCrewMembersRow) -> json.Json { 80 81 let role_name = 81 - role.to_string_pt_br(case row.user_role { 82 + case row.user_role { 82 83 sql.Admin -> role.Admin 83 84 sql.Analyst -> role.Analyst 84 85 sql.Captain -> role.Captain 85 86 sql.Developer -> role.Developer 86 87 sql.Firefighter -> role.Firefighter 87 88 sql.Sargeant -> role.Sargeant 88 - }) 89 + } 90 + |> role.to_string_pt_br 89 91 90 92 json.object([ 91 93 #("id", json.string(uuid.to_string(row.id))), ··· 95 97 ]) 96 98 } 97 99 98 - fn handle_err(err: GetCrewMembersError) { 100 + fn handle_err(err: GetCrewMembersError) -> wisp.Response { 99 101 case err { 100 102 InvalidUUID(id) -> wisp.bad_request("ID de usuário inválido: " <> id) 101 103 DataBase(err) -> web.handle_database_error(err) 102 104 } 103 105 } 104 - 105 - /// Finding the user's crew can fail 106 - type GetCrewMembersError { 107 - /// User has invalid Uuid fornmat 108 - InvalidUUID(String) 109 - /// An error occurred while accessing the DataBase 110 - DataBase(pog.QueryError) 111 - }