///|
priv suberror LaunchFailure {
LaunchError(String)
} derive(Debug)
///|
priv struct PackageMetadata {
directory : String
name : String
relative_name : String
supports_native : Bool
is_main : Bool
aliases : Array[(String, String)]
}
///|
fn metadata_string(value : Json, key : String) -> String raise LaunchFailure {
guard value is Object(fields) && fields.get(key) is Some(String(value)) else {
raise LaunchError("invalid moon package metadata: missing string '\{key}'")
}
value
}
///|
fn parse_package_metadata(text : String) -> Array[PackageMetadata] raise {
let json = @json.parse(text) catch {
_ => raise LaunchError("invalid moon package metadata: expected JSON")
}
guard json is { "packages": Array(packages), .. } else {
raise LaunchError("invalid moon package metadata: missing packages array")
}
let result = []
for pkg in packages {
match pkg {
{ "is-third-party": True, .. } => continue
{ "is-third-party": False, .. } => ()
_ =>
raise LaunchError(
"invalid moon package metadata: missing is-third-party flag",
)
}
let root = metadata_string(pkg, "root")
let relative_name = metadata_string(pkg, "rel")
let name = if relative_name == "" {
root
} else {
"\{root}/\{relative_name}"
}
guard pkg
is {
"is-main": is_main,
"deps": Array(deps),
"supported-targets": Array(targets),
..
} &&
is_main is (True | False) else {
raise LaunchError("invalid moon package metadata for \{name}")
}
let aliases = deps.map(dep => {
(metadata_string(dep, "alias"), metadata_string(dep, "path"))
})
result.push({
directory: metadata_string(pkg, "root-path"),
name,
relative_name,
is_main: is_main is True,
supports_native: targets.any(target => target is String("Native")),
aliases,
})
}
result
}
///|
fn build_artifact(text : String) -> String raise {
let json = @json.parse(text) catch {
_ =>
raise LaunchError("invalid moon run --build-only output: expected JSON")
}
guard json is { "artifacts_path": [String(path)], .. } && path != "" else {
raise LaunchError(
"moon run --build-only did not return exactly one executable",
)
}
path
}