--> Generates sync config and sourcemap scripts for supported tools local process = require("@lune/process") local serde = require("@lune/serde") local stdio = require("@lune/stdio") local task = require("@lune/task") local lib = require("../src") local manifest = require("./lib/manifest") local pathfs = require("../lune_packages/pathfs") type ToolChoice = "rojo" type ManifestExt = { scripts: { [ToolChoice]: { version: string, tool_dependencies: { { [string]: manifest.DependencySpecifier } }, }, }, } local SCRIPTS_DIR = pathfs.getAbsolutePathOf(pathfs.Path.from(".pesde")) local MANIFEST = manifest(nil, (nil :: any) :: { meta: ManifestExt }) local SCRIPTS = { syncConfigGenerator = [[local process = require("@lune/process") local args = table.clone(process.args) local ok, _ = require("./lune_packages/core").generators.%s.syncConfig(table.remove(args, 1), args, { writeToFile = true }) if not ok then return process.exit(1) end]], sourcemapGenerator = [[local process = require("@lune/process") local ok = require("./lune_packages/core").generators.%s.sourcemap(process.args[1]) if not ok then return process.exit(1) end ]], } local README_TMPL = [[# `pesde/scripts_%s` Common scripts intended for use with %s. ## Included scripts ### roblox_sync_config_generator Generates a %s sync config for pesde Roblox packages. ### sourcemap_generator Prints out a sourcemap for Wally dependencies for type extraction. ]] local function logPrefix(type: "error" | "info") local statusColor: stdio.Color = if type == "error" then "red" elseif type == "info" then "green" else error(`Invalid type: {type}`) return `main::{stdio.style("bold")}{stdio.color(statusColor)}{type}{stdio.color("reset")}` end local INFO_PREFIX = `[ {logPrefix("info")}]` local _ERROR_PREFIX = `[{logPrefix("error")}]` local function installDeps(): number local PESDE_INFO_PREFIX = string.gsub(`[{logPrefix("info")}]`, "main", "pesde") local PESDE_ERROR_PREFIX = string.gsub(`[{logPrefix("error")}]`, "main", "pesde") local SPINNER_STATES = { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" } stdio.write(`{PESDE_INFO_PREFIX} Installing dependencies with pesde`) -- Spawn our thread to display the spinner local spinnerThread = task.spawn(function() -- Hide the cursor stdio.write("\x1b[?25l") -- Display the spinner while true do for _, state in SPINNER_STATES do stdio.write(` {state}`) stdio.write( -- Moves the cursor back 1 spot and clears everything after "\x1b[2D\x1b[0K" ) end end end) -- `process_spawn` is an async rust function, so tokio spawns a hardware -- thread and mlua will yield the current thread, allowing for `spinnerThread` -- to continue executing local child = process.spawn("pesde", { "install" }, { stdio = "default", }) -- If we reach this point, that means mlua resumed the current thread and -- `process_spawn` returned or errored. We can now close `spinnerThread` and -- clean up task.cancel(spinnerThread) stdio.write( -- Clear the current line, move cursor back to its beginning and -- show it "\x1b[2K\x1b[1G\x1b[?25h" ) if not child.ok then stdio.ewrite(`{PESDE_ERROR_PREFIX} Failed to install dependencies with pesde, error:\n`) stdio.ewrite(child.stderr) end stdio.write(`{PESDE_INFO_PREFIX} Installed dependencies with pesde successfully\n`) return child.code end for tool, generators in lib.generators do local startTime = os.clock() -- For each tool, we generate a respective manifests and scripts local toolChoice = tool :: ToolChoice local toolScriptsDir = SCRIPTS_DIR:join(toolChoice) local toolMeta = MANIFEST.meta.scripts[toolChoice] if not pathfs.isDir(toolScriptsDir) then pathfs.writeDir(toolScriptsDir) end local capitalisedToolChoice = string.gsub(toolChoice, "^%l", string.upper) -- Define the manifest for the tool local toolManifest: manifest.PesdeManifest = { name = `pesde/scripts_{toolChoice}`, version = toolMeta.version, -- For the description, we capitalize the first letter of the tool name here -- since it is a proper noun description = `Scripts for {capitalisedToolChoice}-based Roblox projects.`, authors = { "daimond113 (https://www.daimond113.com/)", "Erica Marigold ", }, repository = "https://github.com/pesde-pkg/scripts", license = "MIT", includes = { "roblox_sync_config_generator.luau", "sourcemap_generator.luau", "pesde.toml", "README.md", "LICENSE", }, target = { environment = "lune", scripts = { roblox_sync_config_generator = "roblox_sync_config_generator.luau", sourcemap_generator = "sourcemap_generator.luau", }, }, peer_dependencies = toolMeta.tool_dependencies, dependencies = { core = { workspace = "pesde/scripts_core", version = "^" }, }, indices = { default = "https://github.com/pesde-pkg/index", }, } -- Format the scripts for the tool local syncConfigGeneratorScript, sourcemapGeneratorScript = string.format(SCRIPTS.syncConfigGenerator, toolChoice), string.format(SCRIPTS.sourcemapGenerator, toolChoice) -- Finally, write all the generated files pathfs.writeFile(toolScriptsDir:join("pesde.toml"), serde.encode("toml", toolManifest, true)) pathfs.writeFile(toolScriptsDir:join("roblox_sync_config_generator.luau"), syncConfigGeneratorScript) pathfs.writeFile(toolScriptsDir:join("sourcemap_generator.luau"), sourcemapGeneratorScript) pathfs.writeFile( toolScriptsDir:join("README.md"), string.format(README_TMPL, toolChoice, capitalisedToolChoice, capitalisedToolChoice) ) pathfs.copy(pathfs.cwd:join("LICENSE"), toolScriptsDir:join("LICENSE"), true) stdio.write( `{INFO_PREFIX} Generated script project for tool {toolChoice} ({stdio.style("dim")}{string.format( "%.2fms", (os.clock() - startTime) * 1000 )}{stdio.style("reset")})\n` ) end -- Now we install the dependencies for the newly created projects process.exit(installDeps())