domain/architecture/system/container/effects.bend
near-v-framework@0.3.0.0 · 76 lines · 0 definitions
1import Base
2import near-v-framework@0.3.0.0/domain/architecture/system/effs/io.bend as X
3import near-v-framework@0.3.0.0/domain/architecture/system/plan/type.bend as P
4import near-v-framework@0.3.0.0/domain/architecture/environment/external/type.bend as Ex
5import near-v-framework@0.3.0.0/domain/architecture/system/container/type.bend as Ct
6import near-v-framework@0.3.0.0/domain/architecture/system/container/ops.bend as O
7
8# Each built container's stack against the repository at `root`: its dependencies (the nearest
9# package.json at or above its source folder, the root go.mod, and shadcn/ui when components.json sits
10# beside that package.json) and the extensions of its source files.
11
12def under(+root: String, +dir: String, +file: String) -> String:
13 Bool.pick(String, String.is_empty(dir), root ++ "/" ++ file, root ++ "/" ++ dir ++ "/" ++ file)
14
15# The first of these folders with a package.json, or "" (the root).
16def package_dir(dirs: List<&2, String>, +root: String) -> IO(String):
17 match dirs:
18 case []:
19 IO.pure(String, "")
20 case +d <> rest:
21 do IO<String>:
22 text : String <- X.read(under(root, d, "package.json"))
23 later : String <- package_dir(rest, root)
24 return Bool.pick(String, String.is_empty(String.trim(text)), later, d)
25
26def dependencies(+root: String, +source: String, +go: List<&2, String>) -> IO(List<&2, String>):
27 do IO<List<&2, String>>:
28 +dir : String <- package_dir(O.folders(source), root)
29 package : String <- X.read(under(root, dir, "package.json"))
30 components : String <- X.read(under(root, dir, "components.json"))
31 return List.append(&2, String, O.package_deps(package),
32 List.append(&2, String, go, Bool.pick(List<&2, String>, String.is_empty(String.trim(components)), [], ["shadcn/ui"])))
33
34def extensions(+root: String, +source: String) -> IO(List<&2, String>):
35 do IO<List<&2, String>>:
36 out : String <- X.run("git", ["-C", root, "ls-files", "-co", "--exclude-standard", "--", source])
37 return O.source_extensions(X.nonempty(String.lines(out)))
38
39def blocked(+what: String, xs: List<&2, String>, +why: String) -> List<&2, P.Step>:
40 match xs:
41 case []:
42 []
43 case x <> rest:
44 P.Blocked{what, x ++ why} <> blocked(what, rest, why)
45
46def or_current(+what: String, bs: List<&2, P.Step>) -> List<&2, P.Step>:
47 match bs:
48 case []:
49 [P.Current{what}]
50 case b <> rest:
51 b <> rest
52
53def check(+c: Ct.Container, +root: String, +xs: List<&2, Ex.External>, +go: List<&2, String>) -> IO(List<&2, P.Step>):
54 do IO<List<&2, P.Step>>:
55 +deps : List<&2, String> <- dependencies(root, O.source_of(c), go)
56 exts : List<&2, String> <- extensions(root, O.source_of(c))
57 +what : String = "stack " ++ O.key_of(c)
58 return or_current(what, List.append(&2, P.Step, blocked(what, O.stack_missing(c, deps), " is declared but not a dependency"),
59 List.append(&2, P.Step, blocked(what, O.languages_missing(c, exts), " files have no declared language"),
60 blocked(what, O.sdk_missing(c, xs, deps), " is the SDK of a model API it calls but not a dependency"))))
61
62def checks_with(cs: List<&2, Ct.Container>, +root: String, +xs: List<&2, Ex.External>, +go: List<&2, String>) -> IO(List<&2, P.Step>):
63 match cs:
64 case []:
65 IO.pure(List<&2, P.Step>, [])
66 case c <> rest:
67 do IO<List<&2, P.Step>>:
68 one : List<&2, P.Step> <- check(c, root, xs, go)
69 more : List<&2, P.Step> <- checks_with(rest, root, xs, go)
70 return List.append(&2, P.Step, one, more)
71
72# The stack of every container built from the repository at `root`.
73def checks(+root: String, cs: List<&2, Ct.Container>, +xs: List<&2, Ex.External>) -> IO(List<&2, P.Step>):
74 do IO<List<&2, P.Step>>:
75 mod : String <- X.read(root ++ "/go.mod")
76 checks_with(O.built(cs), root, xs, O.go_deps(String.lines(mod)))