From 10d2d6f027851b69352cf90944054c333406ce69 Mon Sep 17 00:00:00 2001 From: filoxenace Date: Tue, 23 Sep 2025 22:33:36 -0400 Subject: [PATCH] Add stricter type checking to newly created modules --- lib/cli.luau | 5 +++-- lib/core.luau | 9 +++++---- lib/fileproc.luau | 18 +++++++++++++++--- lib/types.luau | 15 +++++++++++++++ 4 files changed, 38 insertions(+), 9 deletions(-) create mode 100644 lib/types.luau diff --git a/lib/cli.luau b/lib/cli.luau index 136e9d1..ad18c2c 100644 --- a/lib/cli.luau +++ b/lib/cli.luau @@ -2,10 +2,11 @@ local process = require("@lune/process") local stdio = require("@lune/stdio") local fs = require("@lune/fs") +local types = require("./types") local cli = {} -function cli.parseArgs() +function cli.parseArgs(): types.opts local args = process.args local opts = { outputFile = nil, @@ -76,7 +77,7 @@ function cli.printUsage() stdio.write(stdio.color("reset")) end -function cli.checkOutputFile(outputFile) +function cli.checkOutputFile(outputFile: string?) if outputFile and fs.isFile(outputFile) then stdio.write(stdio.color("red")) stdio.write(`Error: Output file {outputFile} already exists. Will not overwrite.\n`) diff --git a/lib/core.luau b/lib/core.luau index 288f66e..82fcab9 100644 --- a/lib/core.luau +++ b/lib/core.luau @@ -2,11 +2,12 @@ local roblox = require("@lune/roblox") local stdio = require("@lune/stdio") local serde = require("@lune/serde") +local types = require("./types") local core = {} -- recursively searches a model for a workspace instance -function core.scanForWorkspace(model, printInstanceNames) +function core.scanForWorkspace(model: types.model, printInstanceNames: boolean): boolean for _, child in pairs(model) do if printInstanceNames then print(child:GetFullName()) @@ -19,13 +20,13 @@ function core.scanForWorkspace(model, printInstanceNames) end -- checks if file has valid extension -function core.isValidModelFile(fileName) +function core.isValidModelFile(fileName: string): boolean local ext = string.match(fileName, "%.([^%.]+)$") return ext == "rbxm" or ext == "rbxmx" end -- takes in fileContents as a string and deserializes them returning the results of scanForWorkspace() on the deserialized model. if it can't be deserialized, it will return the results of a naive search through the xml -function core.fileContainsWorkspace(fileContents, opts) +function core.fileContainsWorkspace(fileContents: string, opts: types.opts): boolean if opts.zlibDecompressFiles then local success = pcall(function() fileContents = serde.decompress("zlib", fileContents) end) if not success then @@ -41,7 +42,7 @@ function core.fileContainsWorkspace(fileContents, opts) return core.scanForWorkspace(instances, opts.printInstanceNames) end -function core.formatResult(result, fileName) +function core.formatResult(result: boolean, fileName: string): string if result then return stdio.color("green") .. `File {fileName} contains a Workspace instance.` .. stdio.color("reset") else diff --git a/lib/fileproc.luau b/lib/fileproc.luau index 86b9dcc..90032c1 100644 --- a/lib/fileproc.luau +++ b/lib/fileproc.luau @@ -2,14 +2,16 @@ local fs = require("@lune/fs") local stdio = require("@lune/stdio") local process = require("@lune/process") +local serde = require("@lune/serde") local core = require("./core") +local types = require("./types") local fileproc = {} -function fileproc.collectFiles(opts) +function fileproc.collectFiles(opts: types.opts): {string} local filesToProcess = opts.filesToProcess or {} if opts.directoryMode then - if not fs.isDir(opts.directoryPath) then + if not opts.directoryPath or not fs.isDir(opts.directoryPath) then stdio.write(stdio.color("red")) stdio.write(`Error: Directory {opts.directoryPath} does not exist.\n`) stdio.write(stdio.color("reset")) @@ -44,7 +46,7 @@ function fileproc.collectFiles(opts) return filesToProcess end -function fileproc.processFiles(filesToProcess, opts) +function fileproc.processFiles(filesToProcess: {string}, opts: types.opts): {string} local filesWithWorkspace = {} for _, filePath in pairs(filesToProcess) do if fs.isFile(filePath) then @@ -77,4 +79,14 @@ function fileproc.processFiles(filesToProcess, opts) return filesWithWorkspace end +-- take in file contents and zlib decompress them +-- if recursive param is true repeatedly zlib decompress the file until it fails +-- (modelscrape files are often double/triple zlib decompressed) +function fileproc.zlibDecompress(contents: string, recursive: boolean?): string | boolean + local success: boolean, decompressedContents: string = pcall(function() + return serde.decompress("zlib", contents) + end) + return success and decompressedContents or success +end + return fileproc diff --git a/lib/types.luau b/lib/types.luau new file mode 100644 index 0000000..c0f18bf --- /dev/null +++ b/lib/types.luau @@ -0,0 +1,15 @@ +-- custom type definitions + +local types = {} + +export type opts = {outputFile: string?, + directoryMode: boolean, + directoryPath: string?, + forceBinaryRead: boolean, + printInstanceNames: boolean, + zlibDecompressFiles: boolean, + filesToProcess: {string?}} + +export type model = {Instance} + +return types \ No newline at end of file