Skip to content

Instantly share code, notes, and snippets.

@StachuDotNet
Created September 28, 2023 17:03
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save StachuDotNet/2107e3daf35cbecb514aa28af9906c6d to your computer and use it in GitHub Desktop.
// 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