From 95ff0c51643973938485a8cdcf504b81a96875e6 Mon Sep 17 00:00:00 2001 From: filoxenace Date: Tue, 23 Sep 2025 23:22:41 -0400 Subject: [PATCH] Strengthened typechecking and assertions. Added types for modules --- lib/cli.luau | 10 ++++++++-- lib/core.luau | 24 +++++++++++++++++++----- lib/fileproc.luau | 16 +++++++++++----- lib/types.luau | 14 ++++++++------ 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/lib/cli.luau b/lib/cli.luau index ad18c2c..eb5c7eb 100644 --- a/lib/cli.luau +++ b/lib/cli.luau @@ -4,9 +4,15 @@ local stdio = require("@lune/stdio") local fs = require("@lune/fs") local types = require("./types") -local cli = {} +export type CLI = { + parseArgs: () -> types.opts, + printUsage: () -> (), + checkOutputFile: (outputFile: string?) -> () +} -function cli.parseArgs(): types.opts +local cli = {} :: CLI + +function cli.parseArgs(): types.opts local args = process.args local opts = { outputFile = nil, diff --git a/lib/core.luau b/lib/core.luau index 82fcab9..b540d9d 100644 --- a/lib/core.luau +++ b/lib/core.luau @@ -1,13 +1,22 @@ --- handles core detection logic for workspace in models +--[[ handles core detection logic for workspace in models ]] local roblox = require("@lune/roblox") -local stdio = require("@lune/stdio") -local serde = require("@lune/serde") -local types = require("./types") +local stdio = require("@lune/stdio") +local serde = require("@lune/serde") +local types = require("./types") -local core = {} +export type Core = { + scanForWorkspace: (model: {Instance}, printInstanceNames: boolean) -> boolean, + isValidModelFile: (fileName: string) -> boolean, + fileContainsWorkspace: (fileContents: string, opts: types.opts) -> boolean, + formatResult: (result: boolean, fileName: string) -> string +} + +local core = {} :: Core -- recursively searches a model for a workspace instance function core.scanForWorkspace(model: types.model, printInstanceNames: boolean): boolean + assert(typeof(model) == "table", "Expected model to be of type 'table''") + assert(typeof(printInstanceNames) == "boolean", "Expected printInstanceNames to be of type 'boolean'") for _, child in pairs(model) do if printInstanceNames then print(child:GetFullName()) @@ -21,12 +30,15 @@ end -- checks if file has valid extension function core.isValidModelFile(fileName: string): boolean + assert(typeof(fileName) == "string", "Expected fileName to be of type 'string'") 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: string, opts: types.opts): boolean + assert(typeof(fileContents) == "string", "Expected fileContents to be of type 'string'") + assert(typeof(opts) == "table", "Expected opts to be of type 'table'") if opts.zlibDecompressFiles then local success = pcall(function() fileContents = serde.decompress("zlib", fileContents) end) if not success then @@ -43,6 +55,8 @@ function core.fileContainsWorkspace(fileContents: string, opts: types.opts): boo end function core.formatResult(result: boolean, fileName: string): string + assert(typeof(result) == "boolean", "Expected result to be of type 'boolean'") + assert(typeof(fileName) == "string", "Expected fileName to be of type '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 90032c1..c355e71 100644 --- a/lib/fileproc.luau +++ b/lib/fileproc.luau @@ -6,9 +6,16 @@ local serde = require("@lune/serde") local core = require("./core") local types = require("./types") -local fileproc = {} +export type FileProc = { + collectFiles: (opts: types.opts) -> {string}, + processFiles: (filesToProcess: {string}, opts: types.opts) -> {string}, + zlibDecompress: (contents: string, recursive: boolean?) -> string | boolean +} + +local fileproc = {} :: FileProc function fileproc.collectFiles(opts: types.opts): {string} + assert(typeof(opts) == "table", "Expected opts to be of type 'table'") local filesToProcess = opts.filesToProcess or {} if opts.directoryMode then if not opts.directoryPath or not fs.isDir(opts.directoryPath) then @@ -47,6 +54,8 @@ function fileproc.collectFiles(opts: types.opts): {string} end function fileproc.processFiles(filesToProcess: {string}, opts: types.opts): {string} + assert(typeof(filesToProcess) == "table", "Expected filesToProcess to be of type 'table'") + assert(typeof(opts) == "table", "Expected opts to be of type 'table'") local filesWithWorkspace = {} for _, filePath in pairs(filesToProcess) do if fs.isFile(filePath) then @@ -83,10 +92,7 @@ end -- 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 + error("fileproc.zlibDecompress is not implemented.") end return fileproc diff --git a/lib/types.luau b/lib/types.luau index c0f18bf..96b373d 100644 --- a/lib/types.luau +++ b/lib/types.luau @@ -2,13 +2,15 @@ local types = {} -export type opts = {outputFile: string?, - directoryMode: boolean, - directoryPath: string?, - forceBinaryRead: boolean, - printInstanceNames: boolean, +export type opts = { + outputFile: string?, + directoryMode: boolean, + directoryPath: string?, + forceBinaryRead: boolean, + printInstanceNames: boolean, zlibDecompressFiles: boolean, - filesToProcess: {string?}} + filesToProcess: {string?} +} export type model = {Instance}