+4
-1
README.md
+4
-1
README.md
···
131
131
132
132
## Examples
133
133
134
-
See the [example/](./example/) directory for a complete working example.
134
+
See the [examples/](./examples/) directory for complete working examples:
135
+
136
+
- **[01-basic](./examples/01-basic/)** - Basic usage with Erlang/JavaScript targets
137
+
- **[02-lustre](./examples/02-lustre/)** - Frontend app using Lustre
135
138
136
139
## Roadmap
137
140
example/README.md
examples/01-basic/README.md
example/README.md
examples/01-basic/README.md
+1
-1
example/gleam.toml
examples/01-basic/gleam.toml
+1
-1
example/gleam.toml
examples/01-basic/gleam.toml
+4
-6
example/manifest.toml
examples/01-basic/manifest.toml
+4
-6
example/manifest.toml
examples/01-basic/manifest.toml
···
6
6
{ name = "filepath", version = "1.1.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "filepath", source = "hex", outer_checksum = "B06A9AF0BF10E51401D64B98E4B627F1D2E48C154967DA7AF4D0914780A6D40A" },
7
7
{ name = "glam", version = "2.0.3", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "glam", source = "hex", outer_checksum = "237C2CE218A2A0A5D46D625F8EF5B78F964BC91018B78D692B17E1AB84295229" },
8
8
{ name = "gleam_erlang", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_erlang", source = "hex", outer_checksum = "1124AD3AA21143E5AF0FC5CF3D9529F6DB8CA03E43A55711B60B6B7B3874375C" },
9
-
{ name = "gleam_fetch", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_javascript", "gleam_stdlib"], otp_app = "gleam_fetch", source = "hex", outer_checksum = "2CBF9F2E1C71AEBBFB13A9D5720CD8DB4263EB02FE60C5A7A1C6E17B0151C20C" },
10
9
{ name = "gleam_http", version = "4.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "82EA6A717C842456188C190AFB372665EA56CE13D8559BF3B1DD9E40F619EE0C" },
11
10
{ name = "gleam_httpc", version = "5.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C545172618D07811494E97AAA4A0FB34DA6F6D0061FDC8041C2F8E3BE2B2E48F" },
12
-
{ name = "gleam_javascript", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "EF6C77A506F026C6FB37941889477CD5E4234FCD4337FF0E9384E297CB8F97EB" },
13
-
{ name = "gleam_json", version = "3.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "874FA3C3BB6E22DD2BB111966BD40B3759E9094E05257899A7C08F5DE77EC049" },
11
+
{ name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" },
14
12
{ name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" },
15
13
{ name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" },
16
14
{ name = "simplifile", version = "2.3.1", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "957E0E5B75927659F1D2A1B7B75D7B9BA96FAA8D0C53EA71C4AD9CD0C6B848F6" },
17
-
{ name = "squall", version = "0.1.0", build_tools = ["gleam"], requirements = ["argv", "filepath", "glam", "gleam_fetch", "gleam_http", "gleam_httpc", "gleam_javascript", "gleam_json", "gleam_stdlib", "simplifile", "swell"], source = "local", path = ".." },
18
-
{ name = "swell", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "swell", source = "hex", outer_checksum = "7CCA8C61349396C5B59B3C0627185F5B30917044E0D61CB7E0E5CC75C1B4A8E9" },
15
+
{ name = "squall", version = "1.0.0", build_tools = ["gleam"], requirements = ["argv", "filepath", "glam", "gleam_http", "gleam_httpc", "gleam_json", "gleam_stdlib", "simplifile", "swell"], source = "local", path = "../.." },
16
+
{ name = "swell", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "swell", source = "hex", outer_checksum = "CA28A95AB9A01E51D1FCFC0FC4F7102C7F47D04B9711138248D08C2A9F1FE6A3" },
19
17
]
20
18
21
19
[requirements]
···
24
22
gleam_json = { version = ">= 3.0.0 and < 4.0.0" }
25
23
gleam_stdlib = { version = ">= 0.34.0 and < 2.0.0" }
26
24
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
27
-
squall = { path = "../" }
25
+
squall = { path = "../../" }
example/src/example.gleam
examples/01-basic/src/example.gleam
example/src/example.gleam
examples/01-basic/src/example.gleam
example/src/graphql/get_character.gleam
examples/01-basic/src/graphql/get_character.gleam
example/src/graphql/get_character.gleam
examples/01-basic/src/graphql/get_character.gleam
example/src/graphql/get_character.gql
examples/01-basic/src/graphql/get_character.gql
example/src/graphql/get_character.gql
examples/01-basic/src/graphql/get_character.gql
example/src/graphql/get_character_with_fragment.gleam
examples/01-basic/src/graphql/get_character_with_fragment.gleam
example/src/graphql/get_character_with_fragment.gleam
examples/01-basic/src/graphql/get_character_with_fragment.gleam
example/src/graphql/get_character_with_fragment.gql
examples/01-basic/src/graphql/get_character_with_fragment.gql
example/src/graphql/get_character_with_fragment.gql
examples/01-basic/src/graphql/get_character_with_fragment.gql
+5
examples/02-lustre/README.md
+5
examples/02-lustre/README.md
+28
examples/02-lustre/gleam.toml
+28
examples/02-lustre/gleam.toml
···
1
+
name = "lustre_example"
2
+
version = "1.0.0"
3
+
target = "javascript"
4
+
5
+
# Fill out these fields if you intend to generate HTML documentation or publish
6
+
# your project to the Hex package manager.
7
+
#
8
+
# description = ""
9
+
# licences = ["Apache-2.0"]
10
+
# repository = { type = "github", user = "", repo = "" }
11
+
# links = [{ title = "Website", href = "" }]
12
+
#
13
+
# For a full reference of all the available options, you can have a look at
14
+
# https://gleam.run/writing-gleam/gleam-toml/.
15
+
16
+
[dependencies]
17
+
gleam_stdlib = ">= 0.44.0 and < 2.0.0"
18
+
lustre = ">= 5.0.0 and < 6.0.0"
19
+
lustre_http = ">= 1.0.0 and < 2.0.0"
20
+
gleam_json = ">= 3.0.0 and < 4.0.0"
21
+
gleam_http = ">= 4.3.0 and < 5.0.0"
22
+
gleam_fetch = ">= 1.0.0 and < 2.0.0"
23
+
squall = { path = "../../" }
24
+
gleam_javascript = ">= 1.0.0 and < 2.0.0"
25
+
26
+
[dev-dependencies]
27
+
gleeunit = ">= 1.0.0 and < 2.0.0"
28
+
lustre_dev_tools = ">= 2.2.2 and < 3.0.0"
+15
examples/02-lustre/index.html
+15
examples/02-lustre/index.html
···
1
+
<!DOCTYPE html>
2
+
<html lang="en">
3
+
<head>
4
+
<meta charset="UTF-8">
5
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+
<title>Rick and Morty Characters - Lustre + Squall</title>
7
+
</head>
8
+
<body>
9
+
<div id="app"></div>
10
+
<script type="module">
11
+
import { main } from "./build/dev/javascript/lustre_example/lustre_example.mjs";
12
+
main();
13
+
</script>
14
+
</body>
15
+
</html>
+61
examples/02-lustre/manifest.toml
+61
examples/02-lustre/manifest.toml
···
1
+
# This file was generated by Gleam
2
+
# You typically do not need to edit this file
3
+
4
+
packages = [
5
+
{ name = "argv", version = "1.0.2", build_tools = ["gleam"], requirements = [], otp_app = "argv", source = "hex", outer_checksum = "BA1FF0929525DEBA1CE67256E5ADF77A7CDDFE729E3E3F57A5BDCAA031DED09D" },
6
+
{ name = "booklet", version = "1.1.0", build_tools = ["gleam"], requirements = [], otp_app = "booklet", source = "hex", outer_checksum = "08E0FDB78DC4D8A5D3C80295B021505C7D2A2E7B6C6D5EAB7286C36F4A53C851" },
7
+
{ name = "directories", version = "1.2.0", build_tools = ["gleam"], requirements = ["envoy", "gleam_stdlib", "platform", "simplifile"], otp_app = "directories", source = "hex", outer_checksum = "D13090CFCDF6759B87217E8DDD73A75903A700148A82C1D33799F333E249BF9E" },
8
+
{ name = "envoy", version = "1.0.2", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "envoy", source = "hex", outer_checksum = "95FD059345AA982E89A0B6E2A3BF1CF43E17A7048DCD85B5B65D3B9E4E39D359" },
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.3", build_tools = ["gleam"], requirements = ["gleam_community_colour", "gleam_regexp", "gleam_stdlib"], otp_app = "gleam_community_ansi", source = "hex", outer_checksum = "8A62AE9CC6EA65BEA630D95016D6C07E4F9973565FA3D0DE68DC4200D8E0DD27" },
13
+
{ name = "gleam_community_colour", version = "2.0.2", build_tools = ["gleam"], requirements = ["gleam_json", "gleam_stdlib"], otp_app = "gleam_community_colour", source = "hex", outer_checksum = "E34DD2C896AC3792151EDA939DA435FF3B69922F33415ED3C4406C932FBE9634" },
14
+
{ 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
+
{ name = "gleam_fetch", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_http", "gleam_javascript", "gleam_stdlib"], otp_app = "gleam_fetch", source = "hex", outer_checksum = "2CBF9F2E1C71AEBBFB13A9D5720CD8DB4263EB02FE60C5A7A1C6E17B0151C20C" },
17
+
{ name = "gleam_http", version = "4.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_http", source = "hex", outer_checksum = "82EA6A717C842456188C190AFB372665EA56CE13D8559BF3B1DD9E40F619EE0C" },
18
+
{ name = "gleam_httpc", version = "5.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gleam_httpc", source = "hex", outer_checksum = "C545172618D07811494E97AAA4A0FB34DA6F6D0061FDC8041C2F8E3BE2B2E48F" },
19
+
{ name = "gleam_javascript", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_javascript", source = "hex", outer_checksum = "EF6C77A506F026C6FB37941889477CD5E4234FCD4337FF0E9384E297CB8F97EB" },
20
+
{ name = "gleam_json", version = "3.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_json", source = "hex", outer_checksum = "44FDAA8847BE8FC48CA7A1C089706BD54BADCC4C45B237A992EDDF9F2CDB2836" },
21
+
{ name = "gleam_otp", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_stdlib"], otp_app = "gleam_otp", source = "hex", outer_checksum = "BA6A294E295E428EC1562DC1C11EA7530DCB981E8359134BEABC8493B7B2258E" },
22
+
{ name = "gleam_regexp", version = "1.1.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_regexp", source = "hex", outer_checksum = "9C215C6CA84A5B35BB934A9B61A9A306EC743153BE2B0425A0D032E477B062A9" },
23
+
{ name = "gleam_stdlib", version = "0.65.0", build_tools = ["gleam"], requirements = [], otp_app = "gleam_stdlib", source = "hex", outer_checksum = "7C69C71D8C493AE11A5184828A77110EB05A7786EBF8B25B36A72F879C3EE107" },
24
+
{ name = "gleam_time", version = "1.5.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_time", source = "hex", outer_checksum = "D560E672C7279C89908981E068DF07FD16D0C859DCA266F908B18F04DF0EB8E6" },
25
+
{ name = "gleam_yielder", version = "1.1.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleam_yielder", source = "hex", outer_checksum = "8E4E4ECFA7982859F430C57F549200C7749823C106759F4A19A78AEA6687717A" },
26
+
{ name = "gleeunit", version = "1.9.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "gleeunit", source = "hex", outer_checksum = "DA9553CE58B67924B3C631F96FE3370C49EB6D6DC6B384EC4862CC4AAA718F3C" },
27
+
{ name = "glint", version = "1.2.1", build_tools = ["gleam"], requirements = ["gleam_community_ansi", "gleam_community_colour", "gleam_stdlib", "snag"], otp_app = "glint", source = "hex", outer_checksum = "2214C7CEFDE457CEE62140C3D4899B964E05236DA74E4243DFADF4AF29C382BB" },
28
+
{ name = "glisten", version = "8.0.1", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib", "logging", "telemetry"], otp_app = "glisten", source = "hex", outer_checksum = "534BB27C71FB9E506345A767C0D76B17A9E9199934340C975DC003C710E3692D" },
29
+
{ name = "gramps", version = "6.0.0", build_tools = ["gleam"], requirements = ["gleam_crypto", "gleam_erlang", "gleam_http", "gleam_stdlib"], otp_app = "gramps", source = "hex", outer_checksum = "8B7195978FBFD30B43DF791A8A272041B81E45D245314D7A41FC57237AA882A0" },
30
+
{ name = "group_registry", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_otp", "gleam_stdlib"], otp_app = "group_registry", source = "hex", outer_checksum = "BC798A53D6F2406DB94E27CB45C57052CB56B32ACF7CC16EA20F6BAEC7E36B90" },
31
+
{ name = "houdini", version = "1.2.0", build_tools = ["gleam"], requirements = [], otp_app = "houdini", source = "hex", outer_checksum = "5DB1053F1AF828049C2B206D4403C18970ABEF5C18671CA3C2D2ED0DD64F6385" },
32
+
{ name = "hpack_erl", version = "0.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "hpack", source = "hex", outer_checksum = "D6137D7079169D8C485C6962DFE261AF5B9EF60FBC557344511C1E65E3D95FB0" },
33
+
{ name = "justin", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "justin", source = "hex", outer_checksum = "7FA0C6DB78640C6DC5FBFD59BF3456009F3F8B485BF6825E97E1EB44E9A1E2CD" },
34
+
{ name = "logging", version = "1.3.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "logging", source = "hex", outer_checksum = "1098FBF10B54B44C2C7FDF0B01C1253CAFACDACABEFB4B0D027803246753E06D" },
35
+
{ name = "lustre", version = "5.4.0", build_tools = ["gleam"], requirements = ["gleam_erlang", "gleam_json", "gleam_otp", "gleam_stdlib", "houdini"], otp_app = "lustre", source = "hex", outer_checksum = "40E097BABCE65FB7C460C073078611F7F5802EB07E1A9BFB5C229F71B60F8E50" },
36
+
{ name = "lustre_dev_tools", version = "2.2.2", build_tools = ["gleam"], requirements = ["argv", "booklet", "filepath", "gleam_community_ansi", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_httpc", "gleam_json", "gleam_otp", "gleam_regexp", "gleam_stdlib", "glint", "group_registry", "justin", "lustre", "mist", "polly", "simplifile", "tom", "wisp"], otp_app = "lustre_dev_tools", source = "hex", outer_checksum = "C66A09B0B268B596F021971E4E4111E4B2B4A1DF5BDFE6C28A1E1FE4CA371F1A" },
37
+
{ name = "lustre_http", version = "1.0.0", build_tools = ["gleam"], requirements = ["gleam_fetch", "gleam_http", "gleam_javascript", "gleam_json", "gleam_stdlib", "lustre"], otp_app = "lustre_http", source = "hex", outer_checksum = "FA293FECBC779074C18E3F74D6668D1F13841899283C87B8C358BB6572D25498" },
38
+
{ name = "marceau", version = "1.3.0", build_tools = ["gleam"], requirements = [], otp_app = "marceau", source = "hex", outer_checksum = "2D1C27504BEF45005F5DFB18591F8610FB4BFA91744878210BDC464412EC44E9" },
39
+
{ name = "mist", version = "5.0.3", 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 = "7C4BE717A81305323C47C8A591E6B9BA4AC7F56354BF70B4D3DF08CC01192668" },
40
+
{ name = "platform", version = "1.0.0", build_tools = ["gleam"], requirements = [], otp_app = "platform", source = "hex", outer_checksum = "8339420A95AD89AAC0F82F4C3DB8DD401041742D6C3F46132A8739F6AEB75391" },
41
+
{ name = "polly", version = "2.1.0", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib", "simplifile"], otp_app = "polly", source = "hex", outer_checksum = "1BA4D0ACE9BCF52AEA6AD9DE020FD8220CCA399A379E50A1775FC5C1204FCF56" },
42
+
{ name = "simplifile", version = "2.3.1", build_tools = ["gleam"], requirements = ["filepath", "gleam_stdlib"], otp_app = "simplifile", source = "hex", outer_checksum = "957E0E5B75927659F1D2A1B7B75D7B9BA96FAA8D0C53EA71C4AD9CD0C6B848F6" },
43
+
{ name = "snag", version = "1.2.0", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "snag", source = "hex", outer_checksum = "274F41D6C3ECF99F7686FDCE54183333E41D2C1CA5A3A673F9A8B2C7A4401077" },
44
+
{ name = "squall", version = "1.0.0", build_tools = ["gleam"], requirements = ["argv", "filepath", "glam", "gleam_http", "gleam_httpc", "gleam_json", "gleam_stdlib", "simplifile", "swell"], source = "local", path = "../.." },
45
+
{ name = "swell", version = "1.0.1", build_tools = ["gleam"], requirements = ["gleam_stdlib"], otp_app = "swell", source = "hex", outer_checksum = "CA28A95AB9A01E51D1FCFC0FC4F7102C7F47D04B9711138248D08C2A9F1FE6A3" },
46
+
{ name = "telemetry", version = "1.3.0", build_tools = ["rebar3"], requirements = [], otp_app = "telemetry", source = "hex", outer_checksum = "7015FC8919DBE63764F4B4B87A95B7C0996BD539E0D499BE6EC9D7F3875B79E6" },
47
+
{ name = "tom", version = "2.0.0", build_tools = ["gleam"], requirements = ["gleam_stdlib", "gleam_time"], otp_app = "tom", source = "hex", outer_checksum = "74D0C5A3761F7A7D06994755D4D5AD854122EF8E9F9F76A3E7547606D8C77091" },
48
+
{ name = "wisp", version = "2.1.0", build_tools = ["gleam"], requirements = ["directories", "exception", "filepath", "gleam_crypto", "gleam_erlang", "gleam_http", "gleam_json", "gleam_stdlib", "houdini", "logging", "marceau", "mist", "simplifile"], otp_app = "wisp", source = "hex", outer_checksum = "362BDDD11BF48EB38CDE51A73BC7D1B89581B395CA998E3F23F11EC026151C54" },
49
+
]
50
+
51
+
[requirements]
52
+
gleam_fetch = { version = ">= 1.0.0 and < 2.0.0" }
53
+
gleam_http = { version = ">= 4.3.0 and < 5.0.0" }
54
+
gleam_javascript = { version = ">= 1.0.0 and < 2.0.0" }
55
+
gleam_json = { version = ">= 3.0.0 and < 4.0.0" }
56
+
gleam_stdlib = { version = ">= 0.44.0 and < 2.0.0" }
57
+
gleeunit = { version = ">= 1.0.0 and < 2.0.0" }
58
+
lustre = { version = ">= 5.0.0 and < 6.0.0" }
59
+
lustre_dev_tools = { version = ">= 2.2.2 and < 3.0.0" }
60
+
lustre_http = { version = ">= 1.0.0 and < 2.0.0" }
61
+
squall = { path = "../../" }
+90
examples/02-lustre/src/graphql/get_characters.gleam
+90
examples/02-lustre/src/graphql/get_characters.gleam
···
1
+
import gleam/dynamic/decode
2
+
import gleam/http/request.{type Request}
3
+
import gleam/json
4
+
import gleam/option.{type Option}
5
+
import squall
6
+
7
+
pub type Characters {
8
+
Characters(results: Option(List(Character)))
9
+
}
10
+
11
+
pub fn characters_decoder() -> decode.Decoder(Characters) {
12
+
use results <- decode.field(
13
+
"results",
14
+
decode.optional(decode.list(character_decoder())),
15
+
)
16
+
decode.success(Characters(results: results))
17
+
}
18
+
19
+
pub type Character {
20
+
Character(
21
+
id: Option(String),
22
+
name: Option(String),
23
+
status: Option(String),
24
+
species: Option(String),
25
+
)
26
+
}
27
+
28
+
pub fn character_decoder() -> decode.Decoder(Character) {
29
+
use id <- decode.field("id", decode.optional(decode.string))
30
+
use name <- decode.field("name", decode.optional(decode.string))
31
+
use status <- decode.field("status", decode.optional(decode.string))
32
+
use species <- decode.field("species", decode.optional(decode.string))
33
+
decode.success(Character(id: id, name: name, status: status, species: species))
34
+
}
35
+
36
+
pub fn characters_to_json(input: Characters) -> json.Json {
37
+
json.object([
38
+
#(
39
+
"results",
40
+
json.nullable(input.results, fn(list) {
41
+
json.array(from: list, of: character_to_json)
42
+
}),
43
+
),
44
+
])
45
+
}
46
+
47
+
pub fn character_to_json(input: Character) -> json.Json {
48
+
json.object([
49
+
#("id", json.nullable(input.id, json.string)),
50
+
#("name", json.nullable(input.name, json.string)),
51
+
#("status", json.nullable(input.status, json.string)),
52
+
#("species", json.nullable(input.species, json.string)),
53
+
])
54
+
}
55
+
56
+
pub type GetCharactersResponse {
57
+
GetCharactersResponse(characters: Option(Characters))
58
+
}
59
+
60
+
pub fn get_characters_response_decoder() -> decode.Decoder(
61
+
GetCharactersResponse,
62
+
) {
63
+
use characters <- decode.field(
64
+
"characters",
65
+
decode.optional(characters_decoder()),
66
+
)
67
+
decode.success(GetCharactersResponse(characters: characters))
68
+
}
69
+
70
+
pub fn get_characters_response_to_json(
71
+
input: GetCharactersResponse,
72
+
) -> json.Json {
73
+
json.object([
74
+
#("characters", json.nullable(input.characters, characters_to_json)),
75
+
])
76
+
}
77
+
78
+
pub fn get_characters(client: squall.Client) -> Result(Request(String), String) {
79
+
squall.prepare_request(
80
+
client,
81
+
"query GetCharacters {\n characters {\n results {\n id\n name\n status\n species\n }\n }\n}\n",
82
+
json.object([]),
83
+
)
84
+
}
85
+
86
+
pub fn parse_get_characters_response(
87
+
body: String,
88
+
) -> Result(GetCharactersResponse, String) {
89
+
squall.parse_response(body, get_characters_response_decoder())
90
+
}
+10
examples/02-lustre/src/graphql/get_characters.gql
+10
examples/02-lustre/src/graphql/get_characters.gql
+139
examples/02-lustre/src/lustre_example.gleam
+139
examples/02-lustre/src/lustre_example.gleam
···
1
+
import gleam/fetch
2
+
import gleam/javascript/promise
3
+
import gleam/list
4
+
import gleam/option.{None, Some}
5
+
import graphql/get_characters
6
+
import lustre
7
+
import lustre/attribute
8
+
import lustre/effect.{type Effect}
9
+
import lustre/element.{type Element}
10
+
import lustre/element/html
11
+
import squall
12
+
13
+
pub fn main() {
14
+
let app = lustre.application(init, update, view)
15
+
let assert Ok(_) = lustre.start(app, "#app", Nil)
16
+
}
17
+
18
+
// MODEL
19
+
20
+
pub type Model {
21
+
Model(state: State)
22
+
}
23
+
24
+
pub type State {
25
+
Loading
26
+
Loaded(characters: List(get_characters.Character))
27
+
Failed(message: String)
28
+
}
29
+
30
+
fn init(_flags) -> #(Model, Effect(Msg)) {
31
+
#(Model(Loading), fetch_characters())
32
+
}
33
+
34
+
// UPDATE
35
+
36
+
pub type Msg {
37
+
HandleCharacters(Result(get_characters.GetCharactersResponse, String))
38
+
}
39
+
40
+
fn update(_model: Model, msg: Msg) -> #(Model, Effect(Msg)) {
41
+
case msg {
42
+
HandleCharacters(Ok(response)) -> {
43
+
let characters = case response.characters {
44
+
Some(chars) ->
45
+
case chars.results {
46
+
Some(results) -> results
47
+
None -> []
48
+
}
49
+
None -> []
50
+
}
51
+
#(Model(Loaded(characters)), effect.none())
52
+
}
53
+
HandleCharacters(Error(err)) -> #(Model(Failed(err)), effect.none())
54
+
}
55
+
}
56
+
57
+
// VIEW
58
+
59
+
fn view(model: Model) -> Element(Msg) {
60
+
html.div([], [
61
+
html.h1([], [html.text("Rick and Morty Characters")]),
62
+
case model.state {
63
+
Loading -> html.p([], [html.text("Loading characters...")])
64
+
Failed(message) ->
65
+
html.div([], [
66
+
html.p([attribute.style("color", "red")], [
67
+
html.text("Error: " <> message),
68
+
]),
69
+
])
70
+
Loaded(characters) -> render_characters(characters)
71
+
},
72
+
])
73
+
}
74
+
75
+
fn render_characters(characters: List(get_characters.Character)) -> Element(Msg) {
76
+
html.div([], [
77
+
html.ul(
78
+
[],
79
+
characters
80
+
|> list.map(fn(character) {
81
+
html.li([], [
82
+
html.div([], [
83
+
html.strong([], [
84
+
html.text(option.unwrap(character.name, "Unknown")),
85
+
]),
86
+
html.text(" - "),
87
+
html.text(
88
+
"Status: " <> option.unwrap(character.status, "Unknown"),
89
+
),
90
+
html.text(", "),
91
+
html.text(
92
+
"Species: " <> option.unwrap(character.species, "Unknown"),
93
+
),
94
+
]),
95
+
])
96
+
}),
97
+
),
98
+
])
99
+
}
100
+
101
+
// EFFECTS
102
+
103
+
fn fetch_characters() -> Effect(Msg) {
104
+
effect.from(fn(dispatch) {
105
+
let client = squall.new("https://rickandmortyapi.com/graphql", [])
106
+
let assert Ok(req) = get_characters.get_characters(client)
107
+
108
+
fetch.send(req)
109
+
|> promise.map(fn(fetch_result) {
110
+
case fetch_result {
111
+
Ok(resp) -> {
112
+
fetch.read_text_body(resp)
113
+
|> promise.await(fn(text_result) {
114
+
case text_result {
115
+
Ok(text) -> {
116
+
let result =
117
+
get_characters.parse_get_characters_response(text.body)
118
+
dispatch(HandleCharacters(result))
119
+
promise.resolve(Nil)
120
+
}
121
+
Error(_) -> {
122
+
dispatch(
123
+
HandleCharacters(Error("Failed to read response body")),
124
+
)
125
+
promise.resolve(Nil)
126
+
}
127
+
}
128
+
})
129
+
}
130
+
Error(_) -> {
131
+
dispatch(HandleCharacters(Error("Failed to fetch characters")))
132
+
promise.resolve(Nil)
133
+
}
134
+
}
135
+
})
136
+
137
+
Nil
138
+
})
139
+
}
+13
examples/02-lustre/test/lustre_example_test.gleam
+13
examples/02-lustre/test/lustre_example_test.gleam