# Call a PostgreSQL Function

Invoke PostgreSQL functions (stored procedures) using the Supabase client.

# `rpc(functionName: string, params: {[string]: any}?)`

The `rpc()` method calls PostgreSQL functions (stored procedures) on your database. This allows you to execute complex database logic, run custom queries, or call functions that don't map directly to table operations.

PostgreSQL functions vs Edge Functions

PostgreSQL functions run on your database server, while Edge Functions run on Supabase's edge network. Use `rpc()` for database logic and `functions:invoke()` for serverless application logic.

## Method Signature

Prop

Type

`rpc?`function(functionName: string, params: {[string]: any}?) -> RootQuery

## Basic Usage

    -- Call a PostgreSQL function without parameters
    local result, err = client
        :rpc("get_server_stats")
        :execute()

    if err then
        warn("Function call failed:", err)
    else
        print("Server stats:", result)
    end

    -- Call a function with parameters
    local userData, err = client
        :rpc("get_user_by_username", {
            p_username = "dragonwarrior"
        })
        :execute()

## Complete Examples

### Example 1: User Authentication Function

    -- PostgreSQL function signature:
    -- FUNCTION authenticate_user(username TEXT, password_hash TEXT) RETURNS JSON

    local function authenticate(username, passwordHash)
        local result, err = client
            :rpc("authenticate_user", {
                username = username,
                password_hash = passwordHash
            })
            :single()
            :execute()

        if err then
            return nil, "Authentication failed: " .. err
        end

        if result.success == false then
            return nil, result.message or "Invalid credentials"
        end

        return {
            userId = result.user_id,
            sessionToken = result.session_token,
            expiresAt = result.expires_at
    end

    -- Usage
    local authResult, authErr = authenticate("player1", "hashed_password_123")
    if authErr then
        warn(authErr)
    else
        print("Authenticated! User ID:", authResult.userId)
    end

### Example 2: Complex Game Calculation

    -- PostgreSQL function that calculates combat results
    -- FUNCTION calculate_damage(
    --     attacker_level INTEGER,
    --     defender_level INTEGER,
    --     weapon_power FLOAT,
    --     armor_defense FLOAT,
    --     critical_chance FLOAT
    -- ) RETURNS TABLE(damage FLOAT, is_critical BOOLEAN, status TEXT)

    local function simulateCombat(attacker, defender)
        local combatResult, err = client
            :rpc("calculate_damage", {
                attacker_level = attacker.level,
                defender_level = defender.level,
                weapon_power = attacker.weaponPower,
                armor_defense = defender.armorDefense,
                critical_chance = attacker.criticalChance
            })
            :execute()

        if err then
            warn("Combat calculation failed:", err)
            return { damage = 0, isCritical = false, status = "failed" }
        end

        return combatResult[1] -- Returns single row as a table
    end

    -- Usage in game
    local damageInfo = simulateCombat(
        { level = 50, weaponPower = 125.5, criticalChance = 0.15 },
        { level = 48, armorDefense = 85.2 }
    )

    print(string.format("Damage: %.1f (Critical: %s)",
        damageInfo.damage,
        damageInfo.is_critical and "YES" or "NO"
    ))

### Example 3: Batch Processing with Array Parameters

    -- PostgreSQL function that processes multiple items
    -- FUNCTION process_inventory_items(item_ids INTEGER[], action TEXT)
    -- RETURNS TABLE(item_id INTEGER, success BOOLEAN, message TEXT)

    local function bulkUpdateInventory(itemIds, action)
        local results, err = client
            :rpc("process_inventory_items", {
                item_ids = itemIds,  -- Pass array directly
                action = action
            })
            :execute()

        if err then
            return nil, "Bulk update failed: " .. err
        end

        -- Process results
        local successful = {}
        local failed = {}

        for _, result in ipairs(results) do
            if result.success then
                table.insert(successful, result.item_id)
            else
                table.insert(failed, {
                    itemId = result.item_id,
                    reason = result.message
                })
            end
        end

        return {
            successful = successful,
            failed = failed,
            successRate = #successful / #itemIds
    end

    -- Usage
    local updateResult, updateErr = bulkUpdateInventory(
        {101, 102, 103, 104, 105},
        "upgrade_tier"
    )

    if updateErr then
        warn(updateErr)
    else
        print(string.format("Upgraded %d/%d items successfully",
            #updateResult.successful,
            #updateResult.successful + #updateResult.failed
        ))
    end

### Example 4: Aggregation and Reporting

    -- PostgreSQL function that generates game reports
    -- FUNCTION generate_daily_report(report_date DATE)
    -- RETURNS JSON

    local function getDailyReport(dateString)
        -- Use today's date if not provided
        local targetDate = dateString or os.date("%Y-%m-%d")

        local report, err = client
            :rpc("generate_daily_report", {
                report_date = targetDate
            })
            :single()
            :execute()

        if err then
            return nil, "Report generation failed: " .. err
        end

        return {
            date = report.date,
            totalPlayers = report.total_players,
            activePlayers = report.active_players,
            newRegistrations = report.new_registrations,
            revenue = report.revenue,
            mostPlayedGame = report.most_played_game,
            peakConcurrent = report.peak_concurrent
    end

    -- Usage
    local dailyReport, reportErr = getDailyReport("2024-01-15")
    if reportErr then
        warn(reportErr)
    else
        print(string.format("Daily Report for %s:", dailyReport.date))
        print(string.format("Active Players: %d", dailyReport.activePlayers))
        print(string.format("Revenue: $%.2f", dailyReport.revenue))
    end

### Example 5: Type-Safe Function Calls

    -- Define types for function parameters and return value
    type CombatParams = {
        attacker_level: number,
        defender_level: number,
        weapon_power: number,
        armor_defense: number,
        critical_chance: number

    type CombatResult = {
        damage: number,
        is_critical: boolean,
        status: string

    -- Call with type validation
    local params: CombatParams = {
        attacker_level = 45,
        defender_level = 42,
        weapon_power = 110.5,
        armor_defense = 75.8,
        critical_chance = 0.12

    local result: {CombatResult}, err: string? = client
        :rpc("calculate_damage", params)
        :executeTyped()

    if err then
        warn("Type validation failed:", err)
    elseif #result > 0 then
        print("Damage dealt:", result[1].damage)
    end

## Filters & Method Chaining with RPC

RPC function calls can be followed up with filters and modifiers, just like select. However, make sure to respect the chaining order: filters first, modifiers last.

### Correct Order for RPC

    -- RPC can be followed by select-like modifiers
    local result = client
        :rpc("get_complex_data", {          -- Step 1: Call function
            filter = "active",
            limit = 100
        })
        :order("created_at", {              -- Step 2: Apply sorting (if function returns table)
            ascending = false
        })
        :limit(10)                          -- Step 3: Apply limit
        :execute()                          -- Step 4: Execute

    -- Some functions return single values, not tables
    local singleValue = client
        :rpc("get_player_count", {          -- Returns integer, not a table
            status = "active"
        })
        :single()                           -- Use single() for non-table returns
        :execute()

## Error Handling

### Common PostgreSQL Function Errors

    -- Function doesn't exist
    local result, err = client
        :rpc("nonexistent_function", {})
        :execute()

    if err then
        warn(err)  -- "function nonexistent_function() does not exist"
    end

    -- Wrong parameter types
    local result, err = client
        :rpc("get_user_by_id", {
            user_id = "not_a_number"  -- Expected integer
        })
        :execute()

    if err then
        warn(err)  -- "Invalid input syntax for type integer: "not_a_number"
    end

    -- Missing required parameters
    local result, err = client
        :rpc("authenticate_user", {
            -- Missing password_hash parameter
            username = "test"
        })
        :execute()

    if err then
        warn(err)  -- "null value in column 'password_hash' violates not-null constraint"
    end

### Graceful Error Handling Pattern

    local function safeRpc(functionName, params, defaultValue)
        local result, err = client
            :rpc(functionName, params)
            :returns("minimal")
            :execute()

        if err then
            -- Check for specific PostgreSQL errors
            if string.find(err:lower(), "does not exist") then
                warn(string.format("Function '%s' not found in database", functionName))
            elseif string.find(err:lower(), "permission denied") then
                warn(string.format("No permission to call function '%s'", functionName))
            elseif string.find(err:lower(), "division by zero") then
                warn("Mathematical error in function logic")
            else
                warn(string.format("RPC '%s' failed: %s", functionName, err))
            end

            -- Return default value on error
            return defaultValue
        end

        return result
    end

    -- Usage
    local playerCount = safeRpc("get_active_player_count", {}, 0)
    print("Active players:", playerCount)

### Transaction-Safe Function Calls

    local function executeInTransaction(functionCalls)
        -- Start a transaction
        local transactionResult, transactionErr = client
            :rpc("begin_transaction")
            :execute()

        if transactionErr then
            return nil, "Failed to start transaction: " .. transactionErr
        end

        local results = {}
        local hasError = false

        -- Execute multiple functions in transaction
        for _, funcCall in ipairs(functionCalls) do
            local result, err = client
                :rpc(funcCall.name, funcCall.params)
                :execute()

            if err then
                -- Rollback on any error
                client:rpc("rollback_transaction"):execute()
                return nil, string.format("Transaction failed at '%s': %s",
                    funcCall.name, err)
            end

            table.insert(results, result)
        end

        -- Commit if all succeeded
        local commitResult, commitErr = client
            :rpc("commit_transaction")
            :execute()

        if commitErr then
            return nil, "Failed to commit transaction: " .. commitErr
        end

        return results, nil
    end

    -- Usage
    local transactionResults, transErr = executeInTransaction({
        { name = "deduct_gold", params = { player_id = 123, amount = 100 } },
        { name = "add_item", params = { player_id = 123, item_id = 456 } },
        { name = "log_transaction", params = { player_id = 123, action = "purchase" } }
    })

[Delete DataDelete rows from your PostgreSQL database using the Supabase client.](https://roblox-supabase.vercel.app/docs/Database/delete-data)[Filter MethodsLearn how to use filter methods to refine your queries in the Roblox Supabase client.](https://roblox-supabase.vercel.app/docs/FiltersAndModifiers/filters)


Part to Terrain is a Roblox plugin that allows users to convert parts into terrain.

## Tools used
The plugin uses some third-party tools while developing:
- [React-lua](https://github.com/jsdotlua/react-lua) - Lua translation of Facebook's React
- [BasicState](https://github.com/csqrl/BasicState) - Key-value based state management library
- [Rojo](https://github.com/rojo-rbx/rojo) - Syncs scripts into Roblox Studio.
- [Selene](https://github.com/Kampfkarren/selene) - Syntax checking and linter
- [Wally](https://github.com/UpliftGames/wally) - Package manager for Roblox projects

## Building the plugin
1. Make sure you have installed Git, Wally, and Rojo in order to build the plugin.
*(If you want to use toolchains like [Rokit](https://github.com/rojo-rbx/rokit), run `rokit install`)*

2. Clone the repo:
git clone https://github.com/mkargus/PartToTerrain.git
3. Inside the project's root folder, you'll need to install the packages used for the plugin via Wally:
wally install

4. To compile the plugin, run Rojo with this command:
rojo build -p PartToTerrain.rbxm

## Credits
* [TigerCaptain](https://roblox.com/users/19053090/profile) - Original concept
* [CloneTrooper1019](https://roblox.com/users/2032622/profile) - Helped with the original plugin
* [Valletta](https://twitter.com/valletta__) - Created the logo for this plugin


# Dialogue Maker
![](https://github.com/user-attachments/assets/8759b695-e748-44df-93d8-1c935387af4e)

## About
Run the show with the Dialogue Maker: an open-source plugin for creating RPG-like dialogue boxes for NPCs in your Roblox game! It comes with a GUI that helps you add messages and player responses to your NPCs.

> [!TIP]
> This plugin is intended for non-programmers and developers of small games to easily create dialogue in their game. If you or one of your teammates know how to program, the Dialogue Maker Group recommends installing the [DialogueMaker/client](https://github.com/DialogueMaker/client) and [DialogueMaker/conversation](https://github.com/DialogueMaker/conversation) libraries for more control.

## Features
### Responsive dialogue editor
The Dialogue Maker uses the power of Roblox Studio's Explorer to help you navigate dialogue trees. We let you create labels per dialogue item, which can help if you need to know which message is which before you open the script.

![alt text](image.png)

### Full support for Dialogue Maker Client
This plugin makes configuring Dialogue Maker Client easy. It creates scripts from pre-defined templates when you want to make a new conversation or configure a conversation tree.

### Update and recover Dialogue Maker Client
If we release a new update to Dialogue Maker Client, you can use this plugin to update the packages, easing the transition from an older version to a new one. You can also use the plugin to restore your packages if they become corrupted.

## Where can I get it?
You can either get [the version Beastslash updates at the Roblox Library](https://www.roblox.com/library/4930928141/Dialogue-Maker-Beta) or you can build your own version by using the scripts in this repository.

## How do I use it?
Check out the [documentation](/docs/README.md).

## Development
### Can I contribute?
Sure! If you feel like that the Dialogue Maker can be improved for everyone, just send a feature request in the issues. You could also submit a pull request if you already added it yourself. Beastslash will sync changes made between the plugin and repository.

Just be aware that your contribution available to anyone under the GPL-3.0 license. Read [LICENSE](./LICENSE) for more information.

## Acknowledgements
* [**Christian "Sudobeast" Toney**](https://christiantoney.com) - Producer and Lead Programmer
* [**BHickey94**](https://github.com/BHickey94) - Code Contributor
* [**GAVsi115**](https://devforum.roblox.com/u/gavsi115/summary) - Code Contributor and Bug Reporter
* [**extravent3**](https://devforum.roblox.com/u/extravent3/summary) - Issue Sponsor and Bug Reporter
* [**ruax2891**](https://twitter.com/ruax2891) - QA Tester
* [**InkyTheBlue**](https://twitter.com/InkyTheBlueDerg) - QA Tester
* [**BeatArcade**](https://www.roblox.com/users/2893686241/profile) - Bug Reporter
* [**joshuajon**](https://github.com/joshuajon) - Bug Reporter
* [**LordMerc**](https://devforum.roblox.com/u/lordmerc/summary) - Bug Reporter
* [**thomkok13**](https://devforum.roblox.com/u/thomkok13/summary) - Bug Reporter
* [**kitifulnines**](https://devforum.roblox.com/u/kitifulnines/summary**) - [Bug Reporter](https://github.com/Beastslash/roblox-dialogue-maker/issues/88)
* [**DavidColetta**](https://github.com/DavidColetta) - [Bug Reporter](https://github.com/Beastslash/roblox-dialogue-maker/issues/86)


# What is this?
Straight up, this is identical copy of accustomed color picker gui that roblox uses. I've tried to script it to be as simillar as possible to one you usually see when choosing color in studio, both visually and mechanically. I did it for my own plugin needs, but then found a way to make my plugin easier without using any color pickers, thus I'm outsourcing it. Hope yall find a good use out of it!

![RobloxStudioBeta_Zfb1QSdfoM](https://github.com/user-attachments/assets/a770a952-c545-448f-a81d-f654df176e11)

# How to use?

Firstly you need to copy code `color_picker.luau` inside your plugin code to use

Then, create an object with pluginGuiId as the first argument. (pluginGuiId is needed to create DockWidgetPluginGui)\
Then use `:Prompt()` method to open gui so user can start choosing color.

```luau
local Picker = PluginColorPicker.new('MyPlugin_ColorPicker_1')
-- ^ pluginGuiId should be different for every plugin/window or it can cause problems!

print(Picker:Prompt()) -- will print color or nil if user did not choose any color
# Simple, right? But there's more!

### Open color picker gui with starting color:
Useful when you want to show color of object you're changing when opening.
```luau
local Picker = PluginColorPicker.new('MyPlugin_ColorPicker_1')
local StartingColor = Color3.fromRGB(255, 0, 0)

local result = Picker:Prompt(StartingColor) -- will open gui with red color already choosen

### Bind to color change:
If you wanna change color of object in real time when user is choosing, use `:BindToChange()` method to bind a function.
```luau
local Picker = PluginColorPicker.new('MyPlugin_ColorPicker_1')
local Part = workspace.Part

Picker:BindToChange(function(color)
  Part.Color3 = color
end)

local result = Picker:Prompt()

### Set color in real time:
If for some freaky reason you wanna to set color when user is already choosing, use `:Set(color)` method.
```lua
local Picker = PluginColorPicker.new('MyPlugin_ColorPicker_1')

task.spawn(function()
    Picker:Set(Color3.FromRGB(255, 0, 0))
    task.wait(0.5)
    Picker:Set(Color3.FromRGB(0, 255, 0))
    task.wait(0.5)
    Picker:Set(Color3.FromRGB(0, 0, 255))
end)

local result = Picker:Prompt()

### Cancel prompt:
If you want for some reason to stop user from choosing a color, use `:Cancel()` method. You can add custom color argument that will be passed when cancelling.
```luau
local Picker = PluginColorPicker.new('MyPlugin_ColorPicker_1')
local ColorOnCancel = Color3.fromRGB(255, 0, 0)

task.delay(5, function()
  Picker:Cancel(ColorOnCancel) -- if cancel works after user already choosed some result, it would do nothing.
end)

local result = Picker:Prompt()
-- if user will wait 5 seconds without choosing, the result will be red color

### Destroy the picker:
You can destroy object to disconnect and delete everything. (ALWAYS DO IT IF YOU WANT TO STOP USING IT TO DISCONNECT USELESS CONNECTIONS IN YOUR PLUGIN CODE)
```luau
local Picker = PluginColorPicker.new('MyPlugin_ColorPicker_1')
Picker:Prompt()
Picker:Destroy() -- will destroy all gui and disconnect all connections

### Check if it's opened:
Should be self explanatory
```luau
local Picker = PluginColorPicker.new('MyPlugin_ColorPicker_1')

print(Picker:IsOpened())


# AlyaNum

**AlyaNum** is the ultimate big number library for Roblox incremental games, perfect for both small and large-scale projects!

This library is a high-performance fork of [OmegaNum](https://create.roblox.com/store/asset/11646892509/OmegaNum-Readable) by FoundForces and [Naruyoko](https://github.com/Naruyoko), completely rewritten for speed, clarity, and maintainability. AlyaNum stands out with its extraordinary limit: numbers up to 10^^^^^10 (heptation), a value so large it's virtually unreachable in any Roblox game.

Despite this massive range, AlyaNum is faster than other libraries like [EternityNum](https://create.roblox.com/store/asset/12144172446/EternityNum-2) and [InfiniteMath](https://github.com/KdudeDev/InfiniteMath), giving you both performance and power.

If you want even more speed and don't need such a high limit, check out my other library, [SerikaNum](https://github.com/evilbocchi/serikanum), which offers a smaller cap of 10^(2^1024) but can outperform AlyaNum by 4–20x in most cases.

For more information, refer to [the documentation](https://evilbocchi.github.io/alyanum/documents/Introduction.html).


# @antivivi/alyanum

# AlyaNum

[](https://github.com/evilbocchi/alyanum/actions/workflows/ci.yml) [](https://github.com/evilbocchi/alyanum/releases/latest)

**AlyaNum** is the ultimate big number library for Roblox incremental games, perfect for both small and large-scale projects!

This library is a high-performance fork of [OmegaNum](https://create.roblox.com/store/asset/11646892509/OmegaNum-Readable) by FoundForces and [Naruyoko](https://github.com/Naruyoko), completely rewritten for speed, clarity, and maintainability. AlyaNum stands out with its extraordinary limit: numbers up to 10^^^^^10 (heptation), a value so large it's virtually unreachable in any Roblox game.

Despite this massive range, AlyaNum is faster than other libraries like [EternityNum](https://create.roblox.com/store/asset/12144172446/EternityNum-2) and [InfiniteMath](https://github.com/KdudeDev/InfiniteMath), giving you both performance and power.

If you want even more speed and don't need such a high limit, check out my other library, [SerikaNum](https://github.com/evilbocchi/serikanum), which offers a smaller cap of 10^(2^1024) but can outperform AlyaNum by 4–20x in most cases.

For more information, refer to [the documentation](https://evilbocchi.github.io/alyanum/documents/Introduction.html).


# @antivivi/alyanum

## Documents

[Introduction](https://evilbocchi.github.io/alyanum/documents/Introduction.html)

## Modules

[index](https://evilbocchi.github.io/alyanum/modules/index.html)


> **This repository is sponsored and mantained by [Smiling Axolotl](https://smilingaxolotl.com/).**

# Emote Custom Thumbnail
Tired of Roblox's automatic emote thumbnails? This plugin gives you full control over every parameter Roblox allows. Switch between a quick, simplified view or dive into advanced mode for pixel-perfect results.

## 📦 Installation
This plugin was made source-available due to Roblox Creator Store requirements (which block the use of `InsertService`).
To install manually:
1. Download the [**latest release**](https://github.com/Vexot/CustomEmoteThumbnail/releases) from this repository.
2. Place the file in your **Roblox Studio Local Plugins** folder.

<video src="https://github.com/user-attachments/assets/69fe8524-c9f3-4ad2-888a-07cbaba0aa1b">
  Your browser does not support the video tag.
</video>

## ✨ Features
- **Full customization** – tweak every available parameter.
- **Two modes** –
  - **Simplified Mode**: Fast, intuitive, simplified setup.
  - **Advanced Mode**: Pixel-perfect control.
- **Language sync** – Currently available in **Spanish** and **English**, automatically matching your Studio language.
- Tested to some extent — bug reports and contributions are welcome!

## 🛠 Contributing
Found a bug? Have an idea?
- Open an **Issue** or send a **Pull Request**.
- Feel free to suggest improvements or add new features.

## 📚 Notes
- Some functionality comes from **Roblox Client Tracker** due to the lack of official documentation on emote thumbnail customization.
- This code wasn’t originally meant to be released (it was rushed out before I traveled), so don’t expect perfectly polished code… yet!


![banner](https://user-images.githubusercontent.com/67706277/210158331-c96900fc-d645-4893-a95c-fd4eb700a975.png)

# Getting Started
The following instructions will get you up and running with an Order-powered experience! This assumes that you have at least a basic understanding of Roblox Studio.

## 1) Download VS Code and Rojo
1. Download and install VS Code from [here](https://code.visualstudio.com/)
2. From VS Code, install the extension Rojo from the Extensions tab on the left sidebar or through [this link.](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo)
3. In Roblox Studio, search for and add the plugin for Rojo through the toolbox, or use [this link.](https://create.roblox.com/marketplace/asset/6415005344/Rojo-7)

## 2) Create a new repository based on this template
1. At the top of this page, click the green "Use this template" button and select "Create a new repository"
2. Select the proper owner, add a name, choose your desired visiblity options, and click "Create repository from template"
3. Using the software of your choice (I typically use VS Code's Source Control menu), clone your new repository to your computer

## 3) Initialize Wally
1. If you don't yet have Wally, you can install it [from here.](https://github.com/UpliftGames/wally)
2. Open a terminal in your new project's directory and run the command `wally install` to get the included packages.

## 4) Project configuration
1. Open the new repository in VS Code and then open the `default.project.json` file
2. At the top, you'll see a string that reads "New Order Project", replace this with the name of your new project and save the file

## 5) Sync code into Roblox Studio
1. In VS Code, click the Rojo button on the bottom right (if you don't see this icon, verify the Rojo extension is installed and restart VS Code)
2. In the context menu that appears, click on `default.project.json` at the bottom
3. In Roblox Studio, create or open a place file that will host your new experience
4. Switch to the Plugins tab, and select Rojo
5. In the Rojo window that appears, click "Connect"

You are now up and running with Order! Any code you write in VS Code will be synced into your new game whenever you save the file. If you need further help, you can visit [the DevForum](https://devforum.roblox.com/), read [the Order docs](https://michaeldougal.github.io/order/), or check out [the Rojo docs](https://rojo.space/)!


## Why Order?

Order removes the barriers between modules so you can focus on building great experiences.

### Cyclic Dependency Support

The standout feature of Order. Modules can freely reference each other — no more restructuring your code to avoid circular imports. Order handles the complexity behind the scenes through a metatable-based approach.

### Effortless Module Loading

Replace `require()` chains with a single call: `shared("ModuleName")`. Resolve modules by name, partial path, or direct instance reference — Order finds them for you.

### Customizable Init Sequence

Define your own initialization pipeline. The default Prep → Init pattern gives you a synchronous setup phase followed by an async runtime phase, and you can override or extend this per-task or project-wide.

### Task Priority Control

Set a Priority value on any task to control its position in the load order — higher values go first, negatives last. Gain fine-grained control over startup without tangling dependency chains.

### Multi-Place Universe Support

First-class support for Roblox game universes. Map Place IDs to named types, then define which Code Groups are active per type — share exactly the right code across your lobby, game servers, and more.

### Built-In Developer Tools

Toggle verbose module loading logs and cyclic-dependency analysis straight from Settings.luau. Silent mode keeps production output clean while keeping Studio output rich.

## Clean, Intuitive API

Order's API is designed to stay out of your way. Here's how common patterns look in practice.

Loading ModulesDefining a TaskCircular Dependencies

    -- Load a module by name (no path required)
    local DataManager = shared("DataManager")

    -- Or by partial path for disambiguation
    local GetRemote = shared("lib/GetRemote")

    -- Or by direct ModuleScript reference
    local Util = shared(game.ReplicatedStorage.Shared.Util)


[ ](https://github.com/michaeldougal/order/edit/master/docs/index.md "Edit this page")

A module loader framework for Roblox that provides simple and fast module lookup, cyclic dependency support, a customizable initialization sequence, and more! Created by [@ChiefWildin](https://twitter.com/chiefwildin)

## What's so special about Order?

The core design principle in Order is to **remove barriers and enable the developer**. It combines the best features of current popular frameworks, and adds a few of its own.

## Are there any unique features in Order?

There are! One of these unique features is the ability to have modules with circular dependencies. Occasionally, libaries and tasks need to interchangably use one another's public functions and variables, but Luau doesn't allow this by default. Order achieves support for this through a metatable-based bait-and-switch style tactic (see [Special notes](https://michaeldougal.github.io/order/notes)).

## Is there anything else I need to know?

Order is a relatively new framework, and I'm still actively developing it. As such, functionality and features can and will change at any time and I'm still ironing out all the kinks and bugs. If you have any suggestions or find any bugs yourself, feel free to reach out! Issues, discussions, and pull requests can be submitted to [the project repo](https://github.com/michaeldougal/order), or you can join [the [ nxt_lvl ] Discord server](https://discord.gg/QvZ66Pw)!


[ ](https://github.com/michaeldougal/order/edit/master/docs/notes.md "Edit this page")

# Some special notes

## No bare code in modules with circular dependencies

In order to support circular dependencies, it must be guaranteed that the module in question has **no bare code that references a circular dependency**. That is to say that any code that references the circular dependency must be contained within a function. If Order detects this bare code, you will be notified with a warning in the output and no operation will be processed on the module in question.

## Loading modules with non-unique names

Modules can be specified through several different paths. If the name is unique, you can reference it simply through that. If two modules exist with the same name however, Order will warn you that it found two or more possible modules for your request, and will ask you to be more specific. You can use any level of the module paths it provides you with, as long as they're unique as well.

Order does not index all potential file paths by default, so it is recommended to use the **shortest unique paths possible** in order to conserve memory usage.

## Printing module tables

One of the complications with the method Order uses to support circular dependencies is that if you try to print out one of these module's tables, it would return a table address instead of an output-friendly table. In order to preserve as much functionality as possible, Order will list out table keys and values in a custom format when converting the table to a string.


[ ](https://github.com/michaeldougal/order/edit/master/docs/gettingstarted.md "Edit this page")

# Getting started

To get started working with Order, you can use any of the options detailed below. Be sure to check out [the API](https://michaeldougal.github.io/order/api) for details on how everything works!

## **Cyclone**

Cyclone is an implementation of the Order framework that also comes packaged with some commonly used utilities that can speed up development quite a bit. It is the recommended way to get up and running with Order. Go [here](https://github.com/nxtlvlrbx/cyclone) to get started.

## **Rojo**

### Clone the repo

The repository for Order can be found [here](https://github.com/michaeldougal/order).

A Rojo project file is included in the repository, so it's as simple as creating a new place file and serving it up! If you'd like to learn more about Rojo, see [the official documentation](https://rojo.space/).

## **Roblox**

### Get the package

I highly recommend the professional environment that Rojo offers, but if you'd like, you can also get Order directly from the Roblox catalog [here](https://www.roblox.com/library/11152308855/). Installation instructions are included with the package. Note that this package follows a different setup structure and has to be updated manually, so updates come a lot slower to this version and it may often be out of date.


[ ](https://github.com/michaeldougal/order/edit/master/docs/contributions.md "Edit this page")

# Want to make a contribution?

Order is a fully open-source project, and I would love to take community contributions that will make it even better! In the interest of quality control though, I've decided to set forth some rules that contributions must follow in order to be integrated into the project. If this all sounds good to you, [make a pull request](https://github.com/michaeldougal/order/pulls)!

## Rules

  1. **Style** \- Contributions should do their best to conform to the [Roblox Luau Style Guide](https://roblox.github.io/lua-style-guide/). I realize that that's not always possible or practical, so some exceptions can be made in the interest of functionality.
  2. **Utility** \- Contributions should expand or enhance Order in a way that aligns with the project's design philosophy of making things simpler and easier for the developer. Anything that does not do so will be rejected.
  3. **Documentation** \- Any changes that add complex functionality should contain comments that explain **why** you're doing what you're doing. This is also part of the Roblox Luau Style Guide (rule #1), but is worth reiterating.


[ ](https://github.com/michaeldougal/order/edit/master/docs/api.md "Edit this page")

# API

## Settings

The framework settings module (located at `src/_order/Settings.lua`) has a few different options that developers can customize for their projects.

  * `DebugMode` \- When set to `true` this will make the loading process verbose so that you can iterate on the framework or tweak behavior.
  * `SilentMode` \- When set to `true` this will disable all regular output (version printing, notifications about when initialization has finished, etc.) This will not disable warnings. By default this is turned off during Studio development, and turned on for production.
  * `InitOrder` \- Can be set to either `"Project"` or `"Individual"`. Project means that each initialization function will be run on every task before moving on to the next initialization function. Individual means that each task will run through each of its initialization functions before moving on to the next task. Both settings respect module priority values.
  * `InitFunctionConfig` \- A table that defines the initialization functions for the project and their options.
  * `PortableMode` \- An experimental setting that allows Order to run in a portable mode where it does not assume it is the main or only framework in the game. This is intended for use with plugins or other small scope projects and will require a custom project structure.

## File structure

### Tasks

Tasks are modules that have code intended for immediate execution at runtime. Tasks should be placed in the `tasks` folder of the appropriate context.

Info

Any module that is placed inside the `tasks` folder will be loaded by default, even if no initialization function exists within it or if it isn't even a table. All other modules are loaded only as requested.

#### Priorities

If you wish to give a task priority during the initialization phase, set a `Priority` key in the main module table to the priority level you would like (higher values load first, negative values load last). Setting a priority is optional - if you don't set one, the task will be set to priority 0 by default.

Warning

Tasks with priorities are still initialized asynchronously, so if the task yields during initialization there is no guarantee that it will finish before a lower priority task starts initializing. Tasks with the same priority are initialized in an arbitrary order.

#### Initialization functions and synchronization

In the default configuration, tasks can place their code to execute into two initialization functions: `:Prep()` and `:Init()`. `:Prep()` comes first and is synchronous, and then `:Init()` comes after and is asynchronous. Tasks are not required to have either, and are allowed to define their own initialization functions if desired. These can be defined by placing a table called `InitConfigOverride` in the module table, following the same structure as is found for `InitFunctionConfig` in the `Settings.lua` file of the framework folder.

#### Example

    local NewTask = {
        Priority = 5,

    function NewTask:Prep()
        print("Task is prepped.")
    end
    s
    function NewTask:Init()
        print("Task is running!")
    end

    return NewTask

### Everything else

All other modules can be placed in the provided `lib` folder, or any other custom folders that you create.

### File paths

There are five top-level directories by default:

  * `character` \- StarterPlayer.StarterCharacterScripts
  * `client` \- StarterPlayer.StarterPlayerScripts
  * `first` \- ReplicatedFirst
  * `server` \- ServerScriptService
  * `shared` \- ReplicatedStorage.Shared

Note

`first` and `character` are not scanned for task modules, as it is assumed that developers will simply use LocalScripts/Scripts instead. If you wish to add tasks there, you may add custom support at the end of the main framework module. For Rojo users, further file path customization can be configured in the `default.project.json` file.

## Loading dependencies

Order makes use of the `shared` global variable to load dependencies. In code, this takes the place of the usual `require` keyword. This function can take either a string of the module's name, a string of a partial or complete path to the module, or a direct object reference to a ModuleScript. Valid examples:

    local AnimNation = shared("AnimNation")

    local AnimNation = shared("lib/AnimNation")

    local AnimNation = shared(game:GetService("ReplicatedStorage").Shared.lib.AnimNation)

Warning

When two or more modules exist with the same name or partial path, Order will warn you that it found multiple modules for your request, and will ask you to be more specific. You can use any level of the module paths it provides you with, as long as it is unique.

The Order module itself can also be used instead of `shared` if you have other uses for that keyword, want to avoid globals like the plague, or are running in portable mode. For example:

    local require = require(game:GetService("ReplicatedStorage").Shared.Order)

### Supporting modules from other frameworks

If you would like to import a module from another framework that uses `require` to load dependencies (such as Nevermore), simply redirect `require` to `shared`:

    local require = shared

Or, alternatively, you can redirect their require call to the main Order module:

    local require = require(game:GetService("ReplicatedStorage").Shared.Order)

Also be sure to update your initializer configuration to support the module's intended initialization procedure (or adapt it to Order's, if preferred.)


# OpenSB

An opensource scriptbuilder for Roblox.

### Notice

By default, this depends on https://luau-compile.onrender.com ([running this](https://github.com/Open-SB/luau-compile)).

Which is being used to compile Luau source code into bytecode (only for localscripts). As there is no good solution for compiling Luau in Luau at the moment (that is small & lightweight).

As a bonus using an full Luau compiler allows us to generate bytecode with optimizations turned on without much performance overhead.

This is being used in [compile.luau](https://github.com/Open-SB/OpenSB/blob/main/modules/server/compile.luau), and I encourage you to change it (check [Configuration](https://github.com/Open-SB/OpenSB#Configuration)) to using your own hosted version.

As a fallback it will by default rely on a [toolbox modulescript](https://roblox.com/library/107945471093637) (owned by [ewd3v](https://github.com/ewd3v), and powered by [LuauCeption](https://github.com/RealEthanPlayzDev/LuauCeption)) to compile Luau instead in cases where HttpService is being ratelimited. The reason this is an external module and not built into OpenSB is because it's an optional feature and it's easier to change it to use another toolbox modulescript instead. It also means it's by default not loaded into the game until it gets used for the first time (LuauCeption is really large).

The module being used can also be changed or have it's feature completely disabled by [adding custom configuration](https://github.com/Open-SB/OpenSB#Configuration).

## Getting Started

You will need to [install aftman](https://github.com/LPGhatguy/aftman#aftman) first to get the required tooling.

After you have installed aftman, run:

```bash
aftman install

## Configuration

This uses a lune script to aid in building the project with provided configuration ([source available here](https://github.com/Open-SB/OpenSB/blob/main/.lune/build)).

Custom configurations can be made in a ".config.toml" file (ignored in the .gitinore, and should be placed in the root folder), and uses the same format as the ["default.toml" in .lune/build/config](https://github.com/Open-SB/OpenSB/blob/main/.lune/build/config/default.toml) (also where you should look for all availble configurations and for small documentation).

Any defined fields under the selected branch will replace the default value. To make configurations that apply to any branch use the "global" branch.

Example:

```toml
[global]
scriptHostKey = "secret"

[dev]
workerThreads = 4

[prod]
workerThreads = 12

(The script host key will be set to "secret" for all branches, and workerThreads will be set to 4 while in dev, and 12 while in prod).

Custom darklua rules can be provided under the "darkluaRules" field for the selected branch (will replace default rules!).

## Building & testing

To build the place from scratch, use:

```bash
lune run build dev && rojo build -o "OpenSB.rbxlx"

Next, open `OpenSB.rbxlx` in Roblox Studio and start the Rojo server:

```bash
rojo serve

Then when you want to test your changes, use:

```bash
lune run build dev

(The --watch flag on darklua would've worked if the modules folder was in src, but doing that would process a duplicate of the modules folder)

To build the "production" version, use:

```bash
lune run build prod

A list of "branches" is visible when running the build script without providing a branch:

```bash
lune run build

For more help, check out the [Rojo](https://rojo.space/docs) and [darklua](https://darklua.com/docs) documentation.


Added in 0.2.2

Functions defined using the method syntax (with a `:`) will be replaced with their field like syntax.

This rule can be useful when obfuscating code, since it, along with the `rename_variables` rule, makes it less clear that a given function is an instance (or method) function. This obfuscation can result in smaller code when when used with `rename_variables` rule, since darklua can then rename repeated references to `self` with a single-letter variable name, saving thousands of bytes across a large Lua program.

## Examples

InputOutput

    local Car = {}

    function Car:move(distance)
        self.position = self.position + distance
    end

    local Car = {}

    function Car.move(self,distance)
        self.position = self.position + distance
    end

Input| Output

    local Car = {}

    function Car:move(distance)
        self.position = self.position + distance
    end

    local Car = {}

    function Car.move(self,distance)
        self.position = self.position + distance
    end


Added in 0.11.0

This rule removes all Luau type declarations and annotations.

## Examples

InputOutput

    local var: number? = nil

    local var= nil

InputOutput

    type Array<T> = { T }
    local test: Array<string> = {}

    local test= {}

InputOutput

    return value :: string

    return value

InputOutput

    local function getAverage(array: { string }): number
        local sum: number = 0
        for _, element: number in array do
            sum += tonumber(element) :: number
        end
        return sum / #array
    end

    local function getAverage(array)
    local sum= 0
        for _, element in array do
            sum += (tonumber(element) )
    end
        return sum / #array
    end

Input| Output

    local var: number? = nil

    local var= nil

    type Array<T> = { T }
    local test: Array<string> = {}

    local test= {}

    return value :: string

    return value

    local function getAverage(array: { string }): number
        local sum: number = 0
        for _, element: number in array do
            sum += tonumber(element) :: number
        end
        return sum / #array
    end

    local function getAverage(array)
    local sum= 0
        for _, element in array do
            sum += (tonumber(element) )
    end
        return sum / #array
    end


This require mode is meant to be used for resolving content using Luau _module paths_. It is the require mode used by the [Lune runtime](https://lune-org.github.io/docs/).

**_Warning!_ ** The _path_ require mode should not be confused with the _luau_ require mode. Both require modes are used with strings looking like file paths, but they resolve to actual files differently.

The Luau require mode follows the Luau RFCs for require resolution (see [Amended Require Resolution](https://rfcs.luau.org/amended-require-resolution.html) and [Abstract Module Paths](https://rfcs.luau.org/abstract-module-paths-and-init-dot-luau.html) documents). Once enabled, darklua will find all require calls made with strings (single or double quotes) and resolve them.

## Bundling Support

It can be configured in the **bundle** part of the configuration file. For a quick overview of the bundling configuration, see [the documentation page](https://darklua.com/docs/bundle/).

## Configuration Overview

The Luau require mode can be defined as the string ‘luau’ to use all the default values, or with its object format:

      name: "luau",

      // optional
      aliases: {
        "@pkg": "./Packages",
      },

      // optional (defaults to true)
      use_luau_configuration: true,

## Aliases

When a path do not start with `.`, `..` or `/`, their first component is used to find its associated source location. These locations can be configured with the `aliases` parameter of the path require mode configuration.

To provide flexibility, aliases are not restricted to start with `@`, unlike the aliases from the Luau configuration file (`.luaurc`).

Relative paths in `aliases` are resolved based on the configuration file location.

### Example

Given this configuration file for bundling:

      bundle: {
        require_mode: {
          name: "luau",
          aliases: {
            "@pkg": "./Packages",
            // you can also map directly to a file (Lua or
            // any supported data file)
            images: "./assets/image-links.json",
          },
        },
      },

It is possible to make these require call in any file:

    local Promise = require("@pkg/Promise")
    local images = require("images")

## Luau Configuration Files

Luau configuration files are named `.luaurc` and they can contain an `aliases` parameter which acts like the `aliases` parameter in darklua.

The value of `use_luau_configuration` will change how darklua finds new aliases. Before looking at the `aliases` value, darklua will attempt to find the nearest `.luaurc` configuration file to each file it processes. If it finds one, it will load the aliases.

This behavior is enabled by default. It can be disabled by setting `use_luau_configuration` to `false`.


Added in 0.3.6

This rule computes expressions (that are determined to be static) and replaces them with their result. An expression will not be replaced if it has any side-effects. This can make code smaller, but also make code slightly faster since the computation is now done ahead of time. This rule is influenced by the evaluation system of darklua. As its capacity increases, the rule will be able to compute more complex expressions.

## Examples

InputOutput

    return 1 + 1

    return 2

InputOutput

    return 10 * 10

    return 100

InputOutput

    return true and 'true' or 'not true'

    return 'true'

InputOutput

    return 'Hello' .. ' friend!'

    return 'Hello friend!'

Input| Output

    return 1 + 1

    return 2

    return 10 * 10

    return 100

    return true and 'true' or 'not true'

    return 'true'

    return 'Hello' .. ' friend!'

    return 'Hello friend!'


Added in 0.3.4

This rule will remove parentheses in a function call when there is only one string or one table as arguments. In large Lua programs, this can save several thousand bytes.

## Examples

InputOutput

    print('hello')

    print'hello'

InputOutput

    create({ ... })

    create{ ... }

Input| Output

    print('hello')

    print'hello'

    create({ ... })

    create{ ... }


Added in 0.12.0

## Parameters

Name| Type| Description| Default
---|---|---|---
preserve_arguments_side_effects| `boolean`| Defines how darklua handle arguments passed to the functions. If true, darklua will inspect each argument and preserve any potential side effects. When false, darklua will not perform any verification and simply erase any arguments passed.| `true`

This rule removes all function calls to [`debug.profilebegin`](https://create.roblox.com/docs/reference/engine/libraries/debug#profilebegin) and [`debug.profileend`](https://create.roblox.com/docs/reference/engine/libraries/debug#profileend).

## Examples

InputOutput

    debug.profilebegin('function name')
    performUpdate()
    debug.profileend()

    do end
    performUpdate()
    do end

Input| Output

    debug.profilebegin('function name')
    performUpdate()
    debug.profileend()

    do end
    performUpdate()
    do end


Rules are what transform Lua code. When processing code with darklua, it is essentially going through a given list of rules one by one, each one transforming code and feeding it to the next rule.

**Important note:** one thing to understand is that the ordering of these rules sometimes have importance! For example, you should inject a value before trying to compute expressions statically, or optimize if branches out.

Information on the built-in rules and their configuration properties can be found [here](https://darklua.com/docs/rules-reference/).

## Rule Format

Rules can be written in two different formats: the shortest format consists of simply providing the rule name. When using this format, any parameters the rule have will use its default value.

For example, the `remove_empty_do` rule does not have any parameters, so it can be specified in the configuration file as:

      rules: ["remove_empty_do"],

If a rule can be configured, the object format can be used to override each parameter. The rule name **must** be specified with a field named `rule`. Then, simply enumerate the property name associated with its value.

For example, the `rename_variables` rule can optionally rename the function names. To do that, the rule must be written using the object format and by defining the `include_functions` field.

      rule: "rename_variables",
      include_functions: true,

## Rule Filtering

When using the object format, a rule can be limited to run only for specific files using `apply_to_files` and `skip_files`. Both field use this [glob patterns implementation](https://github.com/olson-sean-k/wax/blob/master/README.md#patterns). They can be provided as a single pattern string or an array of patterns.

  * `apply_to_files`: The rule runs only on files whose path matches at least one pattern. If set and the file does not match, this rule is skipped for that file.
  * `skip_files`: The rule is skipped for any file whose path matches any pattern. This is **applied after** `apply_to_files`, so you can combine both.

These apply per rule: you can run one rule on all files and another only on `src/**/*.lua`, or skip a rule for test files.

    rules: [
        rule: "remove_comments",
        // skip this rule for anything that's in a 'vendor' folder
        skip_files: "**/vendor/**",
      },
        rule: "rename_variables",
        // apply only this rule for files under the 'src' folder
        apply_to_files: ["src/**/*.lua"],
        include_functions: false,
      },


Added in 0.7.0

## Parameters

Name| Type| Description
---|---|---
except| `string array`| Comments matching any of the given regular expressions will be kept (added in v0.13.1)

It is important to note that when generating code with the `dense` or `readable` generator (e.g. `darklua process src --format dense`), the comments will already be removed. The only way to retain comments is to use the `retain_lines` format and avoid this rule.

The `except` parameter is useful to avoid removing specific comments like `--!native` (which trigger native compilation of modules when using Luau on Roblox). For example, to avoid removing all comments starting with `--!`:

      rule: "remove_comments",
      except: ["^--!"],

## Examples

InputOutput

    return nil -- this is a comment

    return nil

Input| Output

    return nil -- this is a comment

    return nil


Added in 0.14.1

This rule removes all usage of the floor division operator (`//`). It replaces those operations with a regular division (`/`) followed by a `math.floor()` call.

## Examples

InputOutput

    return variable // divider

    return math.floor(variable / divider)

InputOutput

    variable //= 5

    variable =math.floor(variable/ 5)

Input| Output

    return variable // divider

    return math.floor(variable / divider)

    variable //= 5

    variable =math.floor(variable/ 5)


Added in 0.2.3

When a condition from a while statement can be evaluated to false and has no side effects, this rule will remove the statement. For example, the following while statement would be removed.

This rule is influenced by the evaluation system of darklua. The more darklua can evaluate code, the better this rule can be applied.

## Examples

InputOutput

    while 'foo' == 'bar' do
        -- ...
    end

Input| Output

    while 'foo' == 'bar' do
        -- ...
    end


Added in 0.2.0

This simple rule removes all empty do blocks found.

## Examples

InputOutput

    do
    end
    do
        do
        end
    end
    return {}

    return {}

Input| Output

    do
    end
    do
        do
        end
    end
    return {}

    return {}


## Usage

The following section will detail the different commands of darklua. You can also get a list of the available commands and options using the command line tool itself, simply run:

    darklua help

To get help on a specific command, simply append `--help` (or `-h`) to the command name. For example, to get help on the `process` command:

    darklua process --help

### Process

The process command is similar to the minify command: it takes an input path and generates code at the output path. This command will apply [rules](https://darklua.com/docs/rules/) (the default rules or the one given in the configuration file) to each Lua file.

    darklua process <input-path> <output-path>

    optional arguments:
      -c, --config <path>
      Path to a configuration file

#### Example

If you have a `src` folder that contains a bunch of Lua scripts (files ending with `.lua`), you can process all the files with the default configuration (or with the configuration file located in the same folder where you are running the command) into a new folder called `processed-src` using the following command:

    darklua process src processed-src

If a configuration file is found in the folder where the command is run, darklua will automatically use it. If your configuration file is not named `.darklua.json` or `.darklua.json5`, or not located in the folder where you are running the command, you must specify it with the `--config` argument:

    darklua process src processed-src --config ./path/config.json
    # or the shorter version:
    darklua process src processed-src -c ./path/config.json

### Convert

This command takes a data file and converts it to a Lua file. If no output path is provided, the Lua code will be printed to the console.

The supported data formats are: `json`, `json5`, `yaml` or `toml`.

    darklua convert <input-path> [output-path]

    optional arguments:
      -f, --format {json, yaml, toml}

### Minify

This command reads Lua code and reformats it to reduce the size of the code, measured in total bytes. The input path can be a single file name or a directory name. Given a directory, darklua will find all Lua files under that directory and output them following the same hierarchy.

    darklua minify <input-path> <output-path>

    optional arguments:
      --column-span <number>
      The maximum number of characters that should be written on a line

#### Example

If you have a `src` folder that contains a bunch of Lua scripts (files ending with `.lua`), you can generate the minified version of these Lua scripts into a new folder called `minified-src` using the following command:

    darklua minify src minified-src


Added in 0.17.0

This rule converts calls to `math.sqrt(value)` into the equivalent expression `value ^ 0.5`. This transformation can be useful in some Lua runtime as a performance optimization.

## Examples

InputOutput

    local result = math.sqrt(16)

    local result = 16^0.5

InputOutput

    local result = math.sqrt(x + y)

    local result = (x + y)^0.5

InputOutput

    local result = math.sqrt(calculate_value())

    local result = calculate_value()^0.5

Input| Output

    local result = math.sqrt(16)

    local result = 16^0.5

    local result = math.sqrt(x + y)

    local result = (x + y)^0.5

    local result = math.sqrt(calculate_value())

    local result = calculate_value()^0.5


Added in 0.2.1

## Parameters

Name| Type| Description| Default
---|---|---|---
globals| `array`| What identifier should be avoided when generating new names| `['$default']`
include_functions| `boolean`| Controls if function names get renamed (added in v0.7.0)| `false`

To configure this rule to avoid using Roblox globals, add `$roblox` to the

      rule: "rename_variables",
      globals: ["$default", "$roblox"],

A configuration to avoid all identifiers from the default group and the identifier `a` and `b`.

      rule: "rename_variables",
      globals: ["$default", "a", "b"],

## Globals

The `globals` property have special values that can be use to group multiple values together. They start with an `$` character.

### $default

The default standard globals in Lua

    arg, assert, collectgarbage, coroutine, debug, dofile, error, gcinfo, getfenv, getmetatable, io, ipairs, load, loadfile, loadstring, math, module, newproxy, next, os, package, pairs, pcall, print, rawequal, rawget, rawset, require, select, setfenv, setmetatable, string, table, tonumber, tostring, type, unpack, xpcall, _G, _VERSION

### $roblox

The globals from Roblox Lua

    Axes, bit32, BrickColor, CellId, ColorSequence, ColorSequenceKeypoint, Color3, CFrame, DateTime, DebuggerManager, delay, DockWidgetPluginGuiInfo, elapsedTime, Enum, Faces, Instance, LoadLibrary, game, NumberRange, NumberSequence, NumberSequenceKeypoint, PathWaypoint, PhysicalProperties, plugin, PluginDrag, PluginManager, printidentity, Random, Ray, RaycastParams, Rect, Region3, Region3int16, script, settings, shared, stats, spawn, tick, time, TweenInfo, typeof, UDim, UDim2, UserSettings, utf8, Vector2, Vector2int16, Vector3, Vector3int16, version, wait, warn, workspace, ypcall

Note that Lua language key words such as `return` and `do` are automatically excluded and not configurable.


Added in 0.7.0

It is important to note that when generating code with the `dense` or `readable` generator (e.g. `darklua process src --format dense`), all the spacing (whitespaces, tabs, new lines) will not be considered. The only way to retain the spacing information is to use the `retain_lines` format and avoid this rule.

## Examples

InputOutput

    local function getAverage(array)
        local sum = 0
        for _, element in ipairs(array) do
            sum = sum + element
        end
        return sum / #array
    end

    local function getAverage(array)
    local sum=0
    for _,element in ipairs(array)do
    sum=sum+element
    end
    return sum/#array
    end

Input| Output

    local function getAverage(array)
        local sum = 0
        for _, element in ipairs(array) do
            sum = sum + element
        end
        return sum / #array
    end

    local function getAverage(array)
    local sum=0
    for _,element in ipairs(array)do
    sum=sum+element
    end
    return sum/#array
    end


Added in 0.13.0

This rule removes unused variables from code. It also removes unused local function definitions.

## Examples

InputOutput

    local var

InputOutput

    local var1 = true
    local var2 = var1

InputOutput

    local var = call()

    call()

InputOutput

    local function fn() print('unused') end

InputOutput

    local a, b, c = 1, 2, 3
    return a

    local a=1
    return a

Input| Output

    local var

    local var1 = true
    local var2 = var1

    local var = call()

    call()

    local function fn() print('unused') end

    local a, b, c = 1, 2, 3
    return a

    local a=1
    return a


Darklua is capable of bundling Lua code: it will start from a given file and attempt to merge every require into a single file.

**Warning:** it is important that each module do not have any side effects at require-time, as the order of those side effects may not be preserved in the bundled code.

The process command will bundle Lua code when defined in the configuration file. Defining the `bundle` field will set up darklua to bundle code. The following minimal configuration will bundle code using path requires:

      bundle: {
        require_mode: "path",
      },

## Process Command

To bundle code, use the process command. Provide the entry point that you would like to bundle from and the second argument is the output location:

    darklua process entry-point.lua bundled.lua

Given the `entry-point.lua`, darklua will recursively follow the requires and inline the code into a single `bundled.lua` file.

## Configuration

### Require Mode

Require modes are what darklua uses to interpret require calls to other modules. They are useful when bundling or when converting require calls using the [`convert_require` rule](https://darklua.com/docs/rules/convert_require/). When bundling code, darklua uses the require mode defined in the configuration file (in the bundling part) to find the source files.

Currently, there is **2 require mode available for bundling**:

Mode name | Usage | Example | Documentation
---|---|---|---
path | with regular file paths | require("./module") | [documentation](https://darklua.com/docs/path-require-mode/)
luau | with Luau module paths | require("@self/module") | [documentation](https://darklua.com/docs/luau-require-mode/)

For more information about how to configure the require mode, take a look at the [path require mode](https://darklua.com/docs/path-require-mode/) or the [luau require mode](https://darklua.com/docs/luau-require-mode/) configuration pages.

### Excludes

Provide a list of patterns to exclude certain paths from the bundle.

For example, to avoid bundling any require to paths starting with `@lune`:

      bundle: {
        require_mode: "path",
        excludes: ["@lune/**"],
      },

These patterns are similar to Unix globs, but for more information about the differences and the syntax, see the [pattern library documentation](https://github.com/olson-sean-k/wax/blob/master/README.md#patterns) used by darklua.

### Modules Identifier

When darklua bundles multiple modules into a single file, it uses a variable to store all the required modules. This parameter lets you modify that variable name if needed.

      bundle: {
        require_mode: "path",
        // by default, darklua will use the following value
        modules_identifier: "__DARKLUA_BUNDLE_MODULES",
      },

## Require Data Files as Lua

When bundling, the `path` require mode is able to require data files and convert them into Lua data. All that is needed is that the file has one of the recognized extensions:

  * [JSON](https://en.wikipedia.org/wiki/JSON) with `.json` or `.json5`

  * [YAML](https://en.wikipedia.org/wiki/YAML) with `.yml` or `.yaml`

  * [Toml](https://toml.io/en/) with `.toml`

Text files (ending with `.txt`) are also supported and they will simply map to a string with the file content.

If you would like to see a format added, feel free to submit a request using a [GitHub issue](https://github.com/seaofvoices/darklua/issues).

### JSON Example

JSON fileGenerated Lua

      "experienceActivation_singleton": "experienceActivation",
      "experienceConfiguration_singleton": "experienceConfiguration",
      "experience_singleton": {
        "experience": {
          "assetId": 3296599132,
          "startPlaceId": 8667346609
      },
      "placeConfiguration_start": "placeConfiguration",
      "placeFile_start": {
        "placeFile": {
          "version": 2
      },
      "place_start": {
        "place": {
          "assetId": 8667346609

        experienceActivation_singleton = "experienceActivation",
        experienceConfiguration_singleton = "experienceConfiguration",
        experience_singleton = {
            experience = {
                assetId = 3296599132,
                startPlaceId = 8667346609,
            },
        },
        placeConfiguration_start = "placeConfiguration",
        placeFile_start = {
            placeFile = {
                version = 2,
            },
        },
        place_start = {
            place = {
                assetId = 8667346609,
            },
        },

JSON file| Generated Lua

      "experienceActivation_singleton": "experienceActivation",
      "experienceConfiguration_singleton": "experienceConfiguration",
      "experience_singleton": {
        "experience": {
          "assetId": 3296599132,
          "startPlaceId": 8667346609
      },
      "placeConfiguration_start": "placeConfiguration",
      "placeFile_start": {
        "placeFile": {
          "version": 2
      },
      "place_start": {
        "place": {
          "assetId": 8667346609

        experienceActivation_singleton = "experienceActivation",
        experienceConfiguration_singleton = "experienceConfiguration",
        experience_singleton = {
            experience = {
                assetId = 3296599132,
                startPlaceId = 8667346609,
            },
        },
        placeConfiguration_start = "placeConfiguration",
        placeFile_start = {
            placeFile = {
                version = 2,
            },
        },
        place_start = {
            place = {
                assetId = 8667346609,
            },
        },

### YAML Example

YAML fileGenerated Lua

    name: Tests
    on:
      push:
        branches:
          - main
      pull_request:
        branches:
          - main
    jobs:
      code-style:
        name: Verify code style
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - name: Verify code format
            run: cargo fmt -- --check

        name = "Tests",
        on = {
            push = {
                branches = { "main" },
            },
            pull_request = {
                branches = { "main" },
            },
        },
        jobs = {
            ["code-style"] = {
                name = "Verify code style",
                ["runs-on"] = "ubuntu-latest",
                steps = {
                        uses = "actions/checkout@v3",
                    },
                        name = "Verify code format",
                        run = "cargo fmt -- --check",
                    },
                },
            },
        },

YAML file| Generated Lua

    name: Tests
    on:
      push:
        branches:
          - main
      pull_request:
        branches:
          - main
    jobs:
      code-style:
        name: Verify code style
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v3
          - name: Verify code format
            run: cargo fmt -- --check

        name = "Tests",
        on = {
            push = {
                branches = { "main" },
            },
            pull_request = {
                branches = { "main" },
            },
        },
        jobs = {
            ["code-style"] = {
                name = "Verify code style",
                ["runs-on"] = "ubuntu-latest",
                steps = {
                        uses = "actions/checkout@v3",
                    },
                        name = "Verify code format",
                        run = "cargo fmt -- --check",
                    },
                },
            },
        },

### Toml Example

Toml fileGenerated Lua

    [package]
    name = "darklua"
    version = "0.18.0"
    edition = "2018"
    readme = "README.md"
    description = "Transform Lua scripts"
    repository = "https://github.com/seaofvoices/darklua"
    homepage = "https://darklua.com"
    license = "MIT"
    keywords = ["lua", "obsfucation", "minify"]
    exclude = ["site"]

    [badges]
    github = { repository = “seaofvoices/darklua” }

    [lib]
    name = “darklua_core”
    path = “src/lib.rs”

    [[bin]]
    name = “darklua”
    path = “src/bin.rs”

    [features]
    tracing = [“dep:tracing”]

    [dependencies]
    clap = { version = “4.1.1”, features = [“derive”] }
    durationfmt = “0.1.1”
    elsa = “1.7.0”
    env_logger = “0.9.0”
    full_moon = { version = “0.16.2”, features = [“roblox”] }
    json5 = “0.4”
    log = “0.4”
    serde = { version = “1.0”, features = [“derive”] }
    serde_json = “1.0.92”
    serde_yaml = “0.9.17”
    toml = “0.7.2”
    tracing = { version = “0.1”, optional = true }
    wax = “0.5.0”

    [dev-dependencies]
    assert_cmd = “2.0.4”
    criterion = { version = “0.4”, features = [“html_reports”] }
    include_dir = “0.7.3”
    insta = { version = “1.29.0”, features = [“json”, “filters”] }
    paste = “1.0”
    pretty_assertions = “0.7.2”
    rand = “0.7.3”
    rand_distr = “0.2.2”
    serde_bytes = “0.11”
    tempfile = “3.5.0”
    tracing-subscriber = “0.3.16”
    tracing-tracy = “0.10.1”

    [target.‘cfg(target_arch = “wasm32”)‘.dependencies]
    node-sys = “0.4.2”
    web-sys = { version = “0.3.60”, features = [“Window”, “Performance”] }

    [profile.dev.package.full_moon]
    opt-level = 3

    [[bench]]
    name = “process_bench”
    harness = false

    [[bench]]
    name = “parse_bench”
    harness = false

        bench = {
            { harness = false, name = "process_bench" },
            { harness = false, name = "parse_bench" },
        },
        bin = {
            { name = "darklua", path = "src/bin.rs" },
        },
        badges = {
            github = { repository = "seaofvoices/darklua" },
        },
        dependencies = {
            durationfmt = "0.1.1",
            elsa = "1.7.0",
            env_logger = "0.9.0",
            json5 = "0.4",
            log = "0.4",
            serde_json = "1.0.92",
            serde_yaml = "0.9.17",
            toml = "0.7.2",
            wax = "0.5.0",
            clap = { features = { "derive" }, version = "4.1.1" },
            full_moon = { features = { "roblox" }, version = "0.16.2" },
            serde = { features = { "derive" }, version = "1.0" },
            tracing = { optional = true, version = "0.1" },
        },
        ["dev-dependencies"] = {
            assert_cmd = "2.0.4",
            include_dir = "0.7.3",
            paste = "1.0",
            pretty_assertions = "0.7.2",
            rand = "0.7.3",
            rand_distr = "0.2.2",
            serde_bytes = "0.11",
            tempfile = "3.5.0",
            ["tracing-subscriber"] = "0.3.16",
            ["tracing-tracy"] = "0.10.1",
            criterion = { features = { "html_reports" }, version = "0.4" },
            insta = { features = { "json", "filters" }, version = "1.29.0" },
        },
        features = {
            tracing = { "dep:tracing" },
        },
        lib = { name = "darklua_core", path = "src/lib.rs" },
        package = {
            description = "Transform Lua scripts",
            edition = "2018",
            exclude = { "site" },
            homepage = "https://darklua.com",
            keywords = { "lua", "obsfucation", "minify" },
            license = "MIT",
            name = "darklua",
            readme = "README.md",
            repository = "https://github.com/seaofvoices/darklua",
            version = "0.18.0",
        },
        profile = {
            dev = {
                package = { full_moon = { ["opt-level"] = 3 } },
            },
        },
        target = {
            ['cfg(target_arch = "wasm32")'] = {
                dependencies = {
                    ["node-sys"] = "0.4.2",
                    ["web-sys"] = { features = { "Window", "Performance" }, version = "0.3.60" },
                },
            },
        },

Toml file| Generated Lua

    [package]
    name = "darklua"
    version = "0.18.0"
    edition = "2018"
    readme = "README.md"
    description = "Transform Lua scripts"
    repository = "https://github.com/seaofvoices/darklua"
    homepage = "https://darklua.com"
    license = "MIT"
    keywords = ["lua", "obsfucation", "minify"]
    exclude = ["site"]

    [badges]
    github = { repository = “seaofvoices/darklua” }

    [lib]
    name = “darklua_core”
    path = “src/lib.rs”

    [[bin]]
    name = “darklua”
    path = “src/bin.rs”

    [features]
    tracing = [“dep:tracing”]

    [dependencies]
    clap = { version = “4.1.1”, features = [“derive”] }
    durationfmt = “0.1.1”
    elsa = “1.7.0”
    env_logger = “0.9.0”
    full_moon = { version = “0.16.2”, features = [“roblox”] }
    json5 = “0.4”
    log = “0.4”
    serde = { version = “1.0”, features = [“derive”] }
    serde_json = “1.0.92”
    serde_yaml = “0.9.17”
    toml = “0.7.2”
    tracing = { version = “0.1”, optional = true }
    wax = “0.5.0”

    [dev-dependencies]
    assert_cmd = “2.0.4”
    criterion = { version = “0.4”, features = [“html_reports”] }
    include_dir = “0.7.3”
    insta = { version = “1.29.0”, features = [“json”, “filters”] }
    paste = “1.0”
    pretty_assertions = “0.7.2”
    rand = “0.7.3”
    rand_distr = “0.2.2”
    serde_bytes = “0.11”
    tempfile = “3.5.0”
    tracing-subscriber = “0.3.16”
    tracing-tracy = “0.10.1”

    [target.‘cfg(target_arch = “wasm32”)‘.dependencies]
    node-sys = “0.4.2”
    web-sys = { version = “0.3.60”, features = [“Window”, “Performance”] }

    [profile.dev.package.full_moon]
    opt-level = 3

    [[bench]]
    name = “process_bench”
    harness = false

    [[bench]]
    name = “parse_bench”
    harness = false

        bench = {
            { harness = false, name = "process_bench" },
            { harness = false, name = "parse_bench" },
        },
        bin = {
            { name = "darklua", path = "src/bin.rs" },
        },
        badges = {
            github = { repository = "seaofvoices/darklua" },
        },
        dependencies = {
            durationfmt = "0.1.1",
            elsa = "1.7.0",
            env_logger = "0.9.0",
            json5 = "0.4",
            log = "0.4",
            serde_json = "1.0.92",
            serde_yaml = "0.9.17",
            toml = "0.7.2",
            wax = "0.5.0",
            clap = { features = { "derive" }, version = "4.1.1" },
            full_moon = { features = { "roblox" }, version = "0.16.2" },
            serde = { features = { "derive" }, version = "1.0" },
            tracing = { optional = true, version = "0.1" },
        },
        ["dev-dependencies"] = {
            assert_cmd = "2.0.4",
            include_dir = "0.7.3",
            paste = "1.0",
            pretty_assertions = "0.7.2",
            rand = "0.7.3",
            rand_distr = "0.2.2",
            serde_bytes = "0.11",
            tempfile = "3.5.0",
            ["tracing-subscriber"] = "0.3.16",
            ["tracing-tracy"] = "0.10.1",
            criterion = { features = { "html_reports" }, version = "0.4" },
            insta = { features = { "json", "filters" }, version = "1.29.0" },
        },
        features = {
            tracing = { "dep:tracing" },
        },
        lib = { name = "darklua_core", path = "src/lib.rs" },
        package = {
            description = "Transform Lua scripts",
            edition = "2018",
            exclude = { "site" },
            homepage = "https://darklua.com",
            keywords = { "lua", "obsfucation", "minify" },
            license = "MIT",
            name = "darklua",
            readme = "README.md",
            repository = "https://github.com/seaofvoices/darklua",
            version = "0.18.0",
        },
        profile = {
            dev = {
                package = { full_moon = { ["opt-level"] = 3 } },
            },
        },
        target = {
            ['cfg(target_arch = "wasm32")'] = {
                dependencies = {
                    ["node-sys"] = "0.4.2",
                    ["web-sys"] = { features = { "Window", "Performance" }, version = "0.3.60" },
                },
            },
        },


Added in 0.12.0

## Parameters

Name| Type| Description| Default
---|---|---|---
text| `string`| The string to use inside the comment (required if `file` is not defined)|
file| `string`| A path to a file to be used as the comment content (required if `text` is not defined)|
location| `"start" or "end"`| The location where to add the comment| `start`

Use this rule to automatically insert a comment at the start or end of a file. This rule can be useful if you want to insert your license in each file.

**Note:** make sure to avoid using the `remove_comments` rule _after_ this rule in the process sequence, otherwise you will be removing your brand new comment.

## Examples

InputOutput

    print('Print from module')

    --!native
    print('Print from module')

InputOutput

    print('Print from module')

    print('Print from module')--hello!

Input| Output

    print('Print from module')

    --!native
    print('Print from module')

    print('Print from module')

    print('Print from module')--hello!


When transforming Lua using the `darklua process` command, darklua can read a configuration file to customize how the code is transformed.

## Rules

Rules are what transform Lua code. When processing code with darklua, it is essentially going through a given list of rules one by one, each one transforming code and feeding it to the next rule.

**Important note:** one thing to understand is that the ordering of these rules sometimes have importance! For example, you should inject a value before trying to compute expressions statically or optimize if branches out.

More information is available in the section specific to [rule configuration](https://darklua.com/docs/rules/).

## Location

From the directory where you run `darklua process`, darklua will attempt to read the following files automatically:

  * `.darklua.json`
  * `.darklua.json5`

To provide a different configuration file, this subcommand also accept a specific path to a configuration file with `--config <path>`.

## Filtering

It is possible to limit which files are processed using `apply_to_files` and `skip_files`. Both accept glob patterns [from this implementation](https://github.com/olson-sean-k/wax/blob/master/README.md#patterns) (same syntax as `bundle.excludes`). Each field can be a single pattern string or an array of patterns.

  * `apply_to_files`: When set, only files whose path matches at least one pattern are processed. Files that do not match any pattern are skipped entirely.
  * `skip_files`: When set, any file whose path matches any pattern is skipped. This is **applied after** `apply_to_files`, so you can combine both (e.g. process only `src/**/*.lua` but skip `src/**/*.test.lua`).

When both are empty (the default), all files are processed.

## Quick Reference

Any missing field will be replaced with its default value.

      // Output code in different ways depending on the given generator
      generator: "retain_lines", // default value

      // Restrict on which files rules will be applied
      apply_to_files: ["src/**/*.luau"],
      // Exclude applying rules to some files
      skip_files: ["**/*.test.lua"],

      bundle: {
        // Identifier used by darklua to store the bundled modules
        modules_identifier: "__DARKLUA_BUNDLE_MODULES",

        // To avoid bundling certain paths, insert patterns into the list to exclude
        // them (see https://github.com/olson-sean-k/wax/blob/master/README.md#patterns
        // for details about the syntax)
        excludes: [],

        // Configure how requires are interpreted
        require_mode: {
          // Currently, the only supported require mode is `path`
          name: "path",

          // When requiring folders, require the file named like this value inside of it
          module_folder_name: "init",

          // Provide paths that can be required with a specific prefix
          sources: {
            // Map strings to paths relative to the configuration files itself
            // for example, to support requires of Wally packages as `pkg/PackageName`,
            // map `pkg` to a path to the `Packages` folder created by Wally:
            pkg: "./Packages",
          },

          // Enable or disable finding `.luaurc` files to load source aliases
          use_luau_configuration: true, // default value
        },
      },

      // Define the rules that will transform the Lua code.
      // If you do not provide this field, the default list of rules is
      // going to be executed.
      rules: [
        "remove_comments",
        "remove_spaces",
        // For rules with parameters, use the object notation to specify
        // the values to override
          rule: "inject_global_value",
          identifier: "DEBUG",
          value: false,
        },
        "remove_nil_declaration",
        "compute_expression",
        "remove_unused_if_branch",
        "filter_after_early_return",
        "remove_empty_do",
      ],


Added in 0.3.2

This rule will merge consecutive local assignments.

The rule will not merge assignments if one assignment temporally depends on the previous one, since it would break the code or change the behavior. The following code would not be changed:

    local foo = 1
    local bar = foo

Since functions can return multiple values, assignments that extract more than one value will not get merged.

    local foo, bar = multiple_return_values()
    local baz = 0

## Examples

InputOutput

    local foo = 1
    local bar = 2

    local foo ,
    bar = 1
    ,2

Input| Output

    local foo = 1
    local bar = 2

    local foo ,
    bar = 1
    ,2


Added in 0.12.0

## Parameters

Name| Type| Description| Default
---|---|---|---
strategy| `"string" or "tostring"`| Defines how darklua converts the interpolated strings into `string.format` calls. The "string" strategy will make the rule use the `%s` specifier and the "tostring" strategy will use the `%*` specifier.| `string`

This rule removes all interpolated strings and replaces them with `string.format` calls.

## Examples

InputOutput

    return `abc`

    return 'abc'

InputOutput

    return ``

    return ''

InputOutput

    return `+{value} (in seconds)`

    return string.format('+%s (in seconds)', tostring(value))

InputOutput

    return `Total = {#elements}`

    return string.format('Total = %s', tostring(#elements))

Input| Output

    return `abc`

    return 'abc'

    return ``

    return ''

    return `+{value} (in seconds)`

    return string.format('+%s (in seconds)', tostring(value))

    return `Total = {#elements}`

    return string.format('Total = %s', tostring(#elements))


## Rokit

When using [Rokit](https://github.com/rojo-rbx/rokit), install darklua with the following command:

    rokit add seaofvoices/darklua

## Foreman

If you are already using [Foreman](https://github.com/Roblox/foreman), then installing darklua is as simple as adding this line in the `foreman.toml` file:

    darklua = { github = "seaofvoices/darklua", version = "=0.18.0" }

## Download a Release

Pre-built binaries are also available in the [releases page](https://github.com/seaofvoices/darklua/releases) on GitHub. Download the appropriate file for you OS and unzip it, then place the executable where it makes sense for you.

If you are unfamiliar with command line tools and not sure where to start, search how to place the executable so that you can run it from anywhere (for example on [windows](https://lmgtfy.app/?q=add+executable+in+path+windows) or [mac](https://lmgtfy.app/?q=add+executable+in+path+mac))

## Cargo

If you are familiar with the Rust environment, you can also build darklua from source using [cargo](https://doc.rust-lang.org/cargo/getting-started/installation.html).

    cargo install darklua

If you want to use the lastest darklua available, install it using the git url:

    cargo install --git https://github.com/seaofvoices/darklua.git

## Other package managers

darklua is available in some third-party package managers. These packages are primarily supported by the community.

[](https://repology.org/project/darklua/versions)


unreleased

## Parameters

Name| Type| Description
---|---|---
match| `string array`| Attribute names matching any of the given regular expressions will be removed. When empty (default), all attributes are removed.

The `remove_attribute` rule can remove _specific_ function attributes or _all_ function attributes. Attributes are metadata annotations that can be attached to functions using the `@` symbol (e.g., `@deprecated`, `@native`).

By default, all attributes are removed. The `match` parameter allows selective removal of only specific attributes using regular expressions. For example, to remove `@deprecated` attributes while keeping `@native`, configure the rule this way:

      rule: "remove_attribute",
      match: ["deprecated"],

## Examples

InputOutput

    @deprecated
    local function example()
      return process()
    end

    local function example()
      return process()
    end

Input| Output

    @deprecated
    local function example()
      return process()
    end

    local function example()
      return process()
    end


Added in 0.7.0

When an index expression is using a static string (or an expression that can be statically evaluated into a string), this rule replaces it with a field expression. This rule also applies for table declarations: an entry that uses the bracket syntax (e.g. `{ ["key"] = value }`) will get converted into a field-like entry when possible.

## Examples

InputOutput

    return var['field']

    return var.field

InputOutput

    return { ['field'] = true }

    return { field=true }

Input| Output

    return var['field']

    return var.field

    return { ['field'] = true }

    return { field=true }


When outputting code, darklua uses a generator to convert its internal representation of code into actual Lua code in text. You can configure how the code is written by choosing which generator to use.

## retain_lines

This is the **default generator** and the most useful one. This generator will attempt to keep the line numbers from the original code in the generated code.

### Example

Let’s take this snippet of code.

    local function giveReason(message)
        if _G.DEBUG_MODE then
            return message .. " - reason: " .. getReason()
        else
            return message
        end
    end

If darklua processes this code and inline the `_G.DEBUG_MODE` as `true`, remove the if statement and the spaces, the `retain_lines` generator will keep what’s left to fit on the same line. It will produce the following code:

    local function giveReason(message)

    return message.." - reason: "..getReason()

    end

You can specify this generator in the configuration file with:

      generator: "retain_lines",

## dense

This generator will minimize the amount of spaces used when producing Lua code. It will fill each line up to a certain number of characters. By default, it will maximize each line to 80 characters.

The dense generator does not output comments from the original code.

You can specify this generator in the configuration file with:

      generator: "dense",

To configure the maximum column width parameter, use the object notation for the generator value:

      generator: { name: "dense", column_span: 50 },

## readable

This generator will produce Lua code that is, as the name suggest, readable at best. Darklua does not aim to be used as a formatter, so the results may not be optimal.

Compared to the retain_lines generator, this one will completely re-generate the code and will not even attempt to keep the line numbers.

The readable generator does not output comments from the original code.

You can specify this generator in the configuration file with:

      generator: "readable",

To configure the maximum column width parameter, use the object notation for the generator value:

      generator: { name: "readable", column_span: 50 },


Added in 0.12.0

## Parameters

Name| Type| Description| Default
---|---|---|---
preserve_arguments_side_effects| `boolean`| Defines how darklua handle arguments passed to the function. If true, darklua will inspect each argument and preserve any potential side effects. When false, darklua will not perform any verification and simply erase any arguments passed.| `true`

This rule removes all function calls to `assert`.

## Examples

InputOutput

    assert(condition, 'condition is incorrect!')

    do end

Input| Output

    assert(condition, 'condition is incorrect!')

    do end


Added in 0.17.0

This rule converts function calls that use the colon syntax (`:`) to function calls using dot notation (`.`).

This rule only transforms method calls where the prefix is an identifier. Other method calls using field access, index access or function call prefixes are left unchanged.

## Examples

InputOutput

    obj:method()

    obj.method(obj)

InputOutput

    game:GetService('RunService')

    game.GetService(game,'RunService')

InputOutput

    return player:LoadCharacter()

    return player.LoadCharacter(player)

Input| Output

    obj:method()

    obj.method(obj)

    game:GetService('RunService')

    game.GetService(game,'RunService')

    return player:LoadCharacter()

    return player.LoadCharacter(player)


Added in 0.3.3

Local functions that are not recursive will be transformed to a local assignment statement.

Note that, depending on your Lua runtime implementation, you may no longer be able to use reflection-like APIs (eg `debug.info`) to acquire the name of the function, or the function name may be missing from stack traces of `error` invocations.

## Examples

InputOutput

    local function foo(a, b)
        return a + b
    end

    local foo=function(a, b)
    return a + b
    end

Input| Output

    local function foo(a, b)
        return a + b
    end

    local foo=function(a, b)
    return a + b
    end


Added in 0.14.1

This rule removes all `if` expressions (not if statements!) and replaces them with an equivalent expression.

**Note:** this rule is useful if you are converting Luau code into regular Lua code.

## Examples

InputOutput

    local variable = if condition() then { option = true } else { option = false }

    local variable = condition() and{ option = true } or{ option = false }

Input| Output

    local variable = if condition() then { option = true } else { option = false }

    local variable = condition() and{ option = true } or{ option = false }


## All Rules

[append_text_commentAppend a comment at the start or end of a file](https://darklua.com/docs/rules/append_text_comment/)[compute_expressionComputes expressions statically](https://darklua.com/docs/rules/compute_expression/)[convert_function_to_assignmentConvert global function definitions to assignment statements](https://darklua.com/docs/rules/convert_function_to_assignment/)[convert_index_to_fieldConvert index expression into field expressions](https://darklua.com/docs/rules/convert_index_to_field/)[convert_local_function_to_assignConvert local function definitions to variable declarations](https://darklua.com/docs/rules/convert_local_function_to_assign/)[convert_luau_numberConvert Luau numbers into Lua compatible numbers](https://darklua.com/docs/rules/convert_luau_number/)[convert_requireConvert require calls from one environment to another](https://darklua.com/docs/rules/convert_require/)[convert_square_root_callConvert calls to `math.sqrt(value)` into an exponent form (`value ^ 0.5`)](https://darklua.com/docs/rules/convert_square_root_call/)[filter_after_early_returnRemoves unreachable statements following return statements](https://darklua.com/docs/rules/filter_after_early_return/)[group_local_assignmentGroups local assignments into a single statement](https://darklua.com/docs/rules/group_local_assignment/)[inject_global_valueInject a global variable](https://darklua.com/docs/rules/inject_global_value/)[remove_assertionsRemoves call to the assert function](https://darklua.com/docs/rules/remove_assertions/)[remove_commentsRemoves comments](https://darklua.com/docs/rules/remove_comments/)[remove_compound_assignmentConvert compound assignments into regular assignments](https://darklua.com/docs/rules/remove_compound_assignment/)[remove_continueRemove continue statements](https://darklua.com/docs/rules/remove_continue/)[remove_debug_profilingRemoves call to debug.profilebegin and debug.profileend](https://darklua.com/docs/rules/remove_debug_profiling/)[remove_empty_doRemoves empty do statements](https://darklua.com/docs/rules/remove_empty_do/)[remove_floor_divisionRemoves floor divisions](https://darklua.com/docs/rules/remove_floor_division/)[remove_function_call_parensRemoves functions call parentheses](https://darklua.com/docs/rules/remove_function_call_parens/)[remove_if_expressionRemove if expressions](https://darklua.com/docs/rules/remove_if_expression/)[remove_interpolated_stringRemoves interpolated strings (backtick strings)](https://darklua.com/docs/rules/remove_interpolated_string/)[remove_method_callRemoves usages of the method syntax (`:`) in function calls](https://darklua.com/docs/rules/remove_method_call/)[remove_method_definitionConverts function defined using `:` to use a `.`](https://darklua.com/docs/rules/remove_method_definition/)[remove_nil_declarationRemoves explicit declaration to `nil`](https://darklua.com/docs/rules/remove_nil_declaration/)[remove_spacesRemoves spaces](https://darklua.com/docs/rules/remove_spaces/)[remove_typesRemoves types](https://darklua.com/docs/rules/remove_types/)[remove_unused_if_branchRemoves unused if branch](https://darklua.com/docs/rules/remove_unused_if_branch/)[remove_unused_variableRemoves unused variable declarations](https://darklua.com/docs/rules/remove_unused_variable/)[remove_unused_whileRemoves unused while statement](https://darklua.com/docs/rules/remove_unused_while/)[rename_variablesRenames variables and function parameters](https://darklua.com/docs/rules/rename_variables/)

## Unreleased Rules

These rules will be added in the next release:

[remove_attributeRemove function attributes](https://darklua.com/docs/rules/remove_attribute/)