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
119
120
121
122
|
// IMPORTS ---------------------------------------------------------------------
import gleam/bool
import gleam/io
import gleam/regex.{Options}
import gleam/result
import gleam/string
import shellout
import simplifile
// MAIN ------------------------------------------------------------------------
pub fn main() {
io.debug({
use exists <- try(verify_esbuild(), SimplifileError)
use <- bool.guard(!exists, Error(MissingEsbuild))
use _ <- try(build_for_javascript(), ShelloutError)
use _ <- try(bundle_server_component(), ShelloutError)
use _ <- try(bundle_minified_server_component(), ShelloutError)
use script <- try(read_script(), SimplifileError)
use module <- try(read_module(), SimplifileError)
use _ <- try(inject_script(script, module), SimplifileError)
use _ <- try(format_project(), ShelloutError)
Ok(Nil)
})
}
// CONSTANTS -------------------------------------------------------------------
const esbuild = "./build/.lustre/bin/esbuild"
// STEPS -----------------------------------------------------------------------
fn verify_esbuild() {
simplifile.verify_is_file(esbuild)
}
fn build_for_javascript() {
shellout.command(
run: "gleam",
with: ["build", "--target", "javascript"],
in: ".",
opt: [],
)
}
fn bundle_server_component() {
shellout.command(
run: esbuild,
with: [
"./src/server-component.mjs", "--bundle", "--format=esm",
"--outfile=./priv/static/lustre-server-component.mjs",
],
in: ".",
opt: [],
)
}
fn bundle_minified_server_component() {
shellout.command(
run: esbuild,
with: [
"./src/server-component.mjs", "--bundle", "--minify", "--format=esm",
"--outfile=./priv/static/lustre-server-component.min.mjs",
],
in: ".",
opt: [],
)
}
fn read_script() {
simplifile.read("./priv/static/lustre-server-component.min.mjs")
|> result.map(string.replace(_, "\"", "\\\""))
|> result.map(string.trim)
}
fn read_module() {
simplifile.read("./src/lustre/server.gleam")
}
fn inject_script(script, module) {
let inject_regex = "// <<INJECT RUNTIME>>\\n.+\\n.+\\n \\),"
let options = Options(case_insensitive: False, multi_line: True)
let assert Ok(re) = regex.compile(inject_regex, options)
let assert [before, after] = regex.split(re, module)
simplifile.write(
"./src/lustre/server.gleam",
before
<> "// <<INJECT RUNTIME>>\n element.text(\""
<> script
<> "\"),"
<> after,
)
}
fn format_project() {
shellout.command(run: "gleam", with: ["format"], in: ".", opt: [])
}
// ERROR HANDLING --------------------------------------------------------------
pub type Error {
MissingEsbuild
ShelloutError(#(Int, String))
SimplifileError(simplifile.FileError)
}
fn try(
result: Result(a, e),
to_error: fn(e) -> Error,
then: fn(a) -> Result(b, Error),
) -> Result(b, Error) {
case result {
Ok(value) -> then(value)
Error(error) -> Error(to_error(error))
}
}
|