diff --git a/.gitignore b/.gitignore index 67b9151..8c48c3c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -lune_packages/ -luau_packages/ +**/*_packages/ core/pesde.lock diff --git a/.luaurc b/.luaurc index 086d9f1..94fa340 100644 --- a/.luaurc +++ b/.luaurc @@ -1,3 +1,6 @@ { - "languageMode": "strict" + "languageMode": "strict", + "lint": { + "*": false + } } \ No newline at end of file diff --git a/.lune/exec.luau b/.lune/exec.luau new file mode 100644 index 0000000..f9b1c41 --- /dev/null +++ b/.lune/exec.luau @@ -0,0 +1,129 @@ +--> lib: Builder pattern class to spawn child processes + +local stdio = require("@lune/stdio") +local process = require("@lune/process") + +local Option = require("../lune_packages/option") +type Option = Option.Option + +local CommandBuilder = {} + +export type CommandBuilder = typeof(setmetatable({} :: CommandBuilderFields, { __index = CommandBuilder })) +type CommandBuilderFields = { + program: string, + args: { string }, + env: { [string]: string }, + stdioStrategy: Option, +} +export type StdioStrategy = "pipe" | "forward" | "none" +export type IoStrategyMapping = { + stdout: Option, + stderr: Option, +} + +-- FIXME: remove unknown usage +local DEFAULT_STDIO_STRATEGY: IoStrategyMapping = { + stdout = Option.Some("pipe" :: StdioStrategy) :: Option, + stderr = Option.Some("pipe" :: StdioStrategy) :: Option, +} +function CommandBuilder.new(program: string) + return setmetatable( + { + program = program, + args = {}, + env = {}, + stdioStrategy = Option.None :: Option, + } :: CommandBuilderFields, + { + __index = CommandBuilder, + } + ) +end + +function CommandBuilder.withArg(self: CommandBuilder, arg: string): CommandBuilder + table.insert(self.args, arg) + return self +end + +function CommandBuilder.withArgs(self: CommandBuilder, args: { string }): CommandBuilder + for _, arg in args do + self:withArg(arg) + end + + return self +end + +function CommandBuilder.withEnvVar(self: CommandBuilder, var: string, value: string): CommandBuilder + self.env[var] = value + return self +end + +function CommandBuilder.withEnv(self: CommandBuilder, env: { [string]: string }): CommandBuilder + for var, value in env do + self:withEnvVar(var, value) + end + + return self +end + +function CommandBuilder.withStdioStrategy( + self: CommandBuilder, + strategy: StdioStrategy | IoStrategyMapping +): CommandBuilder + -- FIXME: remove unknown usage + self.stdioStrategy = Option.Some(if typeof(strategy) == "string" + then { + stdout = Option.Some(strategy) :: Option, + stderr = Option.Some(strategy) :: Option, + } + else strategy) :: Option + return self +end + +local function intoSpawnOptionsStdioKind(strategy: StdioStrategy): process.SpawnOptionsStdioKind + if strategy == "pipe" then + return "default" + end + + if strategy == "forward" then + return "forward" + end + + if strategy == "none" then + return "none" + end + + error(`Non-strategy provided: {strategy}`) +end + +function CommandBuilder.exec(self: CommandBuilder): process.SpawnResult + print( + stdio.style("bold") .. "$", + stdio.style("dim") .. self.program, + table.concat(self.args, " ") .. stdio.style("reset") + ) + local child = process.spawn(self.program, self.args, { + shell = if process.os == "windows" then "cmd.exe" else "bash", + stdio = self + .stdioStrategy + -- FIXME: remove unknown usage + :orOpt(Option.Some(DEFAULT_STDIO_STRATEGY) :: Option) + :map(function(mappings: IoStrategyMapping) + local translatedMappings: process.SpawnOptionsStdio = {} + for field, value in mappings do + translatedMappings[field] = intoSpawnOptionsStdioKind((value :: Option):unwrap()) + end + + return translatedMappings + end) + :unwrap(), + }) + + if not child.ok then + print(`\n{stdio.color("red")}[luau-lsp]{stdio.color("reset")} Exited with code`, child.code) + end + + return child +end + +return CommandBuilder diff --git a/.lune/fmt.luau b/.lune/fmt.luau new file mode 100644 index 0000000..af1fde8 --- /dev/null +++ b/.lune/fmt.luau @@ -0,0 +1,14 @@ +--> Run stylua to check for formatting errors + +local process = require("@lune/process") + +local CommandBuilder = require("./exec") + +process.exit( + CommandBuilder.new("pesde") + :withArgs({ "run", "./bins/stylua" }) + :withArg("--") + :withArgs(process.args) + :withStdioStrategy("forward") + :exec().code +) diff --git a/.lune/typecheck.luau b/.lune/typecheck.luau new file mode 100644 index 0000000..188841a --- /dev/null +++ b/.lune/typecheck.luau @@ -0,0 +1,17 @@ +--> Run luau-lsp analysis to check for type errors + +local process = require("@lune/process") + +local CommandBuilder = require("./exec") + +local PLATFORM_SEP = if process.os == "windows" then ";" else ":" + +process.exit( + CommandBuilder.new("luau-lsp") + :withArg("analyze") + :withArgs({ "--settings", ".vscode/settings.json" }) + :withArgs({ "--ignore", "'**/*_packages/**'" }) + :withArg(".") + :withStdioStrategy("forward") + :exec().code +) diff --git a/pesde.lock b/pesde.lock index a8ef248..ec5d92a 100644 --- a/pesde.lock +++ b/pesde.lock @@ -7,3 +7,21 @@ lune = "bins/stylua" [workspace."pesde/toolchainlib"] lune = "toolchainlib" + +[graph."lukadev_0/option"."1.2.0 lune"] +direct = ["option", { name = "lukadev_0/option", version = "^1.2.0" }, "standard"] +resolved_ty = "standard" + +[graph."lukadev_0/option"."1.2.0 lune".target] +environment = "lune" +lib = "lib/init.luau" + +[graph."lukadev_0/option"."1.2.0 lune".pkg_ref] +ref_ty = "pesde" +name = "lukadev_0/option" +version = "1.2.0" +index_url = "https://github.com/daimond113/pesde-index" + +[graph."lukadev_0/option"."1.2.0 lune".pkg_ref.target] +environment = "lune" +lib = "lib/init.luau" diff --git a/pesde.toml b/pesde.toml index 91d8f2e..45fda03 100644 --- a/pesde.toml +++ b/pesde.toml @@ -7,5 +7,8 @@ workspace_members = ["toolchainlib", "bins/*"] [target] environment = "lune" +[dependencies] +option = { name = "lukadev_0/option", version = "^1.2.0" } + [indices] default = "https://github.com/daimond113/pesde-index" diff --git a/toolchainlib/src/github.luau b/toolchainlib/src/github.luau index 6623493..7d359e5 100644 --- a/toolchainlib/src/github.luau +++ b/toolchainlib/src/github.luau @@ -37,7 +37,7 @@ function Github.new(repo: string, config: Option) ["Authorization"] = configOrDefault.authToken:mapOr("", function(token) return `Bearer {token}` end), - }, + } :: net.HttpHeaderMap, } :: net.FetchParams, config = config, retries = configOrDefault.retries:unwrapOr(DEFAULT_MAX_RETRIES), diff --git a/toolchainlib/src/init.luau b/toolchainlib/src/init.luau index 286d980..24825a1 100644 --- a/toolchainlib/src/init.luau +++ b/toolchainlib/src/init.luau @@ -87,7 +87,6 @@ end function installTool(tool: ToolId, installPath: pathfs.Path) local toolAlias = toolAliasOrDefault(tool) - local client = Github.new( tool.repo, Option.Some({ @@ -134,7 +133,7 @@ function installTool(tool: ToolId, installPath: pathfs.Path) local binaryPath: pathfs.Path if matchingAsset == nil then - warn("No matching asset found, downloading all assets") + stdio.ewrite("No matching asset found, testing all binaries") for _, asset in assets do local decompressedPath = downloadAndDecompress(asset) @@ -165,7 +164,7 @@ function installTool(tool: ToolId, installPath: pathfs.Path) pathfs.move(binaryPath, installPath) - -- In order to eliminate fs read overhead on startup and to disallow + -- IDEA: In order to eliminate fs read overhead on startup and to disallow -- the use of the tool binary when outside a package where it is installed, -- we can improve this by following what rokit does, where we symlink -- the tool's path to this script, and check the file that we are being