~/bend-docscommunity

domain/architecture/system/container/effects.bend source

domain/architecture/system/container/effects.bend on the hub · documented module

import Baseimport ../effs/io.bend as Ximport ../plan/type.bend as Pimport ../../environment/external/type.bend as Eximport ./type.bend as Ctimport ./ops.bend as O# Each built container's stack against the repository at `root`: its dependencies (the nearest# package.json at or above its source folder, the root go.mod, its .NET projects when it declares C#,# and shadcn/ui when components.json sits beside that package.json) and the extensions of its source files.def under(+root: String, +dir: String, +file: String) -> String:  Bool.pick(String, String.is_empty(dir), root ++ "/" ++ file, root ++ "/" ++ dir ++ "/" ++ file)# The first of these folders with a package.json, or "" (the root).def package_dir(dirs: List<&2, String>, +root: String) -> IO(String):  match dirs:    case []:      IO.pure(String, "")    case +d <> rest:      do IO<String>:        text : String <- X.read(under(root, d, "package.json"))        later : String <- package_dir(rest, root)        return Bool.pick(String, String.is_empty(String.trim(text)), later, d)def project_file_if(is_project: Bool, +path: String, +root: String) -> IO(List<&2, String>):  match is_project:    case False{}:      IO.pure(List<&2, String>, [])    case True{}:      do IO<List<&2, String>>:        text : String <- X.read(root ++ "/" ++ path)        return O.csproj_deps(String.lines(text))def project_file(+path: String, +root: String) -> IO(List<&2, String>):  project_file_if(String.ends_with(path, ".csproj"), path, root)def project_dependencies(paths: List<&2, String>, +root: String) -> IO(List<&2, String>):  match paths:    case []:      IO.pure(List<&2, String>, [])    case +path <> rest:      do IO<List<&2, String>>:        one : List<&2, String> <- project_file(path, root)        more : List<&2, String> <- project_dependencies(rest, root)        return List.append(&2, String, one, more)def dotnet_dependencies(+root: String, +source: String, enabled: Bool) -> IO(List<&2, String>):  match enabled:    case False{}:      IO.pure(List<&2, String>, [])    case True{}:      do IO<List<&2, String>>:        out : String <- X.run("git", ["-C", root, "ls-files", "-co", "--exclude-standard", "--", source])        project_dependencies(X.nonempty(String.lines(out)), root)def dependencies(+root: String, +source: String, +go: List<&2, String>, +dotnet: List<&2, String>) -> IO(List<&2, String>):  do IO<List<&2, String>>:    +dir : String <- package_dir(O.folders(source), root)    package : String <- X.read(under(root, dir, "package.json"))    components : String <- X.read(under(root, dir, "components.json"))    return List.append(&2, String, O.package_deps(package),      List.append(&2, String, go, List.append(&2, String, dotnet,        Bool.pick(List<&2, String>, String.is_empty(String.trim(components)), [], ["shadcn/ui"]))))def extensions(+root: String, +source: String) -> IO(List<&2, String>):  do IO<List<&2, String>>:    out : String <- X.run("git", ["-C", root, "ls-files", "-co", "--exclude-standard", "--", source])    return O.source_extensions(X.nonempty(String.lines(out)))def blocked(+what: String, xs: List<&2, String>, +why: String) -> List<&2, P.Step>:  match xs:    case []:      []    case x <> rest:      P.Blocked{what, x ++ why} <> blocked(what, rest, why)def or_current(+what: String, bs: List<&2, P.Step>) -> List<&2, P.Step>:  match bs:    case []:      [P.Current{what}]    case b <> rest:      b <> restdef check(+c: Ct.Container, +root: String, +xs: List<&2, Ex.External>, +go: List<&2, String>) -> IO(List<&2, P.Step>):  do IO<List<&2, P.Step>>:    dotnet : List<&2, String> <- dotnet_dependencies(root, O.source_of(c), O.uses_language(c, "C#"))    +deps : List<&2, String> <- dependencies(root, O.source_of(c), go, dotnet)    exts : List<&2, String> <- extensions(root, O.source_of(c))    +what : String = "stack " ++ O.key_of(c)    return or_current(what, List.append(&2, P.Step, blocked(what, O.stack_missing(c, deps), " is declared but not a dependency"),      List.append(&2, P.Step, blocked(what, O.languages_missing(c, exts), " files have no declared language"),        blocked(what, O.sdk_missing(c, xs, deps), " is the SDK of a model API it calls but not a dependency"))))def checks_with(cs: List<&2, Ct.Container>, +root: String, +xs: List<&2, Ex.External>, +go: List<&2, String>) -> IO(List<&2, P.Step>):  match cs:    case []:      IO.pure(List<&2, P.Step>, [])    case c <> rest:      do IO<List<&2, P.Step>>:        one : List<&2, P.Step> <- check(c, root, xs, go)        more : List<&2, P.Step> <- checks_with(rest, root, xs, go)        return List.append(&2, P.Step, one, more)# The stack of every container built from the repository at `root`.def checks(+root: String, cs: List<&2, Ct.Container>, +xs: List<&2, Ex.External>) -> IO(List<&2, P.Step>):  do IO<List<&2, P.Step>>:    mod : String <- X.read(root ++ "/go.mod")    checks_with(O.built(cs), root, xs, O.go_deps(String.lines(mod)))