-
-
Save StachuDotNet/2107e3daf35cbecb514aa28af9906c6d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// improvements not represented below | |
// - syntax highlighting (would be resolved by tree-sitter) | |
aliases | |
fn Directory.list = @darklang.Stdlib.Directory.list | |
fn List.map = @darklang.Stdlib.List.map | |
fn List.partition = @darklang.Stdlib.List.partition | |
fn List.append = @darklang.Stdlib.List.append | |
fn List.flatten = @darklang.Stdlib.List.flatten_v0 | |
fn String.endsWith = @darklang.Stdlib.String.endsWith | |
type Result = @darklang.Stdlib.Result.Result | |
module PT = @darklang.LanguageTools.ProgramTypes | |
fn HttpClient.post = @darklang.Stdlib.HttpClient.post_v4 | |
module PM = @darklang.LanguageTools.PackageManager | |
// TODO: throw this into stdlib | |
let listDirectoryRecursive (dir: String) : List<String> = | |
let (files, dirs) = Directory.list dir |> List.partition Builtin.File.isNormal | |
let nested = dirs |> List.map listDirectoryRecursive |> List.flatten | |
dirs ++ files ++ nested | |
let listPackageFilesOnDisk (dir: String) : List<String> = | |
dir | |
|> listDirectoryRecursive | |
|> List.filter (String.endsWith ".dark" $) // currying! | |
let saveItemToCanvas<'Item> (item: 'Item) (name: String) : Result<Unit, String> = | |
let json = item |> Json.serialize<PT.PackageFn.PackageFn> |> ! | |
let response = | |
HttpClient.postString $"http://dark-packages.dlio.localhost:11003/{name}s" json | |
let errMsg = $"Error saving {name} to canvas" | |
match response with | |
| Ok response -> | |
match response.statusCode with | |
| 200 -> Ok() | |
| _ -> | |
print $"Type: {name}; Json: {json}" | |
print $"Status: {response.statusCode|%i}" | |
print $"Body: {response.body |> String.fromBytesWithReplacement}" | |
print errMsg | |
Error errMsg | |
| Error err -> | |
print $"Type: {name}; Json: {json}" | |
print err | |
print errMsg | |
Error errMsg | |
let loadPackageFileIntoDarkCanvas (filename: String) : Result<Unit, String> = | |
let package = | |
filename | |
|> Builtin.File.read | |
|> ! | |
|> String.fromBytesWithReplacement | |
|> Builtin.LocalExec.Packages.parse filename | |
|> ! | |
let fnResults = | |
package.fns |> List.map (saveItemToCanvas<PT.PackageFn.PackageFn> "function") | |
let typeResults = | |
package.types |> List.map (saveItemToCanvas<PT.PackageType> "type") | |
let constantResults = | |
package.constants |> List.map (saveItemToCanvas<PT.PackageConstant> "constant") | |
// Flatten all the result lists into one list | |
let allResults = | |
[ fnResults; typeResults; constantResults ] | |
|> List.flatten | |
let firstError = | |
List.findFirst allResults (fun r -> | |
match r with | |
| Error _ -> true | |
| Ok _ -> false) | |
// Find the first error in the flattened list | |
match firstError with | |
| Some(Error err) -> Result.Result.Error err | |
| _ -> Result.Result.Ok() | |
let printPackageFunction (p: PM.Function) : Unit = | |
let modules = p.modules |> String.join "." | |
print $"Package Function {p.owner}.{modules}.{p.name}_v{Int.toString_v0 p.version}" | |
let printPackageType (p: PM.Type) : Unit = | |
let modules = p.modules |> String.join "." | |
print $"Package Type {p.owner}.{modules}.{p.name}_v{Int.toString_v0 p.version}" | |
let printPackageConstant (p: PM.Constant) : Unit = | |
let modules = p.modules |> String.join "." | |
print $"Package Constant {p.owner}.{modules}.{p.name}_v{Int.toString_v0 p.version}" | |
let printAllPackagesInDb () : Unit = | |
PM.listFunctions () |> List.iter printPackageFunction | |
PM.listTypes () |> List.iter printPackageType | |
PM.listConstants () |> List.iter printPackageConstant | |
// parse args and execute | |
type CliOptions = | |
| Help | |
| LoadPackagesIntoDarkCanvas | |
| ListPackages | |
| BadOption of String | |
let usage () : String = | |
"Usage: LocalExec [options] | |
Options: | |
-h, --help Show this help message and exit | |
load-packages-dark Load packages from disk into dark packages canvas | |
list-packages List packages | |
" | |
let parseArgs (args: List<String>) : CliOptions = | |
match args with | |
| [] -> CliOptions.Help | |
| [ "-h" ] | [ "--help" ] -> CliOptions.Help | |
| [ "list-packages" ] -> CliOptions.ListPackages | |
| [ "load-packages" ] -> CliOptions.BadOption "`load-packages` now executes in F# (not sure how you got here)" | |
| [ "load-packages-dark" ] -> CliOptions.LoadPackagesIntoDarkCanvas | |
| _ -> CliOptions.BadOption "Invalid arguments" | |
let main (args: List<String>) : Int = | |
match parseArgs args with | |
| Help -> | |
print (usage ()) | |
0 | |
| ListPackages -> | |
printAllPackagesInDb () | |
0 | |
| LoadPackagesIntoDarkCanvas -> | |
let files = listPackageFilesOnDisk "/home/dark/app/packages" | |
// TODO: clear packages from dark canvas first? | |
// Wait for canvas to be ready | |
let available = | |
List.fold | |
(List.range 0 10) | |
(Error "Not started") | |
(fun found num -> | |
match found with | |
| Ok() -> Ok() | |
| Error _ -> | |
HttpClient.get "http://dark-packages.dlio.localhost:11003/health" [] | |
|> Result.mapError (fun err -> | |
print $"Error: {err}" | |
Time.sleep 1000.0 | |
err)) | |
match available with | |
| Error msg -> | |
print $"Error waiting for dark packages canvas: {msg}" | |
1 | |
| Ok() -> | |
print "Dark packages canvas is ready" | |
let result = | |
List.fold | |
files | |
(Ok()) | |
(fun (acc, f) -> | |
print $"Loading {f}" | |
match acc with | |
| Error _err -> acc | |
| Ok() -> | |
loadPackageFileIntoDarkCanvas f | |
|> Result.mapError $"Failed to load packages from {f}:\n{$}") | |
match result with | |
| Error err -> | |
print err | |
1 | |
| Ok() -> | |
print "Done loading packages from disk" | |
printAllPackagesInDb () | |
0 | |
| BadOption msg -> | |
print ("Error: " ++ msg) | |
1 | |
main args |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment