Forest Logo
search
package_2

sawdust

By @griffin-dalby

Roblox

Mirrored from Wally

This version ships no README. Showing the README from v1.4.0, mirrored from wally.

๐ŸŒฒ Sawdust Framework

Made for Roblox LuaU Apache 2.0

Sawdust is a lightweight, modular framework for Roblox developers who want clarity, control, and smart abstractions, without the bloat ๐Ÿ˜‰

๐Ÿ’– Built with love by Griffin Dalby
๐Ÿ›  Designed for efficient, easy-to-read, and easy-to-use code - made for devs who hate reading docs.


โœจ Features

  • ๐Ÿ’‰ Service Injection System
    Build, inject, and manage services with dependency resolution.

  • ๐Ÿ”— Smart Networking
    Networking w/ a custom protocol for secure returns from each side, all with a friendly interface.

  • ๐Ÿ“ฆ CDN System
    Efficient asset delivery with preload batching and efficient caching.

  • ๐Ÿ“ฃ Signal Emitters
    Embeddable event behavior for services or general-purpose modules.

  • ๐Ÿ“œ Cache API
    Stackable cache management built for structure, and speed.

  • ๐Ÿงน Maid Utility
    Clean up anything, connections, callbacks, instances, all with tag-based logic.

  • โœˆ And much, much more planned
    I hope to get as much quality of life features as possible.

  • ๐ŸŒณ Lignin
    Lignin is a plugin being developed to aid even further with sawdust development. You'll be able to gradually create networking channels and events/functions, and many more things All of these will create automatic type metadata for a dynamic feeling typechecking experience including assetIds and networking event names.


๐Ÿš€ Quick Start

Network from server <-> client

--> In StarterCharacterScripts.Mechanics

local networking = sawdust.core.networking
local mechanics = networking.getChannel('mechanics')

mechanics.skill:useMiddleware('after', 1, function(pipeline)
    --> I'll fill this all out soon I just want to push this for the rodev game jam tmr I love this module
end)

mechanics.skill:with() --> Returns a new call
    :intent('use')
    :data('fireball', mousePosition)
    :timeout(4)
    :invoke() --> Returns a promise
        :finally(function(req)
            local intent, data = req.intent, req.data
            local didUse = (data[1]==true)


        end)
        :catch(function(issue)
            warn('Issue with skill: fireball')
            warn(issue)
        end)

--> In ServerScriptService.Mechanics

local networking = sawdust.core.networking
local mechanics = networking.getChannel('mechanics')

mechanics.skill:handle(function(req, res)
    local intent, data = req.intent, req.data

    res.intent('success')
    res.data('Whatever you\'d need')
    res.send() --> Send the data back
end)

Build a Service

--> In ServerScriptService.SawdustServices

local builder = sawdust.builder
local services = sawdust.services

services:register(builder.new('OtherService')
    :init(function(self, deps) --> 'init' runtime phase
        self.data = 'Hello!' --> Set OtherService.data to 'Hello!'
    end)
    :method('methodName', function(msg) --> Create a new method (OtherService.methodName(msg))
        print(`Method was called, message: "{msg}"`)
    end)
    :inject('init', function(self, deps) --> Inject function into 'init' runtime phase
        print('Injection into OtherService success!')
    end))

services:register(builder.new('ExampleService')
    :dependsOn('OtherService') --> Depend on the OtherService
    :init(function(self, deps) --> :init() phase
        self.otherService = deps.OtherService
    end)
    :start(function(self) --> :start() phase
        print(`Data from other service: "{self.otherService.data}"`)
        self.otherService.methodName('I called the function from ExampleService!')
    end))

services:resolveAll() --> :init() all services
services:startAll() --> :start() all services

--[[

    This should print this, in order:
    'Injection into OtherService success!'
    'Data from other service: "Hello!"'
    'Method was called, message: "I called the function from ExampleService!"'

--]]

๐Ÿง  Philosophy

Sawdust is designed to:

  • Give maximum control to the developer
  • Encourage clean runtime logic
  • Reduce boilerplate
  • Promote discoverabiliy via tooling & naming clarity
  • Minimize documentation checks

You get injection + dependency management without losing Luau's flexibility.


๐Ÿšš Installation

  1. Drop the Sawdust folder into ReplicatedStorage
  2. Access it on server or client via:
local sawdust = require(game:GetService('ReplicatedStorage').Sawdust)
  1. Access the implementations like:
local sawdust = require(game:GetService('ReplicatedStorage').Sawdust)

local services = sawdust.services
local networking = sawdust.core.networking
local maid = sawdust.util.maid

๐Ÿงช Tests

I've built unit tests for sawdust and all of the implementations (this may not be ALL implementations at time of reading, I may still be working on some.)

๐Ÿ“– Documentation

You can find full documentation & quick start examples + implementation tutorials Here!


๐Ÿ“š Modules

Services

ModuleDescription
builderService definition w/ injections & dependencies
servicesService resolver, runner, and state tracker

Core

ModuleDescription
networkingNetworking system modeled after NodeJS' Express
promisePromise system modeled after NodeJS
signalSimple event emitter system
cacheFast, structured memory management
cdnAsset delivery w/ preload features

Util

ModuleDescription
maidCleanup utility for tagged objects
debounceTimed and interactable debounces
enum_map"Maps" enums to human readable, and back.
statesSimple dynamic state management
timerHeartbeat wrapper w/ decay and start/stop control
uuidCustomizable UUID generator

๐Ÿ“œ License

Sawdust is licensed under Apache 2.0.
Contributions are welcome! While not required by the license, if you would like to improve Sawdust or find bugs, please consider contributing or filing a issue report, it means a lot more than you think <3

Package Details

Install command (Click to copy)


Version

1.6.0

License

Apache-2.0

check_circle

Safe for commercial use

infoModified files must carry a notice of changes. If the package ships a NOTICE file, its attributions must be preserved.

Automated license review โ€” not legal advice.