-
Notifications
You must be signed in to change notification settings - Fork 1
/
gserde.gleam
118 lines (104 loc) · 2.63 KB
/
gserde.gleam
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import gleam/io
import gleam/list
import gleam/bool
import gleam/string
import gleam/result
import glance
import internal/serializer
import dot_env/env
import internal/deserializer
import simplifile
import request.{type Request, Request}
import fswalk
import evil.{expect}
pub fn gen(req: Request) {
let ser =
bool.guard(when: req.ser, return: serializer.from(req), otherwise: fn() {
""
})
let de =
bool.guard(when: req.de, return: deserializer.to(req), otherwise: fn() {
""
})
#(
req,
[ser, de]
|> string.join("\n\n"),
)
}
fn to_output_filename(src_filename) {
string.replace(in: src_filename, each: ".gleam", with: "_json.gleam")
}
pub fn main() {
let is_debug = case env.get_bool("DEBUG") {
Ok(_) -> True
_ -> False
}
fswalk.builder()
|> fswalk.with_path("src")
|> fswalk.with_entry_filter(fn(it) {
string.ends_with(it.filename, ".gleam") && fswalk.only_files(it)
})
|> fswalk.walk
|> fswalk.map(fn(v) { expect(v, "failed to walk").filename })
|> fswalk.each(fn(f) { process_single(f, is_debug) })
}
pub fn process_single(src_filename: String, is_debug) {
bool.guard(!is_debug, Nil, fn() {
io.debug(#("Processing", src_filename))
Nil
})
let src_module_name =
src_filename
|> string.replace("src/", "")
|> string.replace(".gleam", "")
let dest_filename = to_output_filename(src_filename)
let assert Ok(code) = simplifile.read(from: src_filename)
let assert Ok(parsed) =
glance.module(code)
|> result.map_error(fn(err) {
io.debug(err)
panic
})
let custom_types =
list.map(parsed.custom_types, fn(def) { def.definition })
|> list.filter(fn(x) { string.ends_with(x.name, "Json") })
bool.guard(
when: list.length(of: custom_types) <= 1,
return: Nil,
otherwise: fn() { panic as "Only one json type is allowed per file" },
)
let requests =
custom_types
|> list.flat_map(fn(custom_type) {
list.map(custom_type.variants, fn(variant) {
Request(
src_module_name: src_module_name,
type_name: custom_type.name,
module: parsed,
variant: variant,
ser: True,
de: True,
)
})
})
let filecontent =
list.map(requests, gen)
|> list.map(fn(it) { it.1 })
|> string.join("\n\n")
case filecontent {
"" -> Nil
_ ->
simplifile.write(
to: dest_filename,
contents: [
"import gleam/json",
"import gleam/dynamic",
"import " <> src_module_name,
filecontent,
]
|> string.join("\n"),
)
|> result.unwrap(Nil)
}
}