aboutsummaryrefslogtreecommitdiff
path: root/test/build.gleam
blob: 5eb1b0b50166d683b61764cae15369f195c16dc5 (plain)
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))
  }
}